Billon czyli gigantyczny koszt shackowania (część 1)

Do pisania niniejszego tekstu siadam z przekory. A było to tak.

Jakiś czas temu zainteresowałem się kryptowalutami i blockchainem, zacząłem dużo czytać o technicznych aspektach obu tych tematów. Gdzieś mignął mi news o Billonie czyli polskim startupie finansowym, który otrzymał duży unijny grant na rozwój systemu płatności opartego o rozproszony rejestr. Znalazłem kilka artykułów i wywiadów z przedstawicielami projektu, w jednym z nich odnajdując następujący cytat: “[…] technologia jest naprawdę bezpieczna. Nie do złamania. […] koszt shakowania czegokolwiek w Billonie jest tak gigantyczny, że nikomu by się to nie opłacało.” (BusinessInsider). No i tu właśnie włączyła mi się przekora. Rok temu zbadałem aplikacje mobilne wydane przez polskie banki i odnalazłem w nich szereg poważnych błędów, na własne oczy przekonując się, że autorzy aplikacji mają naprawdę trudne zadanie – pełne bezpieczeństwo to konieczność zrobienia setek rzeczy dobrze. Z kolei włamywaczowi często wystarczy znalezienie pojedynczej rzeczy, która została zrobiona źle, by naruszyć bezpieczeństwo całego systemu.

Postanowiłem więc przyjrzeć się aplikacji Billon dla systemu Android i sprawdzić, czy szumne zapowiedzi przekładają się na nieskazitelną jakość produktu. Zastrzeżenie nr 1 – nie mam żadnego interesu w chwaleniu ani krytykowaniu Billona. Jestem po prostu ciekawskim użytkownikiem. Zastrzeżenie nr 2 – nie będę się w ogóle odnosił do aspektów biznesowych, bo się na tym nie znam, a polskim firmom z założenia życzę sukcesów tak w kraju jak i za granicą.

Poniższy zapis będzie quasi-chronologicznym zapisem eksperymentów. Będzie masa dygresji. I dygresji od dygresji. Koniec końców tekst wyszedł za długi i trzeba go było podzielić.

W tej części opisuję aplikację mobilną oraz dostrzeżone problemy tak aplikacji jak i ekosystemu.

W części drugiej znajdują się pytania wysłane twórcom Billona wraz z otrzymanymi odpowiedziami.

Masz własną aplikację mobilną?

Martwisz się, że może zawierać kompromitujące błędy? Skontaktuj się ze mną aby zlecić prywatny audyt bezpieczeństwa. Kontakt: tomasz.zielinski@gmail.com

Instalacja z Google Play a w zasadzie długa dygresja zamiast instalacji

Gdy w Google Play wyszukać hasło “Billon”, wyszukiwarka podpowiada aplikację prezentowaną na stronie https://play.google.com/store/apps/details?id=info.billon.billon2

Końcówka tego adresu to tzw. nazwa pakietu, unikalny identyfikator aplikacji w Google Play. Zanim zacząłem pisać ten tekst, aplikacja była dostępna pod nazwą pakietu info.billon.billon – na szczęście zrobiłem sobie kopię bezpieczeństwa ówczesnego pliku dystrybucyjnego APK. Zmiana nazwy pakietu oznacza de facto publikację zupełnie nowej aplikacji – niemożliwe będzie dokonanie automatycznej aktualizacji z poprzedniej wersji, użytkownik skierowany do sklepu z aplikacjami musi zgodzić się na instalację nowej apki.

Z marketingowego punktu widzenia jest to wyjątkowo bolesne harakiri, oznaczające konieczność budowania bazy użytkowników od zera. Ilu z miliarda użytkowników Instagrama przeprowadziłoby z sukcesem taką operację? Ilu stwierdziłoby, że w sumie nie warto? Co istotne, nie ma sensownego wytłumaczenia technicznego – operacja byłaby konieczna jedynie wtedy, gdyby utracony został plik z certyfikatem używanym do podpisywania nowych wersji aplikacji. To jednak nie to, bo stara i nowa wersja sygnowana jest tym samym certyfikatem. Postanawiam zapytać wydawcę o powody takiej zmiany.

Komunikat w poprzednim wydaniu aplikacji

Spostrzegam, że okno dialogowe (to z literówką powyżej), informujące o istnieniu nowej aplikacji, odsyła mnie do strony https://billon.io/migration (domena nr 1: billon.io, będzie więcej).

Instrukcja migracji do nowego wydania aplikacji

Instrukcja migracji w wariancie “bez pieniędzy w aplikacji” prowadzi do dokumentu w formacie PDF czyli takim, który średnio nadaje się do wyświetlania na małych ekranach i którego Android domyślnie nie obsługuje. Początkujący użytkownicy smartfonów kończą przygodę w tym miejscu.

Instrukcja migracji w wariancie “mam pieniądze w aplikacji” prosi o podanie kwoty posiadanych środków (trzeba wszystko? co będzie, jeśli część zostanie? czy przepadnie? a czy kwota to z groszami? grosze po kropce czy przecinku? a co, jeśli napiszę za dużo? do kiedy trzeba to zrobić?), wpisanie loginu w starej aplikacji i loginu w nowej aplikacji (ma być inny? może? powinien? musi?), zatwierdzenie formularza oraz zatwierdzenie powiadomienia w aplikacji. Możliwości pomyłek jest tyle, że dział obsługi klienta na pewno nie będzie próżnował (spostrzegam przy okazji, że nie da się do Billona zadzwonić, dostępny jest tylko kontakt e-mailowy i poprzez profil na Facebooku). Pytanie tylko, co rzeczywiście dział wsparcia będzie w stanie zrobić, skoro Billonowy blockchain daje gwarancje nienaruszalności? Postanawiam o to zapytać.

Skoro zaczynam testy, gdy stara wersja aplikacji jest już wycofana ze sklepu Play, rezygnuję z testowania migracji. Kiełkuje mi za to myśl o możliwym phishingu, więcej na ten temat później.

