Niewinna dziura związana z prywatnością w Gravatarze – jak bot może upewnić się że zgadł twój e-mail

Posted: 2010/03/11 by wildwezyr in Programistycznie i technicznie
Tagi: , , , ,

Jak wiadomo serwis Gravatar służy do tworzenia globalnie rozpoznawalnych avatarów (ang. Globally Recognized Avatars). Aktualnie coraz więcej serwisów ma wbudowaną integrację z Gravatarem: WordPress (jako skrypt i jako serwis WordPress.com), StackExchange i jego najpopularniejszy serwis StackOverflow itd. itp.

Działanie Gravatarów opiera się na adresie email, który gdzieś podajemy – np. wrzucając wpis na bloga, zakładając konto na serwisie społecznościowym itp.

Link do obrazka wygląda zawsze tak:

http://www.gravatar.com/avatar/<md5-z-emaila>?<jakieś-dodatkowe-parametry>

Przykładowo mój obrazek na blogu antyweb.pl:

http://www.gravatar.com/avatar/8685bca2b36cbdf0f296b189d43789a6?s=48&d=http%3A%2F%2Fantyweb.pl%2Fwp-content%2Fthemes%2Fsmitu%2Fimages%2Favatar_antyweb.jpg%3Fs%3D48&r=G

oraz na StackOverflow.com:

http://www.gravatar.com/avatar/8685bca2b36cbdf0f296b189d43789a6?s=32&d=identicon&r=PG

Jak widać wyliczony skrót MD5 dla mojego adresu email to: 8685bca2b36cbdf0f296b189d43789a6. Oczywiście nie da się z tego odtworzyć mojego adresu, więc niby OK – nie można napisać bota, który sobie weźmie stronę antyweb.pl albo StackOverflow.com i odczyta z adresów do obrazków adresy e-mail…

A jednak istnieje metoda na uzyskanie potwierdzonego adresu e-mail – wystarczy pobawić się z nickiem użytkownika i próbować jakoś dokleić do niego jakiś adres serwera mailowego. Metoda nie jest 100% skuteczna, bo serwer mailowy jaki podałem może być np. mój firmowy, ale… sporo ludzi używa przecież maili na gmail.com, yahoo.com czy tam jeszcze gdzieś. Druga sprawa, która przeszkadza to możliwość użycia innego nicka niż nazwa użytkownika w emailu. Ja jednak mam taki sam nick jak nazwę użytkownika, sporo ludzi też tak robi. Bo czemu by nie?

O ile kandydatów na adres email można przecież tworzyć na podstawie samego nicka w jakimś serwisie, to sprawdzenie jeszcze czy gravatar tego użytkownika ma właściwy skrót MD5 z naszym kandydatem daje 100% potwierdzenie, że oto mamy w ręku zgadnięty dobry adres.

W taki sposób można sprawdzić też np. czy na jakiejś stronie pod nickiem „bart” ukrywa się mój znajomy Bartek (którego maila znam) – o ile podał tam jeden ze znanych mi swoich adresów e-mail…

Jakie są konsekwencje powyższej dziury? Nie wiem – wydaje się to niegroźne. Raczej jest to kwestia świadomości – gdy zostawiamy gdzieś swój adres e-mail nie zawsze jest tak, że nikt nie odkryje jaki adres podaliśmy… A wydawało się, że w serwisie napisali: *adres email wymagany, ale nie zostanie nigdy ujawniony* ;-). Czy aby na pewno?

Jeśli ktoś jest chętny – dysponuję swoim kodem w Javie który testuje nicki + md5 używane przez Gravatara i próbuje zgadnąć email na popularnych serwerach pocztowych. Nie zawsze mu się to udaje – z powodów opisanych powyżej, ale jak już dopasuje poprawnie, to jest 100% pewności – twój adres nie jest tajemnicą!

Reklamy
Komentarze
  1. […] w której bierze udział Piotr Tymochowicz (prawdopodobnie on). Za pomocą opisanej wcześniej metody (programu w Javie jaki do tego napisałem) znam ze 100% pewności adres e-mail jaki Piotr […]

  2. SiliconMind pisze:

    A wystarczyłoby posolić 🙂

    • wildwezyr pisze:

      ale jakim cudem? też na początku myślałem, że wystarczy odrobina soli, ale – po namyśle jak to w praktyce zrobić widzę, że nie bardzo jest jak.

      wg. mnie jedyny sensowny sposób to jednak szyfrowanie za pomocą kluczy publiczny/prywatny – zamiast stosowania MD5…

      jeśli jednak masz pomysł jak solić – napisz jaki. jak solić, aby nie przesolić?

      • SiliconMind pisze:

        Gravatarowy serwer mógłby przechowywać hashe posolonych adresów e-mail i tylko takie publikować. Jeśli nie wiesz jakiej soli używa gravatar, twoja metoda jest kompletnie nieskuteczna.

        Aby miało to sens, to każdy hash przechowywany w bazie powinien być solony inną solą – np. timestamp (a jeszcze lepiej jakiś microtime) dla danego wiersza w tabeli. Zwiększa to wprawdzie ilość danych, które trzeba przechowywać w bazie, ale jednocześnie kolosalnie zwiększa też bezpieczeństwo.

        Normalnie, czyli w przypadku haseł, sól trzyma się osobno – na wypadek wycieku bazy danych użytkowników. Ale tu nie ma to znaczenia, bo chcemy bronić się przed ujawnieniem adresu e-mail, a ten i tak by został odkryty w przypadku wycieku 🙂

  3. wildwezyr pisze:

    SiliconMind :

    Gravatarowy serwer mógłby przechowywać hashe posolonych adresów e-mail i tylko takie publikować. Jeśli nie wiesz jakiej soli używa gravatar, twoja metoda jest kompletnie nieskuteczna.

    Aby miało to sens, to każdy hash przechowywany w bazie powinien być solony inną solą – np. timestamp (a jeszcze lepiej jakiś microtime) dla danego wiersza w tabeli. Zwiększa to wprawdzie ilość danych, które trzeba przechowywać w bazie, ale jednocześnie kolosalnie zwiększa też bezpieczeństwo.

    Normalnie, czyli w przypadku haseł, sól trzyma się osobno – na wypadek wycieku bazy danych użytkowników. Ale tu nie ma to znaczenia, bo chcemy bronić się przed ujawnieniem adresu e-mail, a ten i tak by został odkryty w przypadku wycieku :)

    Czekaj, nie rozumiem. Ale jaki adres do obrazka gravatarowego generowałby potem blog? Skąd blog znałby wartość tej soli? Czy generowałby urle bez uwzględniania soli? Tu jest cała słabość – każdy blog używający gravatarów musi wygenerować url na podstawie znanego mu adresu e-mail, teraz robi to używając MD5 bez solenia, ale aby posolić – musi znać wartość soli, czy nie? Wydaje mi się że przez ten problem nie da rady solić…?

    • SiliconMind pisze:

      Lol, faktycznie. Zapomniałem, że to blog generuje linka do gravatara 🙂

      Można by to obejść na takiej zasadzie, że każdy blog, który chce używać gravatara musi najpierw dostać swój klucz do solenia, wtedy nie byłoby problemu. W sumie nie jest to jakoś szczególnie kłopotliwe – plugin przy instalacji mógłby nawet sam poprosić serwer gravatara o identyfikator i sól dla siebie. To by załatwiło sprawę. Identyfikator byłby jawny, przekazany w linku razem z zahashowanym i posolonym już mailem. Sól byłaby wspólną tajemnicą 🙂

      Więc choć najpierw się trochę zapętliłem, to jednak wychodzi na to, że solić można 🙂 To nawet wydaje się prostsze niż moje pierwotne dywagacje. Wymaga mniej dodatkowych danych, bo potrzebna jest tylko tabela z identyfikatorami blogów i solą do nich przypisaną.

      • wildwezyr pisze:

        hehe. też nad tym myślałem.

        w takim przypadku problem straszny ma gravatar – musi pamiętać każdy możliwy mail z każdą solą każdego serwisu.

        bo robisz tak: mierzesz maila + sól i to poddajesz hashowaniu MD5. takie coś jest skrótem, którego z żaden sposób nie wyciągniesz maila nawet jeśli znasz sól (bo jesteś serwisem gravatar, który zgodnie z twoim pomysłem zna sól).

        więc skoro do gravatara przychodzi link ze skrótem MD5 w którym jest mail z solą. teraz oni nie mają jak z tego skrótu MD5 wyciągnąć maila znając sól. tak działają funkcje skrótu – to ich generalnie zaleta, ale w tym przypadku wada…

        A więc aby sobie to obejść – serwis Gravatar musiałby przejrzeć wszystkie swoje zarejestrowane maile i łączyć każdy z nich ze znaną solą, generować MD5 i patrzeć co wyjdzie. I jak wyjdzie te MD5 co zostało podane w linku, to bingo.

        Drugi problem jest taki, że serwis gravatar generuje domyślne unikalne avatary nawet jak nie podasz u nich żadnego swojego avatara. U mnie masz właśnie taki avatar ;-). Więc gravatary działają nawet jak serwis gravatar nie ma zarejestrowanego adresu e-mail. A to już zupełnie wyklucza podaną metodę iteracji po wszystkich e-mailach w celu znalezienia właściwego.

        Mam nadzieję, że rozumiesz mój powyższy wywód ;-). Jeśli nie mam racji – napisz co skopałem albo czego nie idzie zrozumieć…

      • wildwezyr pisze:

        jeszcze: wydaje mi się, że jedynym sensownym pomysłem jest szyfrowanie (np. kluczem asymetrycznym).

        przykładowo: serwis gravatar udostępnia klucz publiczny – a każdy blog tym kluczem szyfruje maila i to jest przekazywane w URL.

        nikt inny – poza znającym klucz prywatny serwisem Gravatar – nie jest w stanie rozszyfrować maila, a serwis gravatar – jest w stanie bo ma ten swój klucz prywatny i tylko za jego pomocą można rozszyfrować.

        innej sensownej metody na razie nie widzę. można ew. ją usprawnić (wzmocnić kryptograficznie) poprzez rejestrowanie się każdego bloga na serwisie gravatar i ustanawianie pary kluczy publiczny/prywatny – pomiędzy blogiem a gravatarem i każdy blog miałby swój klucz „publiczny” dla siebie i nie powinien go ujawniać.

  4. SiliconMind pisze:

    wildwezyr :
    bo robisz tak: mierzesz maila + sól i to poddajesz hashowaniu MD5. takie coś jest skrótem, którego z żaden sposób nie wyciągniesz maila nawet jeśli znasz sól (bo jesteś serwisem gravatar, który zgodnie z twoim pomysłem zna sól).
    więc skoro do gravatara przychodzi link ze skrótem MD5 w którym jest mail z solą. teraz oni nie mają jak z tego skrótu MD5 wyciągnąć maila znając sól. tak działają funkcje skrótu – to ich generalnie zaleta, ale w tym przypadku wada…

    Ale po co chcesz z hasha wyciągać adres e-mail? Można odwrotnie.
    Prosty przykład dla MySQL, na szybko bez walidacji:
    SELECT avatar FROM users u, sites s WHERE MD5(CONCAT(u.mail, s.salt)) = ‚HASH_Z_BLOGA’ AND s.id = ID_BLOGA

    Tylko tak sobie myślę, że to mogłoby być trochę mało efektywne, ale jak najbardziej realne 🙂 Choć coś mi się zdaje, że pewnie gravatar cachuje, więc przewalanie całej tabeli przez MD5() odbywałoby się raz na jakiś czas dla danej kombinacji bloga i adresu e-mail.

    No ale jasne, asymetrycznie też można, tylko implementacja po stronie klienta byłaby bardziej problematyczna. Rzadko kiedy serwery mają domyślnie włączoną obsługę gpg dla php.

    Heh, to w sumie ciekawy problem – co byłoby bardziej efektywne? Szyfrowanie asymetryczne kluczem publicznym i potem deszyfrowanie prywatnym przez gravatara, czy przepuszczanie całej tabeli z mailami przez MD5?

    • wildwezyr pisze:

      No dokładnie napisałeś to co ja:

      A więc aby sobie to obejść – serwis Gravatar musiałby przejrzeć wszystkie swoje zarejestrowane maile i łączyć każdy z nich ze znaną solą, generować MD5 i patrzeć co wyjdzie. I jak wyjdzie te MD5 co zostało podane w linku, to bingo.

      😉 Taki właśnie kod jak podałeś by to zrobił. Z moich testów prędkość generowania skrótu MD5 to (rząd wielkości): 175 438 hashy/sekundę. Czyli jeśli w bazie mają 1 mln adresów, to jedno żądanie wyciągnięcia avatara trwałoby… 5.7 sekundy na samo znalezienie który to obrazek. Masakra. Konieczne byłoby jakieś cache’owanie. Ale wydaje się, że to sporo danych (rzadka macierz użytkownik x blog na jakim coś napisał)…

      Ale to i tak nie jest możliwe. Powodem jest to, że nie muszę mieć zarejestrowanego gravatara, nie muszę mieć konta na gravatar.com a i tak dostanę fajnego avatara – domyślnego i to wg kilku stylów generowania. U mnie są kalejdoskopowe, a na np. http://komorkomania.pl masz inne (takie mordki). Tych typów jest kilka i dla nieznanych maili to działa, ale takie przeszukiwanie tabeli userów – nie zadziała…

      Nie używam PHP, więc nie wiedziałem, że trzeba jakiejś biblioteki poza standardem do szyfrowania. Ale może blogi wordpressowe mają do niej domyślnie dostęp? Wydaje się, że cache’owanie zaszyfrowanych adresów e-mail może być prostsze i będzie działać też dla e-maili niezarejestrowanych na gravatars.com (zapewne domyślne avatary dla niezarejestrowanych użytkowników są jakoś cache’owane).

      • SiliconMind pisze:

        Mój serwer na zahashowanie 1mln adresów e-mail potrzebował niewiele ponad pół sekundy (0,54). A to nie jest żadna Über-maszyna 🙂

        Używając cache (dla kombinacji adresu e-mail i bloga) można by pewnie sporo oszczędzić. Ale to tylko dywagacje. Nie mam pojęcia jakby to wyszło w praktyce.

        Ale to i tak nie jest możliwe. Powodem jest to, że nie muszę mieć zarejestrowanego gravatara, nie muszę mieć konta na gravatar.com

        Przyznam, że tu kłania się ponownie moja nieznajomość gravatara. Nie używam ani wordpresa ani tym bardziej tego serwisu. Więc nie do końca jestem świadomy tego jak on działa. Jednak, teraz też przecież muszą sobie jakoś z tym radzić dla niezarejestrowanych userów. Przecież nie wiadomo jaki jest ten zahashowany adres e-mail. Więc pewnie i tak posługują się jakąś osobną tabelą dla tych przypadków. Można więc to też uwzględnić przy solonym rozwiązaniu i potem sprawdzać w kolejności od najmniej kosztownego procesu wyszukiwania, do najbardziej.

        Jednak tak jak pisałem na początku to tylko dywagacje. Nie mam pojęcia jakby to wyszło w praktyce.

        Zacząłem ten wątek, bo nie byłem do końca świadomy jak działa gravatar. Pociągnąłem go dalej, bo sam byłem ciekaw, czy można jakoś rozwiązać ten problem. Teoretycznie się da, jedyna bariera, to złożoność obliczeniowa po stronie serwera. Po prostu – odpowiednio mocny serwer by sobie z tym poradził.

        Z kryptografią asymetryczną problem jest taki jak pisałem. Może serwer wordpress ma dostęp do tej biblioteki, a może nie. Nie wiem, ale zostają też wszyscy inni, którzy mają własną instancję wordpressa. Ale nawet jakby ten detal pominąć, to problem złożoności nadal pozostaje, tylko rozkłada się on na większą liczbę maszyn – nie tylko trzeba szyfrować każdy wychodzący do gravatara adres e-mail. Gravatar musi każdy taki adres odszyfrowywać i dopiero wtedy poszukać w bazie. No i dochodzi jeszcze problem długości ciągu znaków z zaszyfrowanym adresem. Tak wygląda zwykły adres e-mail przepuszczony przez RSA 🙂

        hQIOA1E1V8sc3VqhEAgAv9PKkfDLd5szzAq3UtW/ruJv5hVKmOAI0cRVoOwvjVdB
        ts21+dsjfjE7JafNjIbDbQLSxxXi6Sef+/Rkc61eOPz7ltmUwOPXgAIE2nQjHBPK
        ooi0o0RtwD/Glk/NwBSlDM4+jnum0tG/cm+dOIPP3U+3xRvV8MZUooM14DZxBbO6
        5crImYx+lT0dpC8JOwFQSp3+HUSWDfJ1nwEtTEisA1kkwgOaUrMY9Wng7y4WdKQH
        fEAgpHK/JD5Q1QE783dphC9kqnF6p61oNDEN3e8k6y/Mj+zu6b971tzzmdAJDQLN
        dHNurN/GoNJO32ovdyxsG29Pe6FOGcU8OcujzDjtzwgAsnA4jQneaNPwU7ROYM75
        p2K/8HrlMcxVykRrO6nN/T3AV/JFFfYezwQ/OW45FqznmxmPDoQlgD0T1EGL9Wy1
        2aLqMC1MOAm+8gbzwidaH3L7xyy1PTrle8i5UE04AvQDDyapnwdkOkGbiNYF0s6A
        dz8xgmBvfR9LijnEfKzfg+cUzw/ds+Dxvyikr/85croFIcUnC/awFf5wHaRUpCCC
        gJIkaLnFOKdBqAjFHzv2j2MEKXFWrwcNzEccSdSoGZyc20HHJFR5fEB/x/y2hAvb
        Vf5lA7Ti6QjF/gbRVJv1orc3vOyur2BKqvFVhCcExdMkVPxkP78aW9IEPJ03sfm8
        7tJXAcbftfzXWV6FaScodayEZ1ZTFUDEhGC4WboHf3atGSI5NZfpcrlMp2edRuEN
        HHoK2P5sgut3Qch+82dWz7Zaw70mZHbTAvavqMzrVAPdbWumcvVF36rz
        =Fx+k

        Trochę dużo do przekazywania metodą GET 🙂

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s