Tło:
Projektuję schemat uwierzytelniania dla usługi internetowej REST. To nie „naprawdę” musi być bezpieczne (jest to bardziej osobisty projekt), ale chcę, aby było to tak bezpieczne, jak to możliwe, jako ćwiczenie / nauka. Nie chcę używać protokołu SSL, ponieważ nie chcę problemów i, głównie, kosztów związanych z jego konfiguracją.
Te pytania SO były szczególnie przydatne na początek:
- RESTful Authentication
- Najlepsze praktyki dotyczące zabezpieczania interfejsu API / usługi REST
- Przykłady najlepszych internetowych interfejsów API SOAP / REST / RPC? A dlaczego je lubisz? A co z nimi nie tak?
Zastanawiam się nad użyciem uproszczonej wersji uwierzytelniania Amazon S3 (lubię OAuth, ale wydaje się to zbyt skomplikowane dla moich potrzeb). Do żądania dodaję losowo generowaną wartość jednorazową , dostarczoną przez serwer, aby zapobiec atakom związanym z odtwarzaniem.
Aby przejść do pytania:
Zarówno S3, jak i OAuth polegają na podpisywaniu adresu URL żądania wraz z kilkoma wybranymi nagłówkami. Żadne z nich nie podpisuje treści żądania POST lub PUT. Czy nie jest to podatne na atak typu man-in-the-middle, który utrzymuje adres URL i nagłówki oraz zastępuje treść żądania dowolnymi danymi, których chce atakujący?
Wygląda na to, że mogę się temu zapobiec, włączając hash treści żądania do podpisywanego ciągu. Czy to jest bezpieczne?
Odpowiedzi:
Poprzednia odpowiedź wspomniała tylko o SSL w kontekście przesyłania danych i tak naprawdę nie obejmowała uwierzytelnienia.
Naprawdę pytasz o bezpieczne uwierzytelnianie klientów interfejsu API REST. O ile nie używasz uwierzytelniania klienta TLS, sam SSL NIE jest realnym mechanizmem uwierzytelniania dla interfejsu API REST. SSL bez uwierzytelniania klienta uwierzytelnia tylko serwer , co nie ma znaczenia dla większości interfejsów API REST, ponieważ naprawdę chcesz uwierzytelnić klienta .
Jeśli nie korzystasz z uwierzytelniania klienta TLS, musisz użyć schematu uwierzytelniania opartego na skrócie (takiego jak niestandardowy schemat Amazon Web Service) lub OAuth 1.0a lub nawet podstawowego uwierzytelniania HTTP (ale tylko przez SSL).
Schematy te potwierdzają, że żądanie zostało wysłane przez kogoś oczekiwanego. TLS (SSL) (bez uwierzytelnienia klienta) zapewnia, że dane przesyłane przewodowo pozostają nienaruszone. Są to odrębne - ale uzupełniające się - obawy.
Dla zainteresowanych rozszerzyłem pytanie SO na temat schematów uwierzytelniania HTTP i ich działania .
źródło
REST oznacza pracę ze standardami sieci, a standardem „bezpiecznego” transferu w sieci jest SSL. Wszystko inne będzie trochę funky i wymagać będzie dodatkowych nakładów na wdrożenie dla klientów, którzy będą musieli mieć dostępne biblioteki szyfrujące.
Po przejściu na protokół SSL w zasadzie nie ma nic fantazyjnego. Możesz ponownie przejść do standardów internetowych i użyć uwierzytelniania podstawowego HTTP (nazwa użytkownika i tajny token wysyłane wraz z każdym żądaniem), ponieważ jest to znacznie prostsze niż skomplikowany protokół podpisywania i nadal skuteczne w kontekście bezpiecznego połączenia. Musisz tylko upewnić się, że hasło nigdy nie przechodzi przez zwykły tekst; więc jeśli hasło zostanie kiedykolwiek otrzymane przez zwykłe połączenie tekstowe, możesz nawet je wyłączyć i wysłać pocztą do programisty. Powinieneś również upewnić się, że poświadczenia nie są nigdzie rejestrowane po otrzymaniu, tak jak nie logowałbyś zwykłego hasła.
HTTP Digest to bezpieczniejsze podejście, ponieważ zapobiega przekazywaniu tajnego tokena; zamiast tego jest to skrót, który serwer może zweryfikować na drugim końcu. Chociaż może to być przesada w przypadku mniej wrażliwych aplikacji, jeśli zastosujesz środki ostrożności wymienione powyżej. W końcu hasło użytkownika jest już przesyłane w postaci zwykłego tekstu podczas logowania (chyba że robisz jakieś fantazyjne szyfrowanie JavaScript w przeglądarce), a także ich pliki cookie na każde żądanie.
Zauważ, że w przypadku interfejsów API lepiej, aby klient przekazywał tokeny - losowo generowane ciągi - zamiast hasła, za pomocą którego programista loguje się na stronie internetowej. Dlatego programista powinien mieć możliwość zalogowania się do Twojej witryny i wygenerowania nowych tokenów, których można użyć do weryfikacji interfejsu API.
Głównym powodem korzystania z tokena jest to, że można go wymienić, jeśli zostanie naruszony, podczas gdy w przypadku naruszenia hasła właściciel może zalogować się na konto programisty i zrobić z nim wszystko, co chce. Kolejną zaletą tokenów jest to, że możesz wydawać wiele tokenów tym samym programistom. Być może dlatego, że mają wiele aplikacji lub dlatego, że chcą tokenów o różnych poziomach dostępu.
(Zaktualizowano w celu uwzględnienia skutków utworzenia połączenia tylko SSL).
źródło
Możesz też użyć znanego rozwiązania tego problemu i użyć protokołu SSL. Certyfikaty z podpisem własnym są bezpłatne, a to osobisty projekt, prawda?
źródło
Jeśli potrzebujesz skrótu treści jako jednego z parametrów w adresie URL i ten adres URL jest podpisany za pomocą klucza prywatnego, wówczas atak typu man-in-the-middle byłby w stanie zastąpić treść treścią, która wygenerowałaby ten sam skrót. Łatwe do zrobienia z wartościami skrótu MD5 przynajmniej teraz, a gdy SHA-1 jest zepsuty, cóż, otrzymujesz obraz.
Aby zabezpieczyć ciało przed sabotażem, trzeba będzie wymagać podpisu ciała, co jest mniej prawdopodobne, że atak człowieka w środku będzie w stanie złamać, ponieważ nie znają klucza prywatnego, który generuje podpis .
źródło
W rzeczywistości, oryginalny S3 auth nie pozwalają za treść ma zostać podpisana, choć ze słabym podpisu MD5. Możesz po prostu wymusić ich opcjonalną praktykę włączania nagłówka Content-MD5 do HMAC (ciąg do podpisania).
http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html
Ich nowy schemat uwierzytelniania v4 jest bezpieczniejszy.
http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
źródło
Pamiętaj, że twoje sugestie utrudniają klientom komunikację z serwerem. Muszą zrozumieć twoje innowacyjne rozwiązanie i odpowiednio zaszyfrować dane, ten model nie jest tak dobry dla publicznego API (chyba że jesteś amazon \ yahoo \ google ..).
W każdym razie, jeśli musisz zaszyfrować treść, proponuję sprawdzić istniejące standardy i rozwiązania, takie jak:
Szyfrowanie XML (standard W3C)
Zabezpieczenia XML
źródło