Podglądając stronę billon.io dostrzegam inny problem – wszystkie operacje raportowane są do usługi śledzącej pod adresem ptengine.jp. Ogólnie analityka i telemetria to niezbędne elementy każdego porządnego serwisu webowego, ale jestem zdania, że w przypadku banków i usług finansowych dozwolone powinno być wyłącznie samodzielne gromadzenie i przetwarzanie danych o działaniach użytkowników. Tutaj nie dość, że jest to usługa zewnętrzna, to jeszcze dane wędrują poza jurysdykcję Unii Europejskiej.

Dane analityczne z billon.io wędrują do Japonii

Przy okazji zauważam, że na stronie billon.io stopka zawiera ikonkę facebooka kierującą do profilu https://www.facebook.com/billonforgamers. W sekcji informacje znajduje się odesłanie do e-maila w domenie billongroup.com (domena nr 2) oraz strony domowej pod adresem http://www.billon.live (domena nr 3 oraz istotna niestaranność, link bez HTTPS).

Zauważam też w konsoli Javascriptu, że strona łączy się z serwerem frameworka Sails na porcie 5002:

 Attempting to connect to sails: https://billon.io:5002

   |>  Now connected to Sails.
 \___/ For help, see: http://bit.ly/1DmTvgK
 (using sails.io.js browser SDK @v0.14.0)

Trzeba pamiętać, że w wielu sieciach miejskich, hotelowych czy firmowych niestandardowe porty są poblokowane i z takiej łączności nic nie wyjdzie. Podobnie jest z używanym przez Billona protokołem UDP – firewalle często wycinają go całkowicie. Aplikacja androidowa kompletnie nie radzi sobie z tą sytuacją. Bezowocne próby zalogowania w sieci nigdy się nie kończą a użytkownik nie dowie się, dlaczego nie może skorzystać z aplikacji.

Próba logowania w sieci z firewallem – aplikacja nigdy nie poinformuje użytkownika, że wysiłki są bezowocne

Twórcy strony billon.io założyli, że brak możliwości połączenia z portem 5002 oznacza automatycznie przerwę techniczną, na obrazku poniżej widać screenshoty zrobione w odstępie minuty z dwóch różnych sieci – niezabezpieczonej oraz chronionej restrykcyjnym firewallem (trafiłem też 1-go listopada na rzeczywistą przerwę techniczną lub awarię – trudno odróżnić, bo przerwy nie są nigdzie zapowiadane). Użytkownicy zabezpieczonych sieci mogą więc postrzegać usługę jako znacznie mniej stabilną, niż w rzeczywistości.

Ta sama strona otwierana w sieci niezabezpieczonej (po lewej) i chronionej restrykcyjnym firewallem (po prawej)

Wracając do Facebooka – przewinąłem posty i komentarze w poszukiwaniu czegokolwiek na temat nowej wersji aplikacji. Nic. Był za to filmik promocyjny z youtuberką chodzącą po biurze Billona, w kadr załapała się zawartość kilku monitorów. Co tam widzimy? Wyraźny zestaw kodów jednorazowych. Kod źródłowy testów automatycznych. Adres środowiska developerskiego i nazwa jednego z kont. Być może i co jeszcze, gdyby się lepiej przyjrzeć.

Film z youtube: lista kodów jednorazowych, konto developerskie

Film z youtube: testy automatyczne, adres środowiska developerskiego

Instalacja z Google Play, tym razem na serio

Koniec dygresji. Nadal tkwię na stronie aplikacji Billon w sklepie Google Play. Pierwsze zdanie opisu głosi: “To pięknie zaprojektowana i zoptymalizowana aplikacja, w której płacenie jest przyjemnością. Naprawdę.” Wyzwanie podjęte. Poczuję przyjemność płacenia lub polegnę próbując.

Niżej w opisie aplikacji link do http://www.billongroup.com, też bez HTTPS (dla porządku – sprawdziłem, że domen Billona nie ma na liście preloaded HSTS, więc jednak brak dbałości o detale).

Czas na instalację Billona na komórce. Troszkę się do tego przygotowuję – włączam proxy aplikacyjne rozszywające HTTPS i Wiresharka rejestrującego cały ruch sieciowy, podłączam się do konsoli Android Debug Bridge.

Można zaczynać. Uruchamiam apkę.

W konsoli LogCata (logi systemow Androida) od razu ciekawostki na start: debugowy komunikat o źródle instalacji:

mamy powiadomienie o campaign referrer

oraz inny, wyglądający jak notatka programisty (literówka oryginalna)

IGNOROWANE POKAZYWANIE ZGŁASZANIA BŁĘDU, w poowodów koncepcyjnych

Po chwili pokazuje się seria wpisów z raportem inicjalizacji biblioteki natywnej

NDK_BORG: NDK:LC: [JNI_OnLoad 1]

i kolejne, jak

BŁĄD W LOGICE SUBSKRYPCJI

informacja o nieudanej inicjalizacji biblioteki Firebase. W przyszłości pojawią się też komunikaty bardziej opisowe, jak:

sesja już zamknięta podczas wystąpienia error z monexProgress: {
 "status": "BORG_ERROR_LOGINBOX_NOT_FOUND",
 "statusHuman": "BORG_ERROR_LOGINBOX_NOT_FOUND",
 "progressPercent": 0.0
 }

Wszystko to jest złamaniem dobrych praktyk, zgodnie z którymi aplikacja w wersji release (czyli publikowana w sklepie) nie powinna pisać niczego do logów. Widząc takie komunikaty jak wyżej, wścibski użytkownik może obserwować, jak aplikacja radzi sobie w sytuacjach nietypowych i zidentyfikować jej słabe punkty. Komunikat o ukryciu błędu z powodów koncepcyjnych jest, hm, dość ekshibicjonistyczny.

Na ekranie pojawia się monit o przyznanie aplikacji wymaganych uprawnień. Mile widziane byłoby słowo uzasadnienia, do czego apka ich potrzebuje. Odmawiam obu uprawnień. Pojawia się troszkę inna prośba, wybieram opcję anulowania. Zostaję z… pustym ekranem, z którego nie da się wyjść ani strzałką w górnym pasku, ani klawiszem WSTECZ. Pomaga jedynie zabicie i restart aplikacji.

