Lekcja 3: Nieprawidłowa kontrola dostępu do funkcji
Wprowadzenie
W tym odcinku "kontrola dostępu" do funkcji, czyli ograniczanie akcji, jakie użytkownik może wykonać w aplikacji. W przykładowej aplikacji dostępnej pod adresem http://bootcamp.threats.pl/lesson03/ dostępna jest lista wiadomości (znana z poprzedniego ćwiczenia), przy czym dla części wiadomości dostępna jest akcja ich usuwania. Akcja ta jest wywołana przez przycisk "Usuń" przy podglądzie wiadomości:
W przypadku wiadomości, do których użytkownik nie ma prawa usuwania, przycisk ten jest nieaktywny:
Założenie jest takie, że skoro użytkownik nie może klikąć przycisku, to nie usunie wiadomości. Błąd! Może to zrobić i to na kilka sposobów.
To użytkownik kontroluje co i jak widzi
Jednym z podstawowych błędów jest założenie, że to co i jak widzi (oraz jakie akcje może wykonać) użytkownik jest kontrolowane przez programistę. To nieprawda. Do wyświetlenia strony wykorzystywana jest bliżej nieokreślona (jest kilka dostępnych) przeglądarka internetowa o nieznanej konfiguracji, w dodatku działająca w środowisku kontrolowanym przez użytkownika. To, że przycisk jest nieaktywny (w zamierzeniu programisty) nie jest zabezpieczeniem. Na początku aktywujemy przycisk "Usuń".
Metoda 1: modyfikacja źródła strony
Pierwsza metoda to modyfikacja źródła strony zwracanej przez serwer. Całość oczywiście wykonana za pomocą narzędzia Fiddler (patrz: Absolutne podstawy). W tym celu wystarczy przechwycić odpowiedź serwera (Rules - Automatic Breakpoints - After Responses) po kliknięciu na link prowadzący do wiadomości, której usunąć nie mamy prawa.
W przechwyconej, zwróconej przez serwer odpowiedzi, wystarczy usunąć atrybut disabled i przycisk służący do usuwania wiadomości stanie się aktywny.

Metoda 2: developers tools
Atrybutami poszczególnych obiektów można również manipulować z poziomu narzędzi developerskich. Dla przykładu włączenie przycisku "Usuń" w Internet Explorer 8 wygląda mniej więcej tak:
- F12,
- Wybrać "strzałkę" (Select Element by Click),
- W oknie przeglądarki kliknąć na nieaktywny przycisk, obiekt zostanie zlokalizowany,
- Wybrać zakładkę "Attributes",
- Usunąć atrybut "disabled",
Przycisk zostaje "magicznie" aktywowany:

Użytkownik wcale nie musi klikać
Jak wygląda request powodujący usunięcie wiadomości:
POST /lesson03/index.php HTTP/1.1
Accept: image/gif, (...)
Referer: http://bootcamp.threats.pl/lesson03/?id=4
Accept-Language: en-US,pl;q=0.5
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; )
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: bootcamp.threats.pl
Content-Length: 13
Connection: Keep-Alive
Pragma: no-cache
Cookie: PHPSESSID=ebb3d995665519c6625d10ff670f1028
action=delete
Jak widać request jest realizowany przy pomocy metody POST a jedynym przesyłanym parametrem jest parametr action o wartościdelete. Oznacza to, że usuwana jest ta wiadomość, która aktualnie jest wyświetlana, jej identyfikator jest zapisany w sesji.
Czy przejdzie GET
Aktywacja przycisku "Usuń" była konieczna, by użytkownik mógł kliknąć w aktywny przycisk i wygenerować za pośrednictwem przeglądarki stosowny request. Pytanie - czy request ten musi być wykonany przy pomocy metody POST? Wystarczy prosty test, po wejściu na wybraną wiadomość sprawdzić działanie URLa: http://bootcamp.threats.pl/lesson03/index.php?action=delete. Jak widać parametr action został przeniesiony do adresu. Po sprawdzeniu okazuje się, że parametr ten może równie dobrze zostać wywołany przez metodę GET, nie trzeba więc aktywować przycisku, lub w inny sposób fałszować żądania HTTP. Wynika to wprost z faktu, że parametr action odczytywany jest przez $_REQUEST, a nie $_POST.
Fałszowanie żądania
Nawet jeśli wykorzystany zostałby $_POST, nie zmienia to w żaden sposób sytuacji (patrz aktywowanie przycisku). Można też stosowne żądanie wykonać ponownie, na przykład za pomocą Fiddlera. Wystarczy:
- otworzyć wiadomość, do której mamy prawa usuwania,
- usunąć wiadomość,
- otworzyć wiadomość, do której nie mamy prawa usuwania (trzeba załadować do sesji jej identyfikator),
- kliknąć prawym klawiszem na sesję, w której usuwana była poprzednia wiadomość i wybrać Replay - Reisue Request,
Jak widać żądnanie HTTP zostało odtworzone przez Fiddler i wybrana wiadomość zostaje usunięta: