Problem
Jeśli w roli mechanizmu skryptów po stronie serwera jest wykorzystywany język PHP (PHP Hypertext Processor), to w przypadku, gdy projektant aplikacji nie zastosuje odpowiednich środków ostrożności, napastnik może przeprowadzić kilka typów ataków. Szczególnie groźne jest wstrzykiwanie kodu w instrukcji włączania skryptów PHP, gdzie napastnik może wymusić na serwerze WWW pobranie i uruchomienie dowolnego kodu. W tej recepturze spróbujemy sprawdzić, czy aplikacja napisana w PHP pobierze dowolny kod określony przez napastnika i go uruchomi.
Najpierw sprawdzimy, czy aplikacja korzysta z PHP. Jednym ze wskaźników są adresy URL, które odwołują się do zasobów z rozszerzeniami .php, .php3 lub .php4, na przykład: http ://www.example.com/home.php?display=5. Jeśli nie jest jasne, czy aplikacja korzysta z PHP, należy o to zapytać członków zespołu projektowego.
Następnie konfigurujemy gdzieś serwer WWW, postępując zgodnie z recepturą 2.14. Po wykonaniu tych czynności możemy wstrzyknąć kod zamieszczony w listingu 12.15 za pomocą wartości parametrów GET i POST lub wartości plików cookie.
Listing 12.15. Testowanie podatności aplikacji na wstrzykiwanie kodu w instrukcji włączania skryptów PHP
http://host:port/xyzzy_php_test
Parametr host oznacza nazwę hosta lub adres IP skonfigurowanego serwera WWW, natomiast port to numer portu, na którym nasłuchuje serwer WWW. Po wypróbowaniu powyższego adresu URL należy przeszukać pliki dziennika dostępu i dziennika błędów na hoście host, sprawdzając, czy jest tam ciąg znaków xyzzy_php_test. Jeśli w plikach dzienników można znaleźć taki ciąg, oznacza to, że testowana strona próbuje pobrać plik z serwera WWW i jest wrażliwa na wstrzykiwanie kodu w instrukcji włączania skryptów PHP.
DYSKUSJA
Pokazany atak działa, ponieważ funkcje PHP include() i require() pozwalają na czytanie plików zarówno z lokalnego systemu plików, jak i lokalizacji zdalnej. Jeśli w aplikacji istnieje kod PHP, który pobiera od użytkownika zmienne dane wejściowe, a następnie przekazuje je do funkcji include() lub require() tak jak na poniższym listingu, to użytkownik może manipulować zmiennymi w sposób, którego nie przewidzieli projektanci aplikacji. W listingu 12.16 pokazano wiersz kodu PHP, który jest wrażliwy na tego typu atak, w przypadku, gdyby zmienna SuserInput nie została poddana odpowiednim zabiegom unieszkodliwiającym przed wywołaniem funkcji require().
Listing 12.16. Przykładowy wiersz kodu aplikacji wrażliwej na wstrzykiwanie kodu w instrukcji włączania skryptów PHP
require(SdaneUzytkownika . '.php')
Programista może próbować wprowadzać ograniczenia dla zmiennej SuserInput na przykład za pomocą przełączników na stronie HTTP, ale można przecież pominąć kontrolki po stronie klienta i wprowadzić dowolne dane. Jeśli napastnik poda ciąg z punktu „Rozwiązanie" jako wartość zmiennej SuserInput, to kod podejmie próbę pobrania pliku http://host:port/xyzzy_ php_test.php i uruchomi kod PHP z pobranego pliku.
Należy zwrócić uwagę, że kod PHP może pobierać wartości zmiennych GET lub POST, lub nawet wartości HTTP cookie i wykorzystywać je w sposób opisany wcześniej. Modyfikowanie wartości GET można osiągnąć poprzez zwykłe modyfikowanie adresu URL.