Sekwencja ekranów prowadząca w białą dziurę

Jeśli testy nie wyłapały problematycznej ścieżki wykonania na tak wczesnym etapie, to co będzie dalej? Później sprawdzę jeszcze, jak aplikacja poradzi sobie z ręcznym odebraniem uprawnień (zauważy ich brak, nie zauważy przywrócenia).

Zaczynam od nowa, tym razem zgadzam się na wszystko. Pojawia się wskaźnik postępu, po chwili zastąpiony ekranem logowania. Jednocześnie w Fiddlerze widzę nieudaną próbę połączenia z serwerem frodo.billon.io:4000 (podczas testów serwer ten ani razu nie przyjmie połączenia na tym porcie) po którym na ekranie pojawia się dodatkowy bannerek “Wykryto niestabilne połączenie”. Checkbox “zapamiętaj mnie” zsuwa się pod klawisz logowania i prawie go nie widać.

Zakładanie konta

Zapada decyzja – tworzę konto. Podaję nazwę użytkownika “tomek” – wydaje się wolna. Podaję e-mail “tomasz.zielinski+b1@gmail.com” – znaki po plusiku pomagają w usłudze GMail automatycznie sortować pocztę. Na to Billon nie pozwala. Usuwam plus i następujące po nim znaki, formularz przyjmuje dane.

W następnym kroku system pyta, czy na pewno się nie pomyliłem:

Zakładanie konta

Sprawdzam dwa razy i klikam OK.

W następnym kroku do zaakceptowania Licencja Aplikacji oraz Regulamin Banku Wydawcy i Agenta Rozliczeniowego. Zaglądam do logów, gdzie widzę:

TODO | PRIORITY : 3 | Task: https://billon.at:446/T1480 | MSG: Ukryta licencja licenceAgreeCheckbox
TODO | PRIORITY : 3 | Task: https://billon.at:446/T1480 | MSG: Zakomentowana walidacja licencji
TODO | PRIORITY : 3 | Task: https://billon.at:446/T1480 | MSG: setLicenceText

Hm. Brzmi, jakby ktoś nie zdążył z jakimś zadaniem i zanotował sobie, co kiedy zrobić. Pytanie tylko, czemu notatka TODO z numerem ticketa trafia do logów systemowych, zamiast do komentarza w kodzie źródłowym? Taki kiks powinien zostać wychwycony przy wzajemnym przeglądzie kodu, w ostateczności w czasie testów aplikacji.

Zaglądam pod adres billon.at (domena nr 4). Zawartość wygląda następująco:

Zawartość serwowana pod adresem billon.at

Widzimy Mediawiki, prawdopodobnie gromadzona jest tam dokumentacja projektu. Do tego Rocket Chat (odpowiednik Slacka), Phabricator (zarządzanie zadaniami i kodem źródłowym), ownCloud (prywatny odpowiednik Dropboxa). Czy takie rozwiązanie jest bezpieczne? Cóż, same tylko Mediawiki i ownCloud dorobiły się w sumie przeszło ćwierci tysiąca usterek i naiwnością byłoby sądzić, że nikt nie odkryje kolejnych. Rezygnując z użycia VPN-a, administratorzy Billona zwiększają powierzchnię ataku na zaplecze serwerowe i backoffice. Wydaje się to niepotrzebnym ryzykiem.

Wracając do aplikacji – ekran z licencjami do zaakceptowania wygląda tak:

Ekran z licencjami do zaakceptowania

Klikam pierwszy link – prowadzi do dokumentu PDF w formacie A4. Android sam z siebie go nie pokaże, a i po zainstalowaniu czytnika na ekranie komórki przewijanie będzie niewygodne. Umowa licencyjna traktuje o “oprogramowaniu pilotażowym Billon”, jej celem i przedmiotem jest “testowanie i ocena Oprogramowania Beta oraz Dokumentacji”. Jako programistę cieszy mnie wyróżnienie w tekście umowy zagadnienia licencjonowania komponentów Open Source użytych w Billonie. Martwi – że umowa pozwala mi zainstalować “jedną sztukę oprogramowania” Billon na “kompatybilnym komputerze”. Jestem właścicielem kilku urządzeń z Androidem, wszystkie nadmiarowe posłusznie odłożyłem.

Umowa licencyjna wspomina domenę nr 5 czyli billon.info. Zabrania “wykorzystywać dostępu do Oprogramowania w celach komercyjnych”. Duże rozczarowanie, prawie nie używam pieniędzy w innych celach. Zgodnie z najlepszymi amerykańskimi wzorcami licencja zabrania “rozszyfrowywać, dekompilować, dokonywać wstecznej inżynierii, dezasemblować lub w inny sposób sprowadzać Oprogramowanie do postaci czytelnej dla człowieka”, co niekoniecznie stoi w zgodzie z art. 75 ust 2 rodzimej ustawy o prawie autorskim i prawach pokrewnych (zwłaszcza gdy zauważymy, że w okresie między instalacją programu a jego uruchomieniem nie wiążą nas warunki licencji, na którą zgodzimy się – lub nie – po uruchomieniu). Na końcu licencja określa, że Oprogramowanie Billon jest “objęte niniejszą licencją na ograniczony okres 180 dni”.

Wireshark powie mi później, że żądanie pobrania tego i następnego dokumentu zostało wysłane przez nieszyfrowany protokół HTTP. Mogę mieć więc jedynie nadzieję, że to, co przeczytałem, faktycznie zostało wysłane przez serwery Billona.

Jeśli zajrzeć do pakietu dystrybucyjnego z aplikacją, w zasobach można znaleźć dokument PDF w języku angielskim, sygnowany przez Billon Financial Ltd. Aplikacja nie korzysta jednak z tego pliku, więc nie bardzo wiadomo, jaka jest jego rola.

