Co robi programista, któremu nie odpowiada działanie tokenu bezpieczeństwa, dostarczanego przez bank? Analizuje algorytm generowania kodów jednorazowych i implementuje go na swoim Arduino, po czym wszystko opisuje na blogu.
Thiago Valverde miał już dosyć ciągłego aktywowania aplikacji na Androida, służącej do generowania kodów jednorazowych. Za każdym razem, kiedy zmieniał ROM lub telefon, musiał telefonicznie aktywować otrzymaną od banku aplikację. Próbował przenosić ją między urządzeniami za pomocą Titanium Backup, ale z nieznanych mu wówczas powodów proces ten się nie udawał. Postanowił zatem rozgryźć algorytm tworzenia kodów i zaimplementować go własnoręcznie.
Przygotowania
Token miał formę aplikacji dla platformy Android, zatem analizę należało zacząć od pozyskania pliku APK. Do tego celu posłużyło narzędzie adb z pakietu Android SDK. Najpierw trzeba było znaleźć nazwę pakietu, potem ścieżkę do pliku a w końcu pobrać samą aplikację.
$ ./adb shell pm list packages | grep mybank $ ./adb shell pm path com.mybank $ ./adb pull /data/app/com.mybank-1.apk
Kolejnym etapem jest rozpakowanie pliku APK (to zwykłe archiwum ZIP, tylko ze zmienionym rozszerzeniem) oraz konwersja androidowego kodu Dalvik do formatu JAR.
$ unzip com.mybank-1.apk $ mv classes.dex com.mybank-1.dex $ ./d2j-dex2jar.sh com.mybank-1.dex
Tak wyodrębiony plik JAR można już wczytać do dekompilera – na przykład JD-GUI.
Walka z zaciemnieniem kodu
Analizę pliku warto rozpocząć od komunikatów o błędach – pozwalają one zlokalizować interesujące fragmenty kodu. W przypadku tej aplikacji okazało się jednak, że komunikaty są zaszyfrowane.
Kolejne kroki analizy, przeprowadzonej przez Thiago, wskazały, że komunikaty szyfrowane są algorytmem AES za pomocą zaciemnionego klucza. Kiedy już dotarł do prawidłowej formy klucza, okazało się, że szyfrowanie odbywa się w trybie CBC, który nie był oryginalnie zaimplementowany w bibliotece obsługującej szyfrowanie. Nie przeszkodziło to mu jednak w uzyskaniu tekstu jawnego komunikatów programu, co ułatwiło dalszą analizę.
Procedura generowania kodu
Początek analizy był dość prosty – Thiago szybko zlokalizował funkcję tworzącą sygnaturę czasową (timestamp). Okazało się, że program liczy interwały 36-sekundowe (równe czasowi ważności generowanych kodów), upływające od północy dnia 1 kwietnia 2007 roku. Znalazł również odwołanie do funkcji generującej token, której parametrami były klucz i sygnatura czasowa. Pozostało zatem zlokalizować klucz.
Po odszyfrowaniu niektórych ciągów (również AES w trybie CBC) Thiago znalazł odwołanie do bazy danych SQLite, jednak zapisy w bazie były także zaszyfrowane – kolejnym kluczem. Kluczem okazał się skrót SHA-1 z identyfikatora urządzenia android_id. Z tego powodu nie działała opcja przenoszenia aplikacji – domyślnie Titanium Backup nie kopiuje android_id.
Opis algorytmu szyfrowania klucza znajdującego się w bazie przerasta nasze możliwości (odsyłamy do źródła). Algorytm wykorzystuje EAX, CMAC oraz HMAC-SHA1 by w oparciu o podany przez użytkownika kod PIN obliczyć klucz, używany do generowania kodu jednorazowego. Sam algorytm generowania również nas przerasta, ale okazuje się, że jest prawie identyczny z wdrożeniem TOTP w Google Authenticator. Jedyna różnica to data „0” (czyli 1 kwietnia 2007) oraz czas ważności kodu (36 sekund zamiast 30 w GA).
Analiza algorytmu nie pozwala na kradzież cudzych tokenów, a jedynie na zbudowanie aplikacji, która uruchomiona z prawami roota na cudzym telefonie może wykraść odpowiednie informacje, pozwalające na generowanie tokenów jego właściciela. By okraść konto bankowe trzeba oczywiście znać jeszcze nazwę użytkownika i hasło właściciela konta.
Własne wdrożenie
Zadowolony z wyniku swojej analizy Thiago zaimplementował opisany powyżej kod na klonie Arduino, dzięki czemu posiada obecnie swój własny generator tokenów. Znając działanie aplikacji mógłby teraz bez problemu przenosić ją między telefonami (kopiując android_id), zatem najwyraźniej wdrożenie na Arduino jest już sztuką dla sztuki. Jak i pewnie cały projekt, ale to własnie dzięki takim artystom mamy dla Was ciekawą lekturę. Na zakończenie demonstracja działania tokenu.
Komentarze
szkoda ze źródło padło http://valverde.me/2014/01/03/reverse-engineering-my-bank
To tylko apostrof w URL’u, już poprawione.
http://valverde.me/2014/01/03/reverse-engineering-my-bank's-security-token
:%s/adroid_id/android_id
Dzięki, poprawione
Powinni to przeczytać najprawdziwsi twardziele, którzy do dzisiaj nie wiedzą jak przetłumaczyć słowo „obfuscated” i wszystko obfuskują (mam nadzieję, że to nie jest obraźliwe).
;)
http://pl.wikipedia.org/wiki/Zaciemnianie_kodu
Powiedz mi co złego jest w słowie „obfuskacja”
A to, że jeśli mamy dobre polskie odpowiedniki to powinniśmy je stosować…
A niechaj narodowie wżdy postronni znają, iż Polacy nie gęsi, iż swój język mają…
A co jeśli ktoś nie ma Androida? Nie zaloguje się do tego banku? ;)
Nie :D Musi kupić jakiegoś wypaśnego fona z andkiem ;))
Przecież tam jest opóźnienie w wyświetlaniu kodu na telefonie… Przypadek?