10:57
28/7/2015

Podczas wykonywanych przez nas testów penetracyjnych serwisów internetowych sporo uwagi poświęcamy procedurom resetu hasła do konta. Bardzo często znajdują się tam ciekawe błędy, które niekiedy umożliwiają przejęcie konta użytkownika. Błąd tego typu zaobserwować można było w jednym z polskich serwisów zajmujących się obsługą płatności internetowych.

Aaaaale słabe hasło!

Parę dni temu zgłosił się do nas jeden z czytelników, który zapomniał swojego hasła do serwisu Homepay.pl. Kiedy próbował je odzyskać, zauważył że serwis ustawił mu tymczasowe hasło, które wyglądało na podejrzanie nielosowe:

homepay-password

Dzięki uprzejmości kolejnego z naszych czytelników, który posiadał konto w serwisie Homepay, błąd udało się nam odtworzyć i potwierdzić. Na czym dokładnie on polegał i czy można było przy jego pomocy przejąć konto innego użytkownika serwisu?

Przejęcie konta możliwe, ale nie takie proste

Aby zresetować hasło w Homepay, wystarczy podać adres e-mail “ofiary”. System wysyła wtedy link na skojarzony z kontem adres e-mail i dopiero po kliknięciu w tenże link, ofiara otrzymuje e-mailem hasło tymczasowe. Z założenia powinno ono być losowe, ale na skutek błędu programistycznego zawsze i dla każdego zwracane było hasło “aaaaaa“.

Rozważmy możliwości przejęcia konta. Jest prawdopodobne, że ofiara kliknie w linka generującego hasło tymczasowe i tym samym umożliwi osobie znającej błąd w procedurze resetu hasła zalogowanie się do jej konta za pomocą “aaaaaa“. Ale poza podaniem hasła potencjalny włamywacz chcący przejąć konto ofiary potrzebuje jeszcze PIN-u, a tego — zgodnie z informacjami uzyskanymi od właścicieli serwisu — nie może już tak łatwo zresetować (wymagany kontakt z BOK) i nie może go w nieskończoność zgadywać (czasowa blokada konta po 4 nieudanych próbach).

Krótko mówiąc, choć tymczasowe hasło można przewidzieć — do przejęcia konta wybranej osoby droga jest jeszcze długa.

Ale to nie koniec anomalii w Homepay’u…

Ponieważ przed publikacją artykułu chcieliśmy zgłosić błąd właścicielom serwisu Homepay, udaliśmy się na ich stronę internetową i zakładkę kontakt. Tam, po kliknięciu w formularz kontaktowy spotkała nas niemiła niespodzianka — wyskoczył popup przekierowujący kontekst strony na podejrzane treści (m.in. serwisy reklamujące narzędzia do spamowania, kretyńskie filmiki z YT i itp.).

Namierzyliśmy przyczynę przekierowań w kodzie strony Homepay’a. Zagadką pozostawało, czy skrypt ten został dodany na stronę przez samych właścicieli serwisu (w celu zarabiania na podejrzanych reklamach), czy może został wstrzyknięty na skutek jakiejś dziury w skryptach strony?

homepay-scam

Tu warto przypomnieć, że Homepay miał już problemy z bezpieczeństwem. Pod koniec 2013 roku serwis padł ofiarą włamywaczy. Firma wystosowała wtedy takie oświadczenie:

wlamanie-homepay

Aaaaaa co było powodem błędów? Literówka…

Kiedy pomimo wyskakujących popupów udało nam się skontaktować z właścicielami serwisu, musimy przyznać, że komunikacja przebiegła błyskawicznie i profesjonalnie. Poniżej zamieszczamy oświadczenie nadesłane do redakcji przez Dawida Pietrzaka, dyrektora działu informatyki firmy Homepay:

Witam serdecznie redakcję Niebezpiecznika, szczerze mówiąc czekałem dnia, kiedy napiszecie w końcu i o nas ;-)
Rzeczywiście potwierdzamy istnienie obu błędów przez Was wskazanych, które zostały już wyeliminowane.
Jednakże aby rozwiać wątpliwości, chcielibyśmy skomentować następujące sprawy:

