Download - Jak włamałem się do banku

Transcript

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