usunięcie dowolnego pliku
| Po angielsku | arbitrary file deletion |
|---|---|
| Którą formą pisać | po polsku Polska nazwa przyjęła się w tekstach i w wyszukiwarce — używaj jej samodzielnie. |
| Inne formy | usuwanie dowolnych plików · kasowanie dowolnych plików na serwerze |
| Kategoria | Podatności i klasy błędów |
Usunięcie dowolnego pliku to podatność, która pozwala atakującemu skasować na serwerze plik przez niego wskazany, a nie tylko plik, który aplikacja zamierzała usunąć. Najczęściej wynika z path traversal: aplikacja buduje ścieżkę z danych zewnętrznych i nie neutralizuje elementów, które wyprowadzają ją poza dozwolony katalog [1]. MITRE wymienia wśród skutków takiego błędu możliwość nadpisania, usunięcia albo uszkodzenia krytycznych plików, co może całkowicie unieruchomić aplikację [1]. W WordPressie usunięcie jednego pliku konfiguracyjnego potrafi otworzyć drogę do przejęcia całej witryny [2].
Jak działa
Mechanizm jest prosty. Aplikacja ma funkcję, która legalnie usuwa pliki: miniatury po skasowaniu załącznika, pliki tymczasowe, stare eksporty albo kopie. Nazwa lub ścieżka pliku pochodzi z danych, na które użytkownik ma wpływ, na przykład z parametru żądania albo z metadanych zapisanych wcześniej w bazie. Jeśli kod przekazuje tę ścieżkę do funkcji usuwającej bez sprawdzenia, sekwencja „../” przenosi operację poza katalog, dla którego ją zaprojektowano.
Groźniejszy wariant jest dwuetapowy. Atakujący najpierw zapisuje spreparowaną ścieżkę tam, gdzie aplikacja jej nie sprawdza, a potem wywołuje zwykłą, uprawnioną akcję, która tę ścieżkę odczytuje i usuwa wskazany plik. Tak działał błąd w rdzeniu WordPressa opisany niżej, co pokazuje schemat poniżej.
Odmiany
Źródłem błędu nie zawsze jest parametr żądania. Sekurak opisał, jak PHP object injection prowadzi do tego samego skutku: aplikacja z klasą rejestrującą logi, która przyjmuje do deserializacji dane z niezaufanych źródeł, staje się podatna na usuwanie dowolnych plików na serwerze [6]. Destruktor obiektu usuwa plik, a atakujący podmienia w zserializowanym obiekcie jego ścieżkę [6]. Szerzej opisuje to hasło deserializacja niezaufanych danych (insecure deserialization).
| Źródło ścieżki | Przykład | Wymagany dostęp |
|---|---|---|
| parametr żądania | nazwa pliku do skasowania w akcji AJAX | zależnie od kontroli uprawnień |
| metadane w bazie | miniatura załącznika w WordPressie do 4.9.6 [2] | rola Autor [4] |
| zserializowany obiekt | ścieżka w obiekcie niszczonym przez destruktor [6] | zależnie od miejsca deserializacji |
Brak weryfikacji uprawnień w funkcji usuwającej sprawia, że nawet błąd wymagający konta może stać się podatnością wykorzystywaną bez uwierzytelnienia.
W WordPressie
W WordPressie klasa ta dotyczy głównie wtyczek: menedżerów plików, narzędzi do kopii, importerów i formularzy z załącznikami. To typowa podatność we wtyczce. Skutki zależą od tego, który plik zniknie [2].
- wp-config.php — WordPress bez pliku konfiguracyjnego uruchamia kreator instalacji. Atakujący wskazuje w nim własną bazę danych i zakłada w niej konto administratora [2], co jest odmianą, którą opisuje hasło nieautoryzowane konto administratora. Z panelu administratora droga do zdalnego wykonania kodu (RCE) jest już krótka [2].
- .htaccess — usunięcie znosi reguły ochrony katalogów [2], opisane w haśle zabezpieczenia w .htaccess.
- index.php w katalogach — usunięcie odsłania zawartość katalogów [2].
Od wersji 4.9.7 rdzeń ma funkcję wp_delete_file_from_directory(), która usuwa plik tylko wtedy, gdy jego ścieżka leży w podanym katalogu [5]. Kod wtyczki, który kasuje pliki, powinien z niej korzystać.
// usuwaj tylko w obrębie katalogu uploads
$uploads = wp_get_upload_dir();
wp_delete_file_from_directory( $path, $uploads['basedir'] );
Zagrożenia i skutki
Najłagodniejszym skutkiem jest odmowa usługi (denial of service): usunięcie pliku rdzenia, motywu albo biblioteki unieruchamia stronę, co MITRE wymienia wprost jako skutek path traversal [1]. Poważniejsze jest wyłączenie zabezpieczeń przez skasowanie plików, które je realizują. Najpoważniejsze jest przejęcie witryny przez ponowną instalację, opisane wyżej.
Usuwanie bywa też sposobem zacierania śladów: skasowanie logów lub plików potrzebnych do analizy utrudnia ustalenie przebiegu incydentu.
Klasa ta jest bliska wgraniu dowolnego pliku (arbitrary file upload). Obie wynikają z tego, że operacja na systemie plików ufa ścieżce lub nazwie podanej z zewnątrz. Różni je kierunek: wgranie dodaje do serwera kod atakującego, usunięcie odbiera serwerowi plik, od którego zależy jego konfiguracja albo ochrona. W obu przypadkach ocena wagi zależy od tego, jakie konto jest potrzebne i czy ścieżka jest ograniczona do jednego katalogu.
Jak się bronić
MITRE zaleca sprowadzenie ścieżki do postaci kanonicznej, w PHP funkcją realpath(), przed jej użyciem, oraz walidację nazw plików według listy dozwolonych wartości zamiast listy zakazanych znaków [1]. W WordPressie odpowiada temu wp_delete_file_from_directory() [5] i sanityzacja danych wejściowych nazw plików. Tymczasowa poprawka zaproponowana przez badaczy dla błędu w rdzeniu używała basename(), by usunąć z nazwy miniatury elementy ścieżki [2].
Poza kodem ograniczają skutki:
- aktualizacja rdzenia WordPressa i wtyczek, bo poprawki tej klasy trafiają do kolejnych wydań;
- uprawnienia plików, przy których proces serwera WWW nie może zapisywać ani usuwać plików rdzenia i konfiguracji;
- utwardzanie pliku wp-config.php, w tym przeniesienie pliku poziom wyżej;
- monitorowanie integralności plików, które wykrywa zniknięcie pliku;
- kopia zapasowa (backup) pozwalająca odtworzyć usunięte pliki.
Historia i przykłady
Badacze RIPS Technologies zgłosili zespołowi WordPressa 20 listopada 2017 roku błąd, który pozwalał użytkownikowi z uprawnieniami Autora usuwać dowolne pliki [2]. Wartość thumb z metadanych załącznika trafiała bez walidacji do funkcji unlink() w wp_delete_attachment() [2]. Rekord CVE-2018-12895 opisuje go jako błąd w WordPressie do wersji 4.9.6, pozwalający Autorom wykonać dowolny kod przez przejście katalogów w parametrze thumb i usunięcie pliku wp-config.php [4].
WordPress 4.9.7, wydany 5 lipca 2018 roku, naprawił problem z mediami, który mógł pozwolić użytkownikowi z określonymi uprawnieniami na próbę usunięcia plików poza katalogiem uploads [3]. Poprawka ukazała się ponad siedem miesięcy po zgłoszeniu [2].
Przypisy
6- [1] CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') · MITRE
- [2] WordPress File Delete to Code Execution · SonarSource (dawniej RIPS Technologies)
- [3] WordPress 4.9.7 Security and Maintenance Release · WordPress.org
- [4] CVE-2018-12895 — rekord CVE · CVE Program (MITRE)
- [5] wp_delete_file_from_directory() — Code Reference · WordPress.org
- [6] PHP Object Injection – mało znana, krytyczna klasa podatności · Sekurak
Hasła w tym artykule
18- podatność
- path traversal
- PHP object injection
- deserializacja niezaufanych danych (insecure deserialization)
- weryfikacja uprawnień
- podatność wykorzystywana bez uwierzytelnienia
- podatność we wtyczce
- nieautoryzowane konto administratora
- zdalne wykonanie kodu (RCE)
- zabezpieczenia w .htaccess
- atak odmowy usługi
- wgranie dowolnego pliku (arbitrary file upload)
- sanityzacja danych wejściowych
- aktualizacja rdzenia WordPressa
- uprawnienia plików
- utwardzanie pliku wp-config.php
- monitorowanie integralności plików
- kopia zapasowa