1) Problem resetu hasła
Był to problem spowodowany zwykłym błędem ludzkim – a dokładniej literówką w konstrukcji funkcji generującej losowe hasło (lenght zamiast length) przez co pętla zawsze myślała, że tablica znaków ma tylko jedną literę – a ;-)
Chciałbym tutaj zwrócić uwagę, że aby przejąc takie konto w naszym serwisie, nie ukrywam, że trzeba było przede wszystkim jak sami zauważyliście, spowodować, aby użytkownik kliknął w link i nie zmienił natychmiast hasła. Co więcej, logowanie do panelu partnera posiada dwuskładnikową autoryzację – nie taką klasyczną SMSem, ale trzeba było podać jeszcze PIN, który można zresetować tylko kontaktując się z nami i podając dane osobowe. Ponadto, trzy próby wpisania błędnego PINu kończą się blokadą konta na 15 minut.
Generalnie, aby rzeczywiście przejąć konto, należałoby się dość dobrze nagimnastykować i poświęcić masę czasu na bruteforce 4 znakowego PINu – zakładając, że użytkownik przez ten czas nie zmieni hasła ;-)

2) Pop-under na stronie kontaktu (i reklamacji)
Ciężko w to uwierzyć, ale zwyczajnie nie śledziliśmy ostatnich niusów na temat SweetCaptchy z której korzystaliśmy. Tak, powodem był serwis SweetCaptcha, gdzie należało nakarmić świnkę, aby się z nami skontaktować – wdrożony przez nas zewnętrzny serwis zamiast Google’owskiej reCaptchy, która swojego czasu była do przeskoczenia przez boty, a te lubiły zaspamować naszą skrzynkę.

Podsumowując całe wydarzenie, wszystkie dane użytkowników były i są bezpieczne, a reklamy… cóż, u mnie osobiście adblock sobie z tym radził.
Dziękujemy serdecznie za informację i czekamy na propozycję podziękowania za wskazanie błędu.

Na wszelki wypadek, wszystkim programistom aplikacji webowych proponujemy “grepnąć” swoje źródła pod kątem “lenght” — w końcu nie każdy serwis poza hasłem wymaga jeszcze PIN-u ;)

Przy okazji, przypadek Homepay’a — oraz ujawniony w weekend błąd na platformie Steam (por. Jak można było przejąć dowolne konto gracza) — kolejny raz pokazują, dlaczego warto wdrożyć w swoim serwisie dwuskładnikowe uwierzytelnienie

Za pomoc w weryfikacji błędu dziękujemy czytelnikom, MaTyyy i ITB Trade, którzy wyrazili gotowość użyczenia swoich konta do testów polegających na odtworzeniu błędu.

Przeczytaj także:


Dowiedz się, jak zabezpieczyć swoje dane i pieniądze przed cyberprzestępcami. Wpadnij na nasz kultowy ~3 godzinny wykład pt. "Jak nie dać się zhackować?" i poznaj kilkadziesiąt praktycznych i przede wszystkim prostych do zastosowania porad, które skutecznie podniosą Twoje bezpieczeństwo i pomogą ochronić przed atakami Twoich najbliższych. Uczestnicy tego wykładu oceniają go na: 9,34/10!

Na ten wykład powinien przyjść każdy, kto korzysta z internetu na smartfonie lub komputerze, prywatnie albo służbowo. Wykład prowadzimy prostym językiem, wiec zrozumie go każdy, także osoby spoza branży IT. Dlatego na wykład możesz spokojnie przyjść ze swoimi rodzicami lub mniej technicznymih znajomych. W najbliższych tygodniach będziemy w poniższych miastach:

Zobacz pełen opis wykładu klikając tutaj lub kup bilet na wykład klikając tu.

40 komentarzy

Dodaj komentarz
  1. “Generalnie, aby rzeczywiście przejąć konto, należałoby się dość dobrze nagimnastykować i poświęcić masę czasu na bruteforce 4 znakowego PINu – zakładając, że użytkownik przez ten czas nie zmieni hasła ;-)”

    Czyli nie ma limitu na ilość prób? W takim razie użytkownik dostaje smsa o treści: “Ktoś majstruje przy Twoim koncie. Raczej skutecznie.”

    • Przeczytałeś artykuł w całości? 3 błędne piny = 15 minut blokady. To chyba całkiem wystarczające rozwiązanie przeciwko atakowi brute force który potencjalnie mógł by sprawdzić wszystkie możliwe piny w ciągu kilku milisekund?

  2. Skoro już poruszyliście temat resetowania hasła i to, że często znajdujecie w testowanych serwisach tam błędy, drobna propozycja: może zrobicie jakiś ładny artykuł lub chociażby kompilację o tych błędach, czym mogą grozić i dlaczego tak ważne jest ich uniknięcie?

    • Dobry pomysł. Przejrzymy raporty i zbierzemy kompilacje błędów dot. tej funkcji.

  3. lenght czy length bo wydaje mi się że to drugie

  4. No i spoko
    Przyznali sie , skomentowali bez zadufanego podejscia co to nie my i u nas to nie mozliwe
    I like :)

  5. Apropo błędów na stronie. Czy w stopce niebezpiecznika treść: ‘Wszelkie prawa zastrzeżone © 2009- echo date(“Y”);’ jest poprawna ? ;)

    • Zaglądnij do źródeł strony :)

    • oczywiście, od lat wchodzący tu pierwszy raz nabierają się na to i piszą komentarze.

  6. Niby człowiekowi nie chce się później tego wszystkiego testować, ale jak kiedyś polecą pieniążki z konta bankowego, a nie tylko skargi, to trzeba ruszyć pupsko. :>

  7. O czym zapomniałem jeszcze wspomnieć to fakt, że błąd pojawił się około dwóch tygodni temu po zaplanowanej optymalizacji sporej części kodu. I to w zasadzie jedyny powód, dlaczego tak prastara funkcja została w ogóle ruszana.

  8. (lekkiDżołkModeŁon) wyczuwam php+brak testów = główna na niebezpieczniku

  9. “trzy próby wpisania błędnego PINu kończą się blokadą konta na 15 minut.”

    Przy tej restrykcji można sprawdzić 1 pin na 5 minut, czyli odgadniecie dobrego zajęłoby w najgorszym wypadku 34 dni, a to już można odnotować, chociażby prowadząc log błędnych logowan ;) Fakt faktem wielu użytkowników posiada pin 1234 lub 0000 :(

  10. 2009- echo date(“Y”); i hint=”ciekawe kto to zauwazy i czy napisze nam maila…”

    • Ha, dobre :D

    • To jest tam “od wieków”

    • A konkretnie dłużej niż “od zawsze” ;p

      nmsp

    • będe przysięgał że dałem “Reply” na koment Raf ‘a
      :/

  11. PHP to nie jest aż tak tragiczny język, o ile się zmieni parę idiotycznych, domyślnych ustawień. Chyba najważniejszym z nich jest ustawienie error_reporting na E_ALL…

    • Troszkę przekombinowałeś ;)
      error_reporting(0); <- wyświetlanie błedów userowi nie jest najlepszym pomysłem ;p
      zwykłe logowanie błedów do pliku jest duzo lepsze, a najlepiej własny, przemyśłany error handling :)

    • Nie wiem czy dobrze zrozumiałem, ale właśnie dużo początkujących programistów PHP ustawia error_reporting(0), bo myli jego funkcjonalność z display_errors – http://stackoverflow.com/questions/23436568/php-error-reporting-vs-display-errors – a precież jeśli ustawisz na 0 to nic nie trafi na ekran użytkownika, ale do logów też nie ;) Ale ogólnie to prawda, że najlepiej napisać własny handler. Tak czy siak, oni żadnej z tych opcji nie zastosowali poprawnie.

    • Od wyświetlania błędów jest display_errors, a nie funkcja error_reporting.

    • Oczywiście macie racje, skrót myślowy. :)

  12. też się ciągle mylę z “lenght” zamiast “length” ;)

  13. To już wiem skąd się wzięło słyne AAAAAAA sprzedam… ;)

  14. ile razy mam jeszcze pisac żebyście laskawie ruszyli zadki i zaczeli uznawac feedly androidowe za mobile? idzie sie wku*wic do bialosci jak za kazdym razem musze odpalac przegladarke zeby cokolwiek ubwas przeczytać. nie chcecie by do was zagladac? nie ma sprawy, da się załatwić.

    • To nie jest kwestia useragenta, a przeglądarki jaką twój android wykorzystuje do podglądu stron w Feedly. Nie rozumie ona schemy “//” , którą rozumie każda inna przeglądarka, a która jest wykorzystywana na stronach wspierających HTTP i HTTPS. Proponujemy zgłosić błąd producentowi (ew. Feedly).

    • o co tu właściwie chodzi z tymi dwoma ukośnikami? Jakiś przykład?

    • Choćby “<a href=”//jakasstrona.pl/link1”>.
      W zależności od tego, czy stronę serwujesz po HTTP czy po HTTPS, odpowiedni protokół sam “trafi” przed ukośniki.

  15. Pan Prezes mógłby się pochwalić, co to za narzędzia identyfikują włamywacza :)

  16. 3 próby co 15 minut = 288 prób na dobę – 4 cyfrowy pin = 10000 kombinacji – pin złamany max po 5 tygodniach.

  17. Coś jest nie tak z kolejnością komentarzy pod tym postem? nie są sortowane po dacie?

  18. I znowu debiloapostrof. Homepayu, Homepaya, przecież to y wymawiacie, więc po co ta błazenada z apostrofem?

  19. podejrzewam ze PIN w wysokim procencie to data urodzin samej osoby lub osoby bliskiej, co juz nie jest takie trudne do namierzenia. pozdrawiam

  20. To nie literówka w kodzie była tutaj problemem (to ZAWSZE może się zdarzyć). Ja widzę istotniejsze sprawy:
    a) dlaczego programista który pisał ten kod nie miał włączonych wszystkich warningów i notice dla PHP (to obecnie standard podczas developmentu).
    b) dlaczego nikt nie sprawdzał noticów i warningów z logów serwerów produkcyjnych (czy były w ogóle włączone?).
    c) dlaczego tak prosty błąd nie został zauważony podczas niezależnych testów (czy były przeprowadzone?)

    Moim zdaniem za wszystkie 3 problemy odpowiadają osoby zarządzające projektem od strony technologicznej (albo ich brak).

    • Skąd wyście wzięli to PHP? PHP nie ma funkcji do długości stringów, które zawierałyby w nazwie “length”. A wątpię, by pisali osobną metodę do sprawdzania długości stringa z losowymi znakami do hasła…

      Jeśli już, to śmierdzi mi to jakimś nodeJS, bo w JS length jest polem, nie metodą, a odczyt nieistniejącego pola nie rzuca domyślnie wyjątkami. Wklepcie sobie do konsoli:

      console.log((‘aaaaa’.lenght<6));
      console.log(('aaaaa'.length<6));

    • PS. zamieńcie apostrofy na zwykłe, bo wordpress jest gupi i pozmieniał na unicode.

    • Języki dynamiczne są jak socjalizm, skutecznie rozwiązują problemy nie znane w językach statycznie typowanych.

    • Jako ktoś mający przyjemność pracować z kodem PHP mającym 10+ lat – włączenie wyświetlania/logowania notice’ów, analiza i usunięcie przyczyn to robota na kilka tygodni non-stop.

      @kot
      Wystarczy wejść w ich ofertę pracy ;)

  21. ale pierdolicie ,tam jest 2 stopniowa autoryzacja haslo + pin

Odpowiadasz na komentarz Patrykgazing

Kliknij tu, aby anulować

Zamieszczając komentarz akceptujesz regulamin dodawania komentarzy. Przez moderację nie przejdą: wycieczki osobiste, komentarze nie na temat, wulgaryzmy.

RSS dla komentarzy: