Załóżmy, że mamy aplikację mobilną, która korzysta z chmury. Aplikacja przechowuje pewne ustawienia/dane specyficzne dla użytkownika, ale nie są to dane, których ujawnienie lub modyfikacja spowodowałyby koniec świata. W takim scenariuszu wymaganie uwierzytelnienia użytkownika może być nadmiarowe, wystarczająca będzie jego identyfikacja. Identyfikacja ta może odbywać się w sposób kompletnie dla użytkownika niezauważalny. Identyfikowana może być instancja aplikacji (konkretna instalacja) lub urządzenie, na którym ta aplikacja jest zainstalowana.
Gdy sekret nie jest sekretem
Na całą sprawę trzeba popatrzeć też nieco inaczej. Jeśli ktoś dostanie dostęp do czyichś danych, to nic wielkiego się nie dzieje, choć może to być prawdziwe tylko wtedy, gdy:
- ten dostęp do cudzych danych nie ma charakteru masowego,
- nie można skorelować "profilu" z konkretną osobą,
W związku z powyższym dobrze by było, gdyby wykorzystywany identyfikator był unikalny i trudny do przewidzenia. Nie powinien być również wykorzystywany do innych celów.
Dobre przykłady złych przykładów? Proszę bardzo.
Po pierwsze wartość ANDROID_ID (i analogiczne dla iOS). Ta wartość jest z reguły dostępna dla wszystkich aplikacji działających na urządzeniu, może być też wysyłana do serwerów. W rezultacie może się okazać, że wcale nie jest tak nieprzewidywalna (patrz: Antisec Leaks 1,000,001 UDIDs From A Trove Of 12 Million Allegedly Stolen From An FBI Laptop, Publishing firm: iOS UDID leak came from us, not the FBI), a i jest możliwość korelacji identyfikatora z konkretnym użytkownikiem.
Innym pomysłem jest użycie w roli unikalnego identyfikatora SHA1 (lub innego skrótu - szczegóły nieistotne) z adresu MAC karty WiFi, w niektórych przykładach nawet nie ma skrótu, na przykład: Determine MAC Address – UDID Alternative. Problem w tym, że adres MAC to tylko 48 bitów, z czego znaczna część bitów jest "ustalona", choćby na określenie producenta sprzętu. W rezultacie przestrzeń możliwych wartości adresu MAC konkretnych urządzeń jest na tyle niewielka, że może być efektywnie przeszukana. Poza tym adres MAC lata sobie w powietrzu, wystarczy znaleźć się wystarczająco blisko urządzenia i posłuchać.
Trafiają się również bardziej "złożone" pomysły, gdzie hash wyliczany jest nie tylko z adresu karty sieciowej, ale również np. informacji o wersji systemu. Również i w tym przypadku przestrzeń możliwych identyfikatorów może okazać się na tyle niewielka, że jej przeszukanie będzie realne/wykonalne.
Jeśli w aplikacji mobilnej potrzebny jest unikalny identyfikator, warto się zastanowić do czego on ma służyć. Warto zastanowić się, co mogłaby zrobić nieupoważniona (i potencjalnie - złośliwa) osoba, która pozna taki identyfikator. Jeśli ma ona jakiś potencjał do czynienia ZŁA (np. blokowanie dostępu do bankowości internetowej użytkownikom korzystających z aplikacji/urządzeń o konkretnym identyfikatorze), należy zadbać, by zadanie ustalenia/odgadnięcia takiego identyfikatora było jak najtrudniejsze dla atakującego. Dobrym identyfikatorem, w zasadzie "wystarczająco dobrym", może być po prostu GUID generowany przy pierwszym uruchomieniu aplikacji, pod warunkiem, że jest to GUID V4.
GUID V4 ma długość 128 bitów, z czego zdecydowana większość może być losowych. Większość, bo w GUID tego typu pokazuje się 4 w określonym miejscu (pierwsza cyfra w trzeciej grupie):
df021d16-0945-4357-b2fa-0f6bf3ca3007 4f283f31-6bcd-428a-895f-fbdaba2d4f5a 21c03d1b-1a89-41bb-b614-da76559950f3
Nieprzewidywalność GUID zależy od generatora liczb (pseudo)losowych, który jest wykorzystany do ich generowania. Może być taka sytuacja, w której generator PRNG jest "niskiej" jakości i atakujący na podstawie kilku kolejnych wygenerowanych wartości będzie w stanie określić wartości wygenerowane wcześniej, lub te, które dopiero zostaną wygenerowane.
Z drugiej strony w rozważanym scenariuszu nie ma jednego PRNG generującego GUID dla wszystkich aplikacji, tylko jest wiele PRNG, po jednym dla każdego urządzenia, które generują po jednym GUID dla każdej instancji aplikacji. Jeśli ktoś czegoś spektakularnie nie spieprzył (zdarzało się: Ron was wrong, Whit is right), to odtworzenie stanu PRNG na jednym urządzeniu nie powinno być przydatne do przewidzenia wskazań PRNG na innym.
Serwer i tak musi sprawdzić czy nie ma konfliktów (kiepski generator klienta) z identyfikatorami innych użytkowników.
No chyba, że ten "identyfikator" miałby działać jak swego rodzaju hasło i być wysyłany w parze z username.
Jeśli chodzi o potencjalną kolizję, to trzeba popatrzeć na rozmiar identyfikatora i ilość przewidywanych urządzeń (czyli wygenerowanych identyfikatorów), a przy okazji uwzględnić paradoks dnia urodzin. Oczywiście jeśli PRNG jest do niczego, to nasze wspaniałe wyliczenia na nic się nie przydadzą
Jaki procent sieci wifi jest niezabezpieczona lub zabezpieczona słabo (no dobra, tylko WEP zaliczam do "słabo")? Plus (tak się pisze, chodzi o iloczyn ), jaki procent serwisów dane o identyfikatorze prześle w sposób nieszyfrowany?
W ogóle całe zagadnienie trochę bez sensu jest, jak Bartosz zauważa. Toż to wieki temu zwykłe cookies załatwiały. Znaczy "załatwiały".
Jeśli mamy MAC i MAC jest używany do generowania w sposób deterministyczny unikalnego identyfikatora urządzenia (przykładowy hash), to jesteśmy w stanie sobie sami ten identyfikator "wyliczyć" i użyć przy bezpośrednim odwołaniu do usługi. Nie interesuje mnie co lata wewnątrz WPA2, SSL i innych magicznych skrótów typu VPN.
Może i zagadnienie jest bez sensu, ale jednak występuje "w prawdziwym świecie" i generowanie identyfikatorów w sposób przewidywalny pozwala atakującemu na dostęp do cudzych danych, czy na zwykłą złośliwość (blokowanie konta).
Cookies nie do końca rozwiązują problem, bo trzeba zadbać o to, by użytkownik (aplikacja) była identyfikowana w ten sam sposób przez cały czas życia aplikacji. Dałoby się to zrobić, ale stopień skomplikowania rośnie. No chyba, że cookie miałoby być "niezniszczalne", ale wtedy mamy sytuację z identyfikatorem generowanym przez serwer.
Dokładnie. Takie "wieczne" cookie załatwia temat generowania przez serwer. A że niekiedy będzie usunięte i będzie trzeba ustawić jakieś parametry od nowa? Cóż, sam na początku piszesz, że modyfikacja nie jest końcem świata.
Chyba łatwiej by było na konkretnym przykładzie dyskutować.
Teoretycznie powinna mogłaby wystarczyć para nazwa użytkownika i wskazanie tokenu, ale bywają takie rozwiązania, gdy jeden użytkownik może mieć wiele tokenów przywiązanych do siebie.
Token oczywiście można zablokować, jeśli zna się jego identyfikator. Jeśli identyfikator jest łatwy do przewidzenia, blokować można w sposób efektywny i w ten sposób złośliwie odcinać użytkownika/użytkowników od usługi. Zupełnie jest inaczej, jeśli raz na 2**64 prób udaje mi się trafić w istniejący identyfikator i komuś zablokować dostęp, inaczej, jeśli średnio na zablokowanie konta potrzebuję tych prób kilka(dziesiąt|set).