Drugą lekturą był “Regulamin świadczenia usług pośrednictwa wykupu pieniądza elektronicznego BiLLon oferowanej przez Plus Bank S.A.”. Wydaje mi się, że w tytule jest błąd gramatyczny, natomiast w całym dokumencie konsekwentnie mowa o usłudze “biLLon” przez dwa duże el. I faktycznie – zastrzeżony znak towarowy nosi nazwę “biLLon”. Tyle Urząd Patentowy RP, w ogólnoeuropejskiej wyszukiwarce euipo.europa.eu rozróżnienia brak. W połowie dokumentu zaczyna się “Regulamin świadczenia usługi emisji oraz wykupu pieniądza elektronicznego BiLLon oferowanej przez PLUS BANK S.A.”. Oba teksty są bardzo podobne i choć niektóre sekcje są identyczne, ich numeracja różni się. Czy komuś skleiły się dwie wersje jednego dokumentu?

Nie znam wielu użytych terminów, nie rozumiem wielu punktów obu regulaminów. W związku z tym – bez wahania zaznaczam zgodę.

Po kilku sekundach okazuje się, że wybrana przeze mnie nazwa użytkownika jest zajęta. W logach widać komunikat:

letUserTask User nie jest zalogowany, logujacy ani rejestrowany przy próbie wykonania: 
 CallGui_Secure_RegisterFailed() called with: error = [BORG_ERROR_REGISTRATION_NON_UNIQUE_NAME]

Wybieram inną nazwę, ta jest w porządku. Czekam dłuższą chwilę na inicjalizację, na końcu pojawia się estetyczny dashboard z okrągłym zerem na koncie. Animacja na dole sygnalizuje, że trwa proces weryfikacji środków. Czekam dalsze kilka minut, może środków przybędzie. Animacja znika, zero pozostaje. Czas spać.

Doładowanie konta

Kolejny wieczór, uruchamiam telefon i wracam do aplikacji. Billonowi tradycyjnie nie udaje się dostukać do serwera frodo.billon.io na porcie 4000, ale tym razem czerwony pasek nie pojawia się. Loguję się zaznaczając, aby aplikacja “zapamiętała mnie”.

Aplikacja po krótkiej chwili wpuszcza mnie do ekranu głównego. Zauważam żądanie wysłane pod adres https://billon.io:5002/cashout/initiate. Treści niewiele. W tamtą stronę nazwa użytkownika, z powrotem {„status”:”NO_PAYMENTS”}. Ponownie niestandardowy port, który będzie wycięty w wielu sieciach firmowych.

Jednocześnie w Wiresharku zauważam, że do maszyny ts.billon.io na port 8080 co jakiś czas aplikacja coś wysyła. Bez szyfrowania. W XXI wieku. GOŁYM HTTP, JAKBYŚMY DOPIERO CO WYSZLI Z RAJU! Postanawiam zapytać, czy ujawnienie tych danych wystawia mnie lub moje środki na jakiekolwiek niebezpieczeństwo. Skoro jednak mój Billon wysyłał dane otwartym tekstem, równie dobrze mogę zacytować je poniżej.

Dane wysyłane z aplikacji otwartym tekstem

To samo, co wyżej, po rozpakowaniu

Wybieram z menu opcję doładowania konta, decyduję się na płatność kodem BLIK, jako odbiorca pojawia się “billon.me”. To by była domena nr 6, z wrażenia spóźniam się z potwierdzeniem transakcji. Próbuję jeszcze raz, tym razem w porę zatwierdzam kod blika, szast prastu, mam prawdziwe 5 zł na koncie Billona! Aplikacja niezwłocznie edukuje mnie, że utracę środki, jeśli ją teraz odinstaluję. Nie przenosi mnie jednak na ekran startowy, zamiast tego po płatności – udanej lub nieudanej – kontrolka webview widoczna na ekranie otwiera formularz nowego zasilenia. Z punktu widzenia UX – słabo.

Powiadomienia e-mailowe

Na skrzynkę poczty elektronicznej dostaję maila o tytule “Doładowanie aplikacji Billon zakończone” i treści:

Cześć!

Dziękujemy za doładowanie aplikacji Billon! Życzymy przyjemnego korzystania!

Ten e-mail został wysłany automatycznie. Jeśli jednak potrzebujesz wsparcia z naszej strony, 
jesteśmy dostępni pod adresem pomoc@billongroup.com. Napisz do nas!

Pozdrawiamy,

Zespół Billon

Uderzają mnie dwie rzeczy: pierwsza, że nigdy nie potwierdziłem poprawności e-maila. W żadnym momencie procesu rejestracji Billon nie wymaga kliknięcia linku autoryzacyjnego, zamiast tego gotów jest przyjąć dowolny adres e-mail i tam wysyłać korespondencję. Druga – że adres nadawcy to info@billon.io, zaś w treści wspomniano pomoc@billongroup.com. Wygląda jak regularny phishing, dobrze przynajmniej, że rekord SPF jest poprawny.

Nabieram przekonania, że Billona zaprojektowano z istotnymi odstępstwami od dobrych praktyk stosowanych powszechnie w serwisach online, nie wspominając już o branży usług finansowych.

Jakiś czas później zmieniam w ustawieniach adres e-mail przypisany do konta, co wymaga podania hasła i nowego adresu. Po udanej zmianie nadal widzę na ekranie stary e-mail, dopiero wyjście i wejście do ustawień odświeża widok. Testuję tę funkcję 31-go października, na żaden z adresów nie przychodzi potwierdzenie przeprowadzonej operacji. Dwa dni później przeprowadzam zmianę ponownie – tym razem na stary i nowy e-mail przychodzi komunikat informujący o zmianie.

Konsekwentnie – zmiana e-maila nie wymaga potwierdzenia, system od razu wysyła komunikat: “Drogi użytkowniku, podany adres e-mail został wprowadzony do aplikacji Billon w razie potrzeby odzyskania hasła. Otrzymasz na niego kody jednorazowe niezbędne do odzyskania dostępu do Twojego konta”. Jeśli się pomylimy, kontrolę nad kontem oddamy w ręce obcego człowieka. Mam na Gmailu adres złożony z popularnego imienia i nazwiska, nawet nie wiecie, jak często się to zdarza.

