Dzisiaj komentarz do tego tematu: Okradli klientów PKO BP, przez internet, bez znajomości kodów jednorazowych. Właściwie do pewnego stopnia mój komentarz jest tutaj, ale tematowi warto poświęcić kilka słów więcej.
(nie)błąd
Pierwsze podstawowe stwierdzenie: nie ma błędu w serwisie PKO - funkcja działa dokładnie tak jak powinna. Albo dokładniej - działa dokładnie tak, jak została wyspecyfikowana. Cała sytuacja natomiast jest doskonałym przykładem potwierdzającym, że mechanizm (bezpieczeństwa), które użytkownik nie rozumie, nie ma prawa działać.
Będę pisał ogólnie bez pokazywania, w których bankowościach konkretne rozwiązanie jest zastosowane. Jeśli ktoś jest ciekawy - sam może sprawdzić w banku, z którego korzysta.
O co właściwie chodzi? Chodzi o to, że ktoś uzyskał dostęp do cudzego konta w systemie (możliwość logowania), ale bez możliwości autoryzacji przelewu. Mimo tego był w stanie dokonać takich zmian, w wyniku których ofiara sama przelała na konto atakującego sporą kwotę pieniędzy.
Jak atakujący osiągnął swój cel? Jaki błąd w systemie wykorzystał? No cóż, będę uparcie twierdził, że atakujący nie wykorzystał żadnego błędu w systemie, bo takiego błędu nie było. Przy czym od razu zaznaczam, że przez błąd w systemie rozumiem sytuację, w której ktoś może wykorzystać system w sposób niezgodny z jego specyfikacją. Czyli jeśli na przykład jestem w stanie pominąć krok autoryzacji transakcji (choć jest on wymagany), jest to błąd. Jeśli jednak autoryzacja transakcji nie jest wymagana na przelew do kwoty 10 PLN, to wykorzystanie tej funkcji nie jest błędem w systemie. Nie jest błędem w systemie również wykorzystanie tej funkcji wielokrotnie przez co wyprowadzona kwota może być dużo większa niż te 10 PLN, chyba że według specyfikacji taki przelew można na przykład wykonać jedynie pewną ilość razy, a atakujący znajduje sposób na obejście tego limitu.
W tym konkretnym przypadku nieszczęsną funkcją są odbiorcy/przelewy zdefiniowane (znane również jako szablony przelewów). W przypadku większości rozwiązań są dwa typy takich szablonów:
- niezaufane (zwykłe),
- zaufane,
W przypadku przelewu (szablonu) zaufanego wykonanie przelewu w oparciu o taki szablon (przelewu do takiego odbiorcy) nie wymaga dodatkowej autoryzacji. Po prostu w chwili definiowania przelewu jego (istotne) parametry są autoryzowane. Następnie każda zmiana tych istotnych parametrów wymaga autoryzacji. Użytkownik może być pewny, że operacja wykonywana z użyciem zaufanego szablonu jest dokładnie tą operacją, która została zdefiniowana (autoryzowana) przy jego tworzeniu. Każda zmiana istotnych parametrów (czyli przede wszystkim - numeru docelowego konta) wymaga ponownej autoryzacji.
Jeśli ktoś jest w stanie znaleźć możliwość modyfikacji zaufanego przelewu zdefiniowanego bez autoryzacji zmiany - jest błąd w systemie. Tak samo, jeśli ktoś może zmodyfikować parametry przelewu wykonywanego w oparciu o zaufany przelew zdefiniowany. I tak, bywają błędy w implementacji, które osiągnięcie tego celu umożliwiają.
Inaczej przedstawia się sytuacja w przypadku niezaufanego przelewu zdefiniowanego. W tym przypadku założenie jest takie, że skoro przelew tworzony w oparciu o taki szablon jest autoryzowany, to użytkownik powinien zweryfikować parametry autoryzowanej transakcji dokładnie w taki sam sposób, jak powinien to zrobić wtedy, gdy tworzy przelew "z ręki". W takim scenariuszu sam przelew zdefiniowany nie jest "obiektem chronionym" i zmiany tego szablonu przelewu nie wymagają dodatkowej autoryzacji.
No i właśnie dochodzimy do sedna problemu - mamy dwa różne typy czegoś, co dla przeciętnego użytkownika jest po prostu "przelewem zdefiniowanym". Dwa typy, które zachowują się w nieco odmienny sposób, w zależności od wybranych opcji (czyli od typu przelewu). I tego rozróżnienia przeciętny użytkownik nie dostrzega i nie rozumie. A skoro nie rozumie, to nie ma świadomości, że dla pewnych scenariuszy użycia powinien zachować "szczególną ostrożność".
Niewątpliwym błędem byłaby sytuacja, w której użytkownik (atakujący) jest w stanie modyfikować parametry cudzych przelewów niezaufanych. Najczęściej ten błąd wynika z użycia identyfikatorów globalnych - atakujący manipulując identyfikatorem przelewu może zmodyfikować obiekt (przelew), który nie należy do niego. W OWASP Top10 jest to po prostu A4 - Insecure Direct Object References. Błąd trywialny (do wykorzystania i znalezienia) i powszechny - ale czasem płacą za niego 20.000$ (Szok!).
Wróćmy do naszych nieszczęsnych przelewów (szablonów) zdefiniowanych. W opisywanej sytuacji nie ma błędu technicznego, jest natomiast błąd założeń/oczekiwań(?). Przeciętny użytkownik ufa przelewowi, który sam wprowadził - zarówno w przelewie "jednorazowym", jak i przelewie zdefiniowanym. Nie weryfikuje parametrów przelewu otrzymanych w kodzie SMS, bo przecież sam te parametry dopiero co wpisał i widzi na ekranie, że są poprawne. Albo skopiował te parametry ze strony/maila/notatki, więc na pewno są dobre. W przypadku przelewu zdefiniowanego ta wiara jest jeszcze mocniejsza - z tego szablonu korzystał wielokrotnie, nigdy nie było problemów i pieniądze trafiały do właściwego odbiorcy, dlaczego więc tym razem miałoby być inaczej?
No to kilka możliwości dlaczego miałoby być inaczej.
- Dla przelewu "jednorazowego":
- malware na stacji podmienia zawartość schowka modyfikując numer konta,
- malware na stacji podmienia parametry przelewu przy wysyłaniu go na serwer,
- Dla przelewu zdefiniowanego:
- malware na stacji podmienia zawartość schowka modyfikując numer konta,
- malware na stacji podmienia parametry przelewu przy wysyłaniu go na serwer,
- istnieje błąd w systemie pozwalający na modyfikację cudzych przelewów zdefiniowanych,
- ktoś uzyskał dane logowania do konta ofiary i parametry przelewów/odbiorców zostały zmodyfikowane,
Przy projektowaniu mechanizmów bezpieczeństwa należy pamiętać kto z nich korzysta - człowiek. Jeśli system ma być wykorzystany masowo, a tak jest w przypadku systemów bankowości internetowej, można spodziewać się, że świadomość przeciętnego użytkownika nie będzie zbyt wysoka. Dlatego system (i mechanizm bezpieczeństwa) powinien być prosty i zrozumiały, a ilość miejsc, w których coś może pójść nie tak - zminimalizowana. Jednym z miejsc, gdzie coś może pójść nie tak, jest każda interakcja z użytkownikiem, w trakcie której użytkownik ma podjąć decyzję. Nie da się usunąć czynnika ludzkiego, nadal niektóre decyzje muszą być podejmowane przez człowieka (użytkownika), ale warto minimalizować ten udział wszędzie tam, gdzie to jest możliwe.
Coraz mocniej jestem przekonany, że mechanizmy bezpieczeństwa powinny być testowane pod względem ich użyteczności (usability). Zresztą badań w tym zakresie jest coraz więcej. Ogólnie - to mechanizmy bezpieczeństwa powinny być dostosowane do sposobu działania człowieka. Nie można oczekiwać, że człowiek dostosuje się do mechanizmu (oczekiwań projektanta). Zawsze będzie potrzebny jakiś kompromis, ale wynikowe rozwiązanie powinno być dla użytkownika intuicyjne i zrozumiałe.
Super
W przypadku zaufanego przelewu zdefiniowanego autoryzacja ma miejsce w chwili tworzenia przelewu. Potem ten przelew można już wykonać bez autoryzacji, ale nie można zmodyfikować istotnych parametrów przelewu (numeru konta docelowego).
Dla przelewu niezaufanego autoryzacja (i weryfikacja jego parametrów) powinna odbyć się w chwili wysyłania przelewu opartego o taki szablon. Krok autoryzacji jest, natomiast problem polega na tym, że użytkownik nie weryfikuje parametrów takiej operacji, bo "wierzy", że jest to wciąż ta operacja, którą ona sam wprowadził, i z której być może już wielokrotnie wcześniej korzystał.
Uzytkownik powinien sie kierowac prosta zasada. Do zezwolenia na wyjscie pieniedzy z konta potrzebny jest kod sms/jednorazowy i to jest kluczowy punkt całego systemu. Nalezy wszystko zweryfikowac przy podawaniu kodu bo ten kod "robi wszystko". Jezeli za kazdym razem, gdy `przetwarza` kod wszystko dokladnie sprawdzi to potem moze robic co chce, bo pieniadze nie wyjda w nieznane rece (najwyzej zaplaci rachunki za prad na zapas
Niestety zyjemy w czasach gdy media podlapia wszystko, a ludzie sa na tyle bezczelni, ze nie potrafia sie przyznac do bledu.
To zdanie potwierdza tezę, że wszelkie aplikacje powinny być "idiotoodporne", niemalże za rączkę prowadzić użytkowników i ostrzegać na każdym kroku. Jeszcze trochę i do każdej aplikacji producenci będą zmuszeni prawnie dołączać ulotki jak do każdego lekarstwa, żeby nie ponosić odpowiedzialności za błędy użytkowników.
Ogólnie POLA: http://en.wikipedia.org/wiki/Principle_of_least_astonishment