Na tropie błędów. Przewodnik hakerski. Peter Yaworski
Читать онлайн книгу.tylko bank akceptowałby ostatni parametr from, który otrzymał. Zamiast wysyłać 5000 $ z konta 12345 na 67890, kod serwera użyłby drugiego parametru i wysłał pieniądze z konta ABCDEF na 67890.
Kiedy serwer dostaje kilkukrotne parametry z tą samą nazwą, może odpowiedzieć na wiele sposobów. Na przykład PHP i Apache używają ostatniego wystąpienia, Apache Tomcat używa pierwszego, ASP i IIS używają wszystkich i tak dalej. Dwóch badaczy, Luca Carettoni i Stefano di Paola, udostępnili dokładną prezentację wielu różnic między technologiami serwerów podczas konferencji AppSec EU 09; informacja ta jest teraz dostępna na stronie OWASP na https://www.owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf (zob. slajd 9). W wyniku tego nie ma jednego gwarantowanego procesu do obsługi wielokrotnych parametrów z tą samą nazwą, więc znalezienie podatności HPP wymaga nieco kombinowania, by przekonać się o tym, jak działa strona, którą sprawdzasz.
Przykład z bankiem używa parametrów, które są oczywiste. Czasami jednak podatności HPP objawiają się jako rezultat ukrytego zachowania po stronie serwera, wynikającego z kodu, który nie jest bezpośrednio widoczny. Powiedzmy na przykład, że Twój bank zadecydował ulepszyć sposób, w jaki przetwarza przelewy, i zmienia kod w backendzie tak, aby nie używał parametru from z URL-a. Tym razem bank użyje dwóch parametrów, jednego do konta, na które ma zostać wykonany przelew, a drugiego do kwoty do przelania. Przykładowy link mógłby wyglądać tak:
https://www.bank.com/transfer?to=67890&amount=5000
Zazwyczaj kod na serwerze byłby dla nas zagadką, lecz ze względu na potrzeby tego przykładu wiemy, że kod Ruby serwera (nadzwyczaj brzydki i bezużyteczny) wygląda następująco:
user.account = 12345
def prepare_transfer(
params)params << user.account
transfer_money(params) #user.account (12345) becomes params[2]
end
def transfer_money(params)
to = params[0]
amount = params[1]
from = params[2]
transfer(to,amount,from)
end
Ten kod tworzy dwie funkcje, prepare_transfer i transfer_money. Funkcja prepare_transfer używa tablicy o nazwie params
, która zawiera parametry to i amount pochodzące z URL-a. Tablicę stanowiłoby [67890,5000], gdzie jej wartości są wciśnięte między nawiasy, a każda wartość jest oddzielona przecinkiem. Pierwsza linia funkcji dodaje informacje o koncie użytkownika, które zostały zdefiniowane wcześniej w kodzie, na końcu tablicy. Dostajemy zatem tablicę params [67890,5000,12345], która następnie jest przekazana do transfer_money . Zauważ to, że w odróżnieniu od parametrów tablice nie mają nazw powiązanych z ich wartościami, więc kod podlega tablicy zawierającej zawsze każdą wartość w następującej kolejności: konto odbiorcy jako pierwsze, kwota przelewu druga i konto, z którego wychodzi przelew, jako następne. W transfer_money kolejność wartości staje się oczywista z racji, że funkcja przypisuje każdą wartość tablicy do zmiennej. Ze względu na to, że tablice są numerowane od 0, params[0] przyjmuje pierwszą wartość w tablicy, którą w tym przypadku jest 67890 i przypisuje ją do zmiennej to . Pozostałe wartości są również przypisywane zmiennym w wierszach i . Wtedy nazwy zmiennych są przekazane do funkcji transfer, niepokazanej w tym fragmencie, która przyjmuje wartości i wykonuje przelew.W najlepszej sytuacji parametry URL byłyby zawsze formatowane w sposób, jakiego kod oczekuje. Jednakże atakujący mógłby zmienić wynik tego procesu przez podanie w from wartości dla params, tak jak z następującym URL-em:
https://www.bank.com/transfer?to=67890&amount=5000&from=ABCDEF
W tej sytuacji parametr from jest również włączony do tablicy params przekazanej funkcji prepare_transfer; co za tym idzie, wartościami tablicy mogłyby być [67890,5000,ABCDEF], a podanie konta użytkownika w
dawałoby rezultat w postaci [67890,5000,ABCDEF,12345]. W wyniku tego w funkcji transfer_money wywołanej w prepare_tranfer wartość from stałaby się trzecim parametrem, zamieniając oczekiwaną wartość 12345 na wartość atakującego ABCDEF .HPP po stronie klienta
Podatności HPP po stronie klienta pozwalają atakującym na wstrzyknięcie dodatkowych parametrów do adresu URL, w celu wywołania efektów po stronie użytkownika (strona klienta jest częstym sposobem odnoszenia się do akcji, które dzieją się na twoim komputerze, często przez przeglądarkę, a nie po stronie serwera).
Luca Carettoni i Stefano di Paola w swojej prezentacji zamieścili przykład tego zachowania, używając wymyślonego adresu URL http://host/page.php?par=123%26action=edit i następującego kodu na serwerze:
<? $val=htmlspecialchars($_GET['par'],ENT_QUOTES); ?>
<a href="/page.php?action=view&par='.<?=$val?>.'">View Me!</a>
Ten kod generuje nowy adres URL, bazując na wartości par parametru wpisanego przez użytkownika. W tym przykładzie atakujący przekazuje wartość 123%26action=edit jako wartość dla par w celu wygenerowania dodatkowego, nieoczekiwanego parametru. Wartością dla & zakodowaną przez URL jest %26, co oznacza, że kiedy URL jest przetwarzany, %26 jest interpretowane jako &. Ta wartość dodaje dodatkowy parametr do wygenerowanego href-a, bez sprecyzowania parametru w URL-u. Używając parametru 123&action=edit zamiast %26, & byłoby zinterpretowane jako oddzielenie dwóch parametrów, lecz ze względu na to, że strona używa tylko jednego parametru par w swoim kodzie, parametr action zostałby usunięty. Wartość %26 omija ten problem, zapewniając, że akcja nie jest rozpoznawana jako osobny parametr, a więc 123%26action=edit staje się wartością par.
Następnie par (z zakodowanym & jako %26) jest przekazany do funkcji htmlspecialchars
. Funkcja htmlspecialchars konwertuje znaki specjalne, takie jak %26, do ich zakodowanych w HTML-u wartości, zamieniając %26 na & (jednostka w HTML-u, która reprezentuje &), gdzie ten znak może mieć specjalne znaczenie. Zmieniona wartość jest następnie przechowywana w $val. W następnej kolejności generowany jest nowy link przez dodanie $val do wartości href w . Zatem wygenerowany link to <a href="/page.php?action=view&par=123&action=edit">. W konsekwencji atakujący zdołał dodać nieoczekiwany action=edit do URL-a href, który mógłby doprowadzić do podatności w zależności od tego, jak aplikacja traktuje przemycony parametr action.Następne 3 przykłady wyjaśniają szczegółowo oba błędy HPP, zarówno po stronie serwera, jak i klienta, znalezione na HackerOne i Twitterze. Wszystkie z tych przykładów wymagają manipulowania parametrami URL. Miej na uwadze fakt, że żaden z przykładów