Próba odzyskania hasła również udała się jedynie drugiego dnia testów, sam proces jest dość unikalny. Użytkownik otrzymuje dwa e-maile z długimi kodami alfanumerycznymi. Po ich prawidłowym przepisaniu do jednego formularza, pojawia się możliwość wpisania nowego hasła. Postanawiam zapytać o techniczne uzasadnienie takiego podejścia.

Ustawienia aplikacji

Tymczasem zaś wracam do ustawień. Znajduję tam listę walut, aktywna waluta to PLN, dodać można GBP, EUR, USD, BIL oraz… PLN. Gdy dodać PLN do istniejącego PLN, nic się nie dzieje. Chwilę klikam, potem zaglądam do ściągawki opisującej limity kwotowe transakcji, do logcata trafia przyjazny komunikat:

TODO | PRIORITY : 3 | Task: https://billon.at:446/T1760 | MSG: Wymuszona domyślna waluta w limitach

Dodaję obsługę kompletu walut obcych (co to jest BIL?) i zastanawiam się, jak zasilić Billona obcymi nominałami. Okazuje się, że produkcyjna wersja aplikacji zawiera całkowicie zmyślone, niedziałające dane kont do zasileń walutowych. Formatka doładowań w punkcie wpłat ignoruje z kolei wybraną walutę i zawsze pokazuje doładowania złotówkowe. Na tym moje opcje się kończą, nie jestem w stanie zasilić billona walutą inną niż PLN.

Tylko wybór PLN skutkuje prezentacją rzeczywiście istniejącego rachunku

Wybór waluty nie ma znaczenia, doładowanie w punkcie dotyczy wyłącznie PLN

Badam inną opcję w ustawieniach, edytor kwoty automatycznie przenoszonej do Sejfu wygląda tak:

Edytor kwoty oferuje dokładność do tysięcznych części złotego

Jeśli kwotę 49,500 zmienić na 49,512 – zostanie zapamiętana z dokładnością trzech miejsc po przecinku. Również edytor kwoty płatności bez autoryzacji ma precyzję tysięcznych części złotówki. Kwoty w groszach pomnożonych przez 10 widoczne są w bazie danych i plikach składowanych przez aplikację. Zgaduję, że ma to związek z ułamkami groszy wspomnianymi w cytowanym wcześniej regulaminie emisji i wykupu pieniądza elektronicznego – co rodzi wiele pytań, skoro “cyfrowy pieniądz” w Billonie ma być równoważnikiem polskiego złotego dzielącego się w myśl ustawy na sto groszy.

Sejf

Wybieram na głównym ekranie opcję sejfu, próbuję przesłać do niego 2 zł, efekt: “Transakcja nieudana, nie udało się uzbierać odpowiedniej kwoty”. Na konsoli logcata bezradny komunikat:

nie ma WHERE…

Próbuję po raz drugi, złotóweczkę. Też nic. Przy trzeciej próbie zauważam, że w kwocie można podać tak kropkę jak i przecinek. Okazuje się, że kwota “2.00” (z kropką) prowadzi do opisanego błędu. Kwota “2” (bez kropki ani przecinka) – tak samo. Kwota “2,00” (z przecinkiem) – DZIAŁA! Przelew do sejfu działa! Tylko… czemu do sejfu pojechało całe 5 zł?

Przenoszenie pieniędzy do sejfu, aplikacja sama decyduje o kwocie

Serio, wpisałem 2 zł, z konta zeszło 5 zł. Dobra, może wyjąć troszkę z sejfu? Ostrożnie podaję kwotę 2 zł, tym razem pyta o hasło, szastu prastu… w sejfie zero, na urządzeniu 5 zł. To bardzo poważny błąd. Nie wszystkie wydarzenia opisuję tu chronologicznie, ale usterkę zaobserwowałem po kilkukrotnym edytowaniu kwoty automatycznego przenoszenia, zaś problem ustąpił po dokonaniu pierwszej płatności. Może to będzie jakąś wskazówką dla autorów.

Zasoby graficzne i funkcje, których brak

Aby zająć się czym innym, zajrzałem do zasobów aplikacji. Zestaw obrazków sugeruje, że gdzieś w aplikacji dostępna jest lista kontaktów i opcja przekazu środków przez stuknięcie urządzeń. Dodatkowo na stronie billon.live czytam: “Przesyłasz pieniądze bezpośrednio drugiej osobie. To działa jak gotówka – z ręki do ręki”. Proponuję więc koledze założenie konta w Billonie, by przetestować przekazywanie pieniędzy między użytkownikami.

Kolega zakłada konto, instaluje aplikację, ale… nie odnajdujemy możliwości przekazywania środków sobie nawzajem. Okazuje się, że portfel Billon może służyć tylko do płacenia komuś, kto ma konto sprzedawcy, a więc nie do końca “działa jak gotówka”. Nie oddamy nikomu kasy za piwo czy pizzę. Jeśli mamy środki w Billonie a nie w bilonie (dobre, nie?), pozostaje wypłata na konto albo z bankomatu.

Wspomniane grafiki nie zostały skasowane po dezaktywacji lub usunięciu wybranych funkcji. To samo może dotyczyć zezwoleń pozwalających aplikacji kontrolować Bluetooth i Wifi – żadna z aktywnych funkcji ich nie uzasadnia. W pliku z komunikatami odnajduję teksty: “Płatność przy pomocy technologii Blutooth, WiFi Direct lub NFC”, “Wpisując login użytkownika lub wybierając go z listy kontaktów możesz wysłać do niego wybraną kwotę” oraz “Wprowadź kwotę, jaką chcesz zebrać oraz liczbę osób do zrzutki” – widać więc, że przynajmniej w planach zakres funkcji był większy. Postanawiam o to zapytać.

Wewnątrz aplikacji znajdziemy też pokaźny zestaw ikon poświęconych Alior Bankowi. Jego udział w projekcie zapowiadano jeszcze w 2015 roku, jednak do współpracy najwyraźniej nie doszło.

Zauważam w zasobach tekst “Dzięki aplikacji Billon możesz przekazywać nawet bardzo małe kwoty, czyli realizować tzw. mikropłatności. Cyfrową gotówką zapłacisz nawet dziesiątą część grosza. Wygodne np. przy płatnościach za treści w Internecie”. Przychodzi mi do głowy pomysł na oscylator generujący nadmiarowe ułamki grosza, jednak w obecnej wersji minimalna kwota do przelewu to jeden grosz. Trzy cyfry po przecinku w okienku ustawień wyglądają na nieskorygowaną zaszłość.

Realizacja płatności na rzecz sprzedawcy

Skoro nie mogłem wysłać pieniędzy koledze, postanowiłem przetestować płatności na rzecz posiadacza konta sprzedawcy. Okazuje się, że można je zarejestrować w kilka chwil i – podobnie jak w przypadku konta klienckiego – podany podczas rejestracji e-mail nie zostanie zweryfikowany. Nowe konto sprzedawcy może od razu przyjmować środki, jeśli więc sprzedawca poda e-mail z literówką albo zapomni swojej nazwy użytkownika, może wpakować się w kłopoty. Swoboda w tworzeniu kont rodzi wspomniane wcześniej ryzyko phishingu (np. zlecenia na rzecz użytkownika “rnigracja” zamiast systemowego konta “migracja”).

Aplikacja Billon nie ma opcji wysłania pieniędzy. Transakcje realizowane są w modelu odwrotnym – to odbiorca, któremu podajemy swoją nazwę użytkownika, inicjuje żądanie przelewu. Najprostszym sposobem na wysłanie żądania jest skorzystanie ze strony billon.me/loginodbiorcy. Jeśli aplikacja klienta (nadawcy) jest włączona, na ekranie komórki pojawi się żądanie zapłaty. Jeśli aplikacja jest wyłączona, na stronie WWW zobaczymy komunikat “Nie znaleziono użytkownika. Upewnij się, czy wpisałeś prawidłową nazwę”.

Panel pozwalający wygenerować żądanie zapłaty

Jeśli żądanie zapłaty zostanie wystawione podczas transferu środków do sejfu, aplikacja czasem się gubi i przyciemnia ekran ale nie pokazuje odpowiedniego okna dialogowego.

Z ciekawostek: “Regulamin świadczenia usług drogą elektroniczną BILLON.ME” (dostępny przy rejestracji sprzedawcy) zawiera w nagłówku zastrzeżenie praw autorskich Billon Group Limited Ltd z siedzibą w Londynie, choć usługodawcą jest Billon Solutions Sp. z o.o., założona w czerwcu 2017.

Treść umowy zawiera zastrzeżenie praw autorskich innej firmy

Dla porównania – licencjodawcą aplikacji mobilnej jest Billon Sp. z o.o., która rozpoczęła działalność w grudniu 2012.

Pliki składowane przez aplikację

Podczas testów regularnie kopiowałem zawartość katalogu roboczego Billona, aby później przyjrzeć się zawartości plików zapisywanych przez aplikację. Aby było jasne – aplikacje dla systemu Android nie mogą nawzajem zaglądać sobie w dane. Jeśli jednak urządzenie zostanie zainfekowane, złośliwe oprogramowanie będzie mogło bez problemu czytać i modyfikować dowolne pliki. Ostatnią deską ratunku jest wówczas silne szyfrowanie danych w oparciu o klucz, który albo nie jest zapisany w urządzeniu (wywodzi się z hasła użytkownika), albo zapisany jest w bezpiecznym, sprzętowym mechanizmie składowania kluczy.

Niestety, Billon nie robi tu prawie nic:

  • Pliki z preferencjami zaszyfrowane są statycznym kluczem, osadzonym na stałe w kodzie, więc de facto dostęp do pliku oznacza dostęp do odszyfrowanej zawartości
  • Baza danych w formacie SQLite zawiera komplet informacji o transakcjach i całej aktywności użytkownika, więc atakujący może wyliczyć bieżący stan sejfu i konta, pozna też wszystkich kontrahentów
  • Zaszyfrowane kolumny w bazie danych również szyfrowane są statycznym kluczem osadzonym w kodzie
  • Pliki robocze zapisywane są prawdopodobnie w formacie binarnym biblioteki Boost

Podkreślę, że w przypadku Androida powyższe ryzyko dotyczy sytuacji, w której dostęp do plików zyskają osoby trzecie – wskutek przełamania zabezpieczeń lub nieostrożności użytkownika w posługiwaniu się zrootowanym telefonem. Podobny problem dotyczy jednak aplikacji dla systemu Windows, a tam dostęp do różnych katalogów nie jest regulowany tak ściśle, jak w telefonie.

Samo odnalezienie zaszytych na sztywno kluczy nie jest przesadnie skomplikowane. Zauważamy na przykład w katalogu aplikacji całkowicie nieczytelny plik o nazwie “global_settings.settings”. Sprawdzamy, która z klas programu zawiera tekst “global_settings”. Okazuje się, że występuje on w jednym pliku, który można znaleźć niby-przypadkowy ciąg znaków „fo1izO5^53MyunS!b9zCz^U&FuiyI&”. Chwilę później odnajdujemy interfejs, który jest implementowany przez klasę zawierającą tekst “AES/ECB/PKCS5PADDING”. Mamy więc (patrząc od końca): jednoznacznie określony zestaw szyfrów symetrycznych, klucz oraz zaszyfrowany plik. Bingo.

Baza danych SQLite nie jest szyfrowana

Przeglądając binaria trafiam jeszcze na URL w domenie billon.it (domena nr 7), która na porcie 80 zwraca wprawdzie błąd 502 (bad gateway), za to na porcie 81 serwuje zawartość wyglądającą na stronę domową Billona założoną w roku 2014 i porzuconą w 2015. Strona ta nie została zindeksowana przez Google i jest swoistym wehikułem czasu. Wspomina o “nano-płatnościach” w kwocie 0.1 grosza (nanozłotówka to by było 0.0000001 grosza), opisuje podział cyfrowej gotówki na nominały równoważne banknotom i monetom oraz proces wydawania reszty, objaśnia transakcje offline, płatności pod nr telefonu, odsyła do nieistniejących już aplikacji o nazwach pakietu “info.billon.billon.plusbank” oraz “info.billon.billon.demo”, wspomina opcję wzięcia pożyczki przez aplikację oraz wielokrotnie wymienia markę “billon” (z małej litery, dwie środkowe litery kursywą). Słowem – wizja twórców Billona w postaci sprzed kilku lat.

