Race Condition plus LFI dla serwerów Windows i PHP

Zacznijmy od początku, atak Race Condition polega na wykonaniu złośliwej akcji przed warunkiem sprawdzającym jej poprawność (np. pod kątem bezpieczeństwa). Załóżmy, że istnieje aplikacja bankowa, która pozwala na wykonanie przelewu.

Ustalmy, że posiadamy na koncie 1000 PLN, wykonując pojedynczy przelew na taką kwotę, kolejny nie powinien się udać, ponieważ system zwróci nam informację o braku środków.

Załóżmy teraz, że testowany system jest wadliwy i czas w jakim przelew zostaje wykonany (w jakim nasze saldo zostaje pomniejszone) jest wystarczająco długi, aby w tym samym momencie wykonać drugi raz tę samą operację.
Co się wówczas stanie?
– Aplikacja wykona dwa przelewy na kwotę 1000 PLN, ponieważ zanim operacja pierwsza pomniejszy saldo konta, operacja druga zweryfikuje, że nadal posiadamy dodatnie saldo.
Tego typu ataki, tyczą się wielu różnych aspektów, od wgrywania plików po właśnie salda bankowe (niestety).

LFI drugi niezbędny element, dla jasności tego tekstu – jest to atak polegający na załadowaniu lokalnego zasobu na testowanym serwerze, w formie wykonywanego kodu.
Przykładem może być strona oparta o treści ładowane z innych plików, za pomocą zmiennej metody GET.
Załóżmy że istnieje adres: /strona.php?plik=kontakt.php
Jak łatwo się domyślić powyższy skrypt, ładuje nam treść pliku kontakt.php.
Ważne, aby atak LFI mógł zaistnieć – pliki muszą być ładowane w postaci parsowanego kodu, w przeciwnym wypadku, gdy zawartość pliku jest po prostu wyświetlana atak się nie powiedzie (jest to wówczas AFD – Arbitrary File Download).

Najbardziej szkodliwym dla serwera może być atak LFI, który załaduje plik z shellem atakującego np. wgrany jako avatar użytkownika, czy inne tego typu.

Problemy PHP

Specyficzny język jakim jest PHP, pozwala na wiele zależności, wpływających na stabilność aplikacji napisanych właśnie w nim. Przykładem takiego zachowania jest wykorzystanie ataku LFI w celu wywołania błędu w skrypcie, który spowoduje zatrzymanie aktualnego stanu plików tymczasowych.

Ponownie załóżmy, że istnieje adres: /strona.php?plik=kontakt.php
Jeżeli skrypt jest podatny zmodyfikujmy zapytanie na następujące: /strona.php?plik=strona.php

W tej sytuacji aplikacja powinna się zapętlić rekurencyjnie ładując ten sam zasób jakim jest plik strona.php. Gdzie tutaj są pliki tymczasowe, co ma zostać zatrzymane?
Ostatecznie strona się zatrzyma z błędem, jeżeli chodzi o pliki tymczasowe, to gdyby zapytanie przybrało inną formę niż metoda GET, Np. POST z uploadem pliku (multipart/form-data) – to wgrywany zasób do folderu tymczasowego, nie zniknie po wykonaniu skryptu – ponieważ skrypt nie wykona się do końca (zwróci błąd).

Problemy serwerów Windows

Problem, bądź ułatwienie  – w zależności od punktu widzenia czy wykorzystania. Parser PHP dla Windows, pozwala na ładowanie pliku na podstawie jego początku nazwy i jeżeli nie istnieje więcej plików w danym katalogu o takim unikalnym początku nazwy to jego resztę można zastąpić znakiem mniejszości „<”.

Jeszcze raz załóżmy, że istnieje adres: /strona.php?plik=kontakt.php
W przypadku serwerów na Windows można go zamienić na: /strona.php?plik=kontakt<

Efekt wykonania skryptu będzie identyczny.

Podsumowanie

Łącząc wszystkie powyższe zależności jesteśmy w stanie wykonać atak PHP Code Injection (lub RCE, w zależności od konfiguracji serwera).

Krok 1. Przygotowujemy skrypt, który będzie wysyłać nasz złośliwy shell na serwer, poprzez zapętlone zapytanie z LFI.

Skrypt wysyła plik pod adres /strona.php?plik=strona.php – co spowoduje zapętlenie się skryptu i zachowanie wgrywanego pliku w folderze TMP (póki co nie znamy jego nazwy, wiemy jednak, że PHP używa swoistego nazewnictwa plików tymczasowych (załóżmy, że katalogiem tymczasowym na serwerze będzie C:/Windows/tmp). Stworzony plik tymczasowy będzie mieć następującą lokalizację:
C:/Windows/tmp/php123456

Gdzie „123456” to alfanumeryczna losowa kombinacja.

Krok 2. Ten sam skrypt należy udoskonalić o weryfikację, czy wysłany skrypt shella, istnieje – oraz czy można go uruchomić.

Logicznym wydaje się aby spróbować sprawdzić pod adresem: /strona.php?plik=C:/Windows/tmp/php123456

Jednak szansa, że zgadniemy nazwę pliku jest bardzo nikła. Z pomocą przychodzą wątki, warto nasz skrypt zaopatrzyć  w wielowątkowe powtarzanie kroku pierwszego, oraz wielowątkowe sprawdzanie czy plik istnieje.

Krok 3. Udoskonalenie skryptu, aby ten szybciej odnalazł naszego shella na serwerze. Tutaj z pomocą pojawia się udogodnienie/podatność serwerów na Windows. Tworząc odpowiednią ilość plików tymczasowych, możemy z powodzeniem spróbować wykonać atak LFI na pliku z użyciem znaku mniejszości.

Załóżmy, że na serwerze ostatecznie powstał plik:

C:/Windows/tmp/phpb3Da81

Niech zatem skrypt zweryfikuje czy shell istnieje pod adresem:

/strona.php?plik=C:/Windows/tmp/phpb<

Udało się! Shell uruchomiony, mamy pełen dostęp do serwera.

Zauważmy, że dzięki wykorzystaniu funkcjonalności dostępnej na serwerach Windows, wystarczyło odgadnąć/iterować jeden znak, aby uzyskać dostęp do nieznanej nam nazwy pliku – co przyspieszyło atak kilkanaście, o ile nie kilkaset razy.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *