2013-03-19 13 views
21

Wdrażam usługę sieci Web REST, używając języka C#, który będzie hostowany na platformie Azure jako usługa w chmurze. Ponieważ jest to usługa REST, jest ona bezstanowa i dlatego nie ma plików cookie ani stanów sesji.Implementacja tokenu uwierzytelniania usługi REST Web Service

Dostęp do usługi internetowej można uzyskać tylko przez HTTPS (certyfikat dostarczany przez StartSSL.com).

Po zalogowaniu użytkownika do usługi otrzymają token zabezpieczający. Ten token zapewni uwierzytelnianie w przyszłej komunikacji.

Token będzie zawierać znacznik czasu, identyfikator użytkownika i adres IP klienta.

Cała komunikacja będzie się odbywała tylko przez HTTPS, więc nie przejmuję się przechwytywaniem tokena i jego użyciem w atakach powtórki; token i tak wygaśnie.

Jest to usługa publiczna, ale obawiam się, że ktoś mógł zarejestrować się w usłudze, zalogować się, a następnie zmodyfikować token, który otrzymuje, aby uzyskać dostęp do kont innych użytkowników.

Zastanawiam się, jak najlepiej zabezpieczyć zawartość tokena, a także sprawdzić, czy nie zostało naruszone.

Planuję wykonaniem poniższego zabezpieczyć Token:

klient pomyślnie loguje się do usługi, a usługa służy:

  1. Wygeneruj losową wartość hash i to z SHA256 1000 razy.
  2. Wygeneruj jednorazowy klucz sesji z klucza prywatnego + zakasowaną wartość losową.
  3. Skasuj klucz sesji z SHA256 1000 razy, a następnie użyj go do zaszyfrowania tokena
  4. Użyj klucza prywatnego, aby podpisać zaszyfrowany token za pomocą RSA.
  5. Wysyła zaszyfrowany token + podpis + zakasowaną losową wartość do klienta w niezaszyfrowanym pakiecie JSON.

Gdy klient dzwoni do usługi, wysyła zaszyfrowany token i podpis w niezaszyfrowanym pakiecie JSON do usługi. Usługa będzie

  1. Odtworzenie klucza sesyjnego z kluczem prywatnym + zaszyfrowany wartości losowej
  2. używać klucza prywatnego do weryfikacji podpisu
  3. użytku zaszyfrowany klucz sesji do odszyfrowania symbolicznego
  4. Sprawdzić, token nie upłynął
  5. dalej z żądaną operacją ...

ja naprawdę nie wiem nic o szyfrowaniu więc mam kilka pytań:

  1. Czy to wystarczy, czy jest to przesada?
  2. Przeczytałem, że aby wykryć sabotaż, powinienem dołączyć HMAC z tokenem. Ponieważ podpisuję się pod kluczem prywatnym, czy nadal potrzebuję HMAC?
  3. Czy powinienem używać Rijndael zamiast RSA?
  4. Jeśli preferuje się Rijndael, czy wygenerowany IV jest wymagany do odszyfrowania? np. czy mogę je wyrzucić, czy też muszę go wysłać zaszyfrowany token? na przykład Zaszyfrowany token + HMAC + IV + zakasował losową wartość.

Ponieważ cała komunikacja odbywa się za pośrednictwem protokołu HTTPS, niezaszyfrowany pakiet JSON nie jest tak naprawdę niezaszyfrowany, dopóki nie dotrze do klienta.

Również mogę chcieć ponownie wprowadzić usługę w PHP później, więc to wszystko musi być wykonalne również w PHP.

Dzięki za pomoc

Odpowiedz

24

Jesteś naprawdę nadmierne myślenie token. Prawdę mówiąc, najlepsza ochrona tokenowa zależy od losowości, a dokładniej od nieprzewidywalności. Najlepsze tokeny są całkowicie losowe. Ma Pan rację, że użytkownik zmodyfikuje swój token i użyje go do uzyskania dostępu do kont innych osób. Jest to typowy atak znany jako "kradzież sesji". Atak ten jest prawie niemożliwy, gdy żetony są losowo generowane i wygasają po stronie serwera. Używanie informacji użytkownika, takich jak adres IP i/lub sygnatura czasowa, jest złą praktyką, ponieważ poprawia przewidywalność. Zrobiłem atak w college'u, który z powodzeniem odgadł aktywne żetony, które były oparte na znacznikach czasu serwera w mikrosekundach. Autor wniosku pomyślał, że mikrosekundy zmienią się na tyle szybko, że będą nieprzewidywalne, ale tak nie było.

Należy mieć świadomość, że gdy użytkownicy znajdują się za serwerami proxy, serwer proxy będzie czasami wyświetlał żądania SSL w postaci zwykłego tekstu (ze względów bezpieczeństwa wiele serwerów proxy przeprowadzi dokładną inspekcję pakietów). Z tego powodu dobrze jest, aby wygasać sesji. Gdyby nie twoi użytkownicy byliby podatni na atak taki jak ten, a także możliwe XSS i CSRF.

RSA lub Rijndael powinny być wystarczające, pod warunkiem, że mają rozsądną długość klucza. Powinieneś także użyć HMAC z tokenem, aby zapobiec manipulacjom, nawet jeśli je podpisujesz. Teoretycznie byłoby to zbyteczne, ponieważ podpisujesz się kluczem prywatnym. Jednak HMAC jest bardzo dobrze przetestowany, a twoja implementacja mechanizmu podpisywania może być wadliwa. Z tego powodu lepiej jest używać HMAC. Byłbyś zaskoczony, jak wiele wdrożeń zabezpieczeń "roll your own" ma braki, które prowadzą do kompromisu.

Brzmisz całkiem nieźle na temat bezpieczeństwa. Tak trzymaj! Potrzebujemy więcej świadomych bezpieczeństwa programistów na tym świecie.

EDIT:

Uważa się bezpiecznie zawierać znaczniki czasu/identyfikatorów użytkowników w tokena tak długo, jak są one szyfrowane przy użyciu silnego symetrycznego tajnego klucza (jak AES, Blowfish, etc), że tylko serwer ma i tak długo, jak token zawiera odporny na manipulację skrót, taki jak HMAC, , który jest szyfrowany tajnym kluczem wraz z ID użytkownika/sygnaturą czasową. Skrót gwarantuje integralność, a szyfrowanie gwarantuje poufność.

Jeśli w szyfrowaniu nie zostanie uwzględniony HMAC (lub inny skrót), użytkownicy mogą ingerować w zaszyfrowany token i odszyfrować go do czegoś ważnego. Zrobiłem atak na serwerze, w którym identyfikator użytkownika i sygnatura czasowa zostały zaszyfrowane i użyte jako token bez hasha. Zmieniając jeden losowy znak w ciągu, mogłem zmienić swój identyfikator użytkownika z czegoś w rodzaju 58762 na 58531. Chociaż nie mogłem wybrać "nowego" ID użytkownika, udało mi się uzyskać dostęp do konta kogoś innego (było to w środowisku akademickim w ramach kursu).

Alternatywą jest użycie całkowicie losowej wartości tokena i odwzorowanie jej po stronie serwera na przechowywany identyfikator użytkownika/sygnaturę czasową (która pozostaje po stronie serwera i dlatego znajduje się poza kontrolą klientów). Zajmuje to trochę więcej pamięci i mocy obliczeniowej, ale jest bezpieczniejsze. Jest to decyzja, którą musisz podjąć indywidualnie dla każdego przypadku.

Jeśli chodzi o ponowne użycie kluczy pochodzących z IV i innych kluczy, zwykle jest to w porządku, pod warunkiem, że klucze są ważne tylko przez krótki czas. Matematycznie jest mało prawdopodobne, że ktoś może je złamać. Jest to jednak możliwe. Jeśli chcesz przejść przez paranoidalną trasę (którą zwykle robię), generuj losowo wszystkie nowe klucze.

+0

Dzięki za to. Postanowiłem użyć Rijndael i HMAC, ale wciąż staram się o tym przekonać. Czy mogę użyć IV do wyprowadzenia klucza sesji z klucza głównego? Czy mogę również użyć tego samego klucza sesji dla HMAC lub czy muszę uzyskać nowy klucz z bieżącego klucza sesji? Jeśli potrzebuję nowego klucza do HMAC, czy mogę użyć obecnego IV do tego, czy potrzebuję również nowej wartości losowej? Na koniec wspomniałeś, że nie powinienem szyfrować sygnatury czasowej identyfikatorem użytkownika, skąd więc mogę stwierdzić, że token wygasł? ponieważ nie mogę zapisać rekordu sesji w bazie danych. Dzięki jeszcze raz. –

+0

Świetne pytania. Zaktualizuję odpowiedź kilkoma dodatkowymi informacjami. –

+0

Ok, rozumiem. Więc HMAC jest obliczany na podstawie niezaszyfrowanych danych, a następnie szyfrowany danymi? Czy muszę przechowywać HMAC na serwerze, aby móc go później porównać, czy mogę odszyfrować token, a następnie obliczyć HMAC z niezaszyfrowanych danych i porównać je z HMAC, który został zaszyfrowany danymi? –

Powiązane problemy