Prywatność użytkownika aplikacji

Przyznam, że z tym rozdziałem mam duży problem. Twórcy aplikacji Billon nie udostępnili opisu protokołu blockchain na takich samych zasadach, na jakich można poczytać o Bitcoinie, Ethereum i dziesiątkach innych kryptowalut. Tam mamy do czynienia z jawnym protokolem i oprogramowaniem open-source. Tu nieznane pozostają formaty plików, model komunikacji, sposób organizacji sieci i mechanizmy zabezpieczające blockchain przed sfałszowaniem.

Wśród entuzjastycznych zapewnień, jaki to Billon jest szybki, bezpieczny i wygodny, brakuje kluczowej informacji – które dane są w sieci Billon traktowane jako jawne, a które pozostają tajne. Przykład – w sieci Bitcoin, gdzie cały blockchain jest jawny, możliwe jest prześledzenie wszystkich przepływów, jednak adresy mają postać kluczy kryptograficznych, same z siebie nie zdradzają żadnych informacji o osobach przeprowadzających transakcje. Billon korzysta z nazw kont wybranych przez użytkowników, przetwarza adresy poczty elektronicznej i – wg słów autorów – zapisuje w blockchainie numery rachunków bankowych powiązanych z danym kontem.

Jednocześnie – co potwierdził support – kopie moich danych są “zabezpieczone (duplikowane) w innych węzłach sieci Billon”. Jest całkiem prawdopodobne, że zapisane dane są cyfrowo podpisane, jednak z całą pewnością nie wszystkie są szyfrowane.

Gdy więc trafiłem wśród danych przetwarzanych przez aplikację na plik z e-mailem innego użytkownika sieci Billon, zadzwoniły mi wszystkie dzwonki alarmowe. Użytkownik ten potwierdził mi, że testował aplikację miesiąc wcześniej, przeprowadzając kilka testowych operacji. Jego e-mail, hash hasła i jeszcze jedno pole nieznanego zastosowania są zapisane otwartym tekstem w pliku wyglądającym na obiekt zserializowany biblioteką Boost.

Operator usługi Billon musi koniecznie zacząć informować użytkowników o sposobie przetwarzania i dystrybucji danych. Rozgłaszanie otwartym tekstem e-maila użytkownika losowym węzłom sieci jest faktem dramatycznie odbiegającym od poziomu poufności, jakiego oczekiwalibyśmy od pośrednika finansowego.

Witryna billon.me umożliwia enumerację nazw kont sprzedawców oraz tych użytkowników, którzy mają w danej chwili aktywną aplikację. Nie jest dla mnie jasne, czemu płatności mogą być inicjowane przez nieuwierzytelnionych użytkowników, jest za to bardzo prawdopodobne, że wobec braku autoryzacji relatywnie łatwo byłoby o atak DoS.

Billon zbiera i wysyła w świat szczegółowe dane o położeniu użytkownika i nazwie sieci wifi

Billon przy użyciu biblioteki Crashlytics zbiera informacje o lokalizacji użytkownika, nazwie sieci wifi, w metadanych podaje też nazwę i identyfikator użytkownika. Żaden z dokumentów nie informuje użytkownika, że taka aktywność będzie miała miejsce, komplet danych leci do serwerów w USA w więc poza jurysdykcję Polski i Unii Europejskiej. Ciekawe, jaki wpływ na takie praktyki będą miały regulacje RODO/GDPR, które wejdą w życie za kilka miesięcy.

Debugowy kod w aplikacji

W wielu aplikacjach programiści zaszywają funkcje testowe, które pozwalają kontrolować dodatkowe ustawienia, wymuszać sytuacje wyjątkowe lub prezentować na żywo stan wewnętrznych mechanizmów aplikacji. Regułą jest jednak, że funkcje takie dostępne są jedynie w wydaniach przeznaczonych do testów wewnętrznych. Narzędzia do tworzenia aplikacji na Androida bardzo ułatwiają usunięcie wybranych komponentów z kompilacji release.

Menu z opcjami developerskimi można otworzyć w aplikacji pobranej ze sklepu Play

Billon łamie tę zasadę, funkcje developerskie są dostępne w aplikacji pobranej ze sklepu, pracującej w środowisku produkcyjnym. Na zrootowanym urządzeniu można dostać się do nich na co najmniej dwa sposoby (żaden nie wymaga modyfikacji aplikacji). Gdy to zrobimy, zobaczymy nowe usługi, sposoby zasilenia konta, metody wypłaty środków i autoryzacji użytkowników. Pojawia się też opcja edycji listy kontaktów i uruchomienia debugera gdb lub jednego z kilkunastu poleceń diagnostycznych i backupowych.

Funkcje testowe stanowią dla atakującego cenną podpowiedź, jak wygląda prawidłowa sekwencja użycia klas i metod, które nie zostały jeszcze wykorzystane produkcyjnie. Dają też okazję do interakcji z backendem w sposób, który nie wywoła alarmu – wzorce aktywności były już wcześniej widywane.

Podsumowanie

System płatności Billon i aplikacja dla systemu Android zawierają szereg usterek i rozwiązań odbiegających od standardów branżowych. Moją uwagę zwróciły następujące elementy:

  • Ścieżki interakcji aplikacji, które kończą się ślepym zaułkiem – ekranem, z którego nie da się wyjść inaczej, jak tylko zabijając aplikację
  • Komunikacja aplikacji z backendem przy użyciu protokołu UDP oraz niestandardowych portów protokołu TCP – z tego powodu w wielu zabezpieczonych sieciach aplikacja w ogóle nie połączy się ze światem
  • Wysyłanie do logów szczegółowego opisu zmian stanu aplikacji, komunikatów o ignorowanych problemach, publikowanie w logach URL-i do ticketów opisujących zadania, które nie zostały jeszcze w aplikacji zaimplementowane
  • Wyświetlanie w aplikacji produkcyjnej ekranów-zaślepek zawierających błędne dane i niedziałające funkcje
  • Dyskusyjne praktyki devops, dzięki którym do narzędzi zespołu developerskiego można próbować zalogować się z całego internetu
  • Nieaktualne (?) i omyłkowo zdublowane (?) umowy licencyjne, pobierane przez niezabezpieczony kanał komunikacji [patrz część 2]
  • Brak potwierdzania prawidłowości adresów e-mail linkiem autoryzacyjnym lub w jakikolwiek inny sposób; wysyłanie korespondencji, w której domena nadawcy nie zgadza się z odnośnikiem w treści
  • Usterki w interfejsie aplikacji mobilnej skutkujące realizacją transakcji z/do sejfu na inną kwotę niż zlecona
  • Szyfrowanie plików aplikacji symetrycznym kluczem osadzonym na sztywno w kodzie aplikacji, używanie nieszyfrowanej bazy SQLite zawierającej informacje o stanie konta i sejfu
  • Użycie bardzo wielu domen, pod którymi serwowane są aplikacje webowe o różnym wyglądzie – ułatwia to atak polegający na skierowaniu użytkownika pod alternatywny adres zawierający słowo “billon”, ale kontrolowany przez atakującego
  • Niejasny model bezpieczeństwa i brak informacji o tym, jakie informacje i w jakiej formie będą wysyłane do serwerów Billona i innych członków sieci – ja w swoich plikach znalazłem e-mail innego użytkownika
  • Zbieranie bez wiedzy użytkownika informacji o lokalizacji, nazwie sieci wifi
  • Obecność funkcji testowych i debugowych w sklepowej wersji aplikacji mobilnej

Uważny czytelnik zauważy, że powyższy opis nie opisuje “hackowania blockchaina” i nie sygnalizuje, że pieniądze użytkownika są zagrożone. Na dobrą sprawę temu tematowi dopiero zaczynam się przyglądać – elektronicznym pieniądzem zawiaduje bowiem wielka biblioteka natywna, której analiza wykroczyła poza zakres niniejszego tekstu. Pozostaje jednak faktem, że opisana wyżej duża liczba problemów nie napawa optymizmem – Billon jest wszakże rozwijany od pięciu lat.

Przeczytaj DRUGĄ CZĘŚĆ artykułu, zawierający pytania wysłane do spółki Billon oraz otrzymane odpowiedzi.

Testy przeprowadzono w dniach 23.10 – 12.11.2017, testowano aplikację Billon w wersji 3.3.10 opublikowaną w sklepie Play dnia 23.09.2017.

Masz własną aplikację mobilną?

Martwisz się, że może zawierać kompromitujące błędy? Skontaktuj się ze mną aby zlecić prywatny audyt bezpieczeństwa. Kontakt: tomasz.zielinski@gmail.com

Newsletter

Jeśli chcesz być informowany o nowych tekstach na Bardzo Ciekawym Blogu, zasubskrybuj newsletter. Nikomu nie udostępnię Twojego adresu, dostaniesz średnio jednego maila na kilka miesięcy.

Starzy ludzie znajdą feed RSS tutaj.

Dodatek o domenach Billona

Lista domen w użyciu:

  • billon.info (rejestracja 2013-10-11, zunit sp z o.o.) – przekierowanie na billongroup.com, wskazywana w wielu miejscach jako główna witryna marki
  • billon.at (rejestracja 2013-10-11, zunit sp z o.o.) – narzędzia developerów Billona
  • billon.in (rejestracja 2013-10-11, zunit sp z o.o.) – instalacja pakietu OnlyOffice
  • billon.me (rejestracja 2013-10-11, zunit sp z o.o.) – panel sprzedawcy, panel żądania zapłaty
  • billon.io (rejestracja 2014-12-08, Billon Sp z o.o.) – formularz zasilenia konta Billon
  • billongroup.com (rejestracja 2016-04-09, Billon Sp z o.o.) – angielskojęzyczna strona marki Billon
  • billonfinancial.co.uk (rejestracja 2017-01-13, Billon Finacial Ltd.) – przekierowanie na billon.live/uk/; nazwa firmy we WHOIS ma literówkę
  • billon.pro (rejestracja 2017-01-27, Billon Sp z o.o.) – dokumentacja API
  • billon.live (rejestracja 2017-08-02, Billon Sp z o.o.) – wielojęzyczna strona marki Billon
  • billondigital.com (rejestracja 2017-10-04, Billon Sp z o.o.) – do niedawna landing page OVH, obecnie strona domowa produktów nie związanych z systemem płatności Billon

Lista domen nieużywanych lub zawierających porzucone treści:

  • billon.it (rejestracja 2013-10-11, zunit sp z o.o.) – na porcie 81 polskojęzyczna strona marki Billon z roku 2015
  • billon.nl (rejestracja 2013-10-11, zunit sp z o.o.) – przekierowanie
  • billon.tv (rejestracja 2013-10-11, zunit sp z o.o.) – przekierowanie
  • billon.mobi (rejestracja 2013-10-11, zunit sp z o.o.) – przekierowanie
  • billon.co.uk (rejestracja 2013-10-11, zunit sp z o.o.) – przekierowanie
  • billon.cash (rejestracja 2015-01-08, Billon Sp z o.o.) – przekierowanie
  • billon.tech (rejestracja 2017-04-11, Billon Sp z o.o.) – przekierowanie
  • billon.life (rejestracja 2017-03-23, Billon Sp z o.o.) – przekierowanie

Okazjonalnie na stronach pojawiają się problemy z certyfikatami HTTPS, pod niektórymi ścieżkami serwowane są witryny o różnych stopniach kompletności. Czasem pojawiają się inne zasoby, jak http://www.billon.info/demo/?url=/demo – strona demonstracyjna pokazująca przykładowe zastosowania usługi, np. spreparowaną stronę YouTube z datkami Billona

Domenę billon.be zarejestrował sobie Gaël Billon