Bezpieczeństwo schematów uwierzytelniania REST

228

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:

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?

dF.
źródło
6
Amazon S3 może zawierać Content-MD5 jako część ciągu nagłówka, aby zapobiec opisywanemu atakowi MITM.
laz
8
MD5 jest bardzo słabą funkcją skrótu i ​​od wielu lat nie zaleca się jej używania: en.wikipedia.org/wiki/MD5 . Użyj SHA2 w dzisiejszych czasach. MD5 to szminka na świni z kryzysem tożsamości.
Henrik
6
Startcom zapewnia bezpłatne certyfikaty SSL, które nie generują ostrzeżeń o certyfikatach w głównych przeglądarkach
Plato,
5
@SeanKAnderson (rant: Uważam za absurdalne, jak ludzie mówią o 99,99999% s, gdy Internet jest oblegany przez agencje szpiegowskie, które zautomatyzowały DUŻĄ liczbę ataków już w 2008 roku - to taki dziwny sposób radzenia sobie z prawdziwym problemem - „Naaah, to nie będzie problem; moja babcia nie będzie w stanie go zhakować”
Henrik
2
@Plato Polecam LetsEncrypt w tych dniach za darmo certyfikaty SSL
transfer87

Odpowiedzi:

168

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 .

Les Hazlewood
źródło
16
Dokładnie. Jedyną rzeczą, którą SSL weryfikuje, jeśli chodzi o interfejs API, jest to, że wywołanie, z którym ma do czynienia, nie zostało pomieszane z trasą. Interfejs API wciąż nie ma pojęcia, kto z nim rozmawia ani czy w ogóle powinien mieć do niego dostęp.
Tim Gautier
1
Dobra odpowiedź. Poleciłbym również rzucić okiem na te doskonałe zasoby .. owasp.org/index.php/Web_Service_Security_Cheat_Sheet i owasp.org/index.php/REST_Security_Cheat_Sheet (DRAFT)
dodgy_coder
2
To tylko drobna uwaga, ale korzystanie z protokołu SSL ma również dodatkową zaletę, polegającą na zapobieganiu podsłuchom i atakom typu man in the middle.
dodgy_coder,
@Les Hazlewood Czy możesz wyjaśnić, w jaki sposób podstawowe uwierzytelnianie HTTP za pomocą protokołu HTTP może pomóc ustalić, czy serwer wie, z kim rozmawia?
Wiosna,
@ Les Hazlewood tutaj zadałem to pytanie; tnx stackoverflow.com/questions/14043397/…
Wiosna,
60

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).

mahemoff
źródło
3
Myślę, że możesz dostać certyfikat GoDaddy ssl za około 30 USD rocznie. Byłem zszokowany, gdy zobaczyłem, ile kosztują certyfikaty Verisign SSL (600 USD rocznie czy coś, jeśli dobrze pamiętam?) Ale opcja GoDaddy jest całkowicie wykonalna.
Brian Armstrong,
19
O ile nie używasz wzajemnego uwierzytelniania SSL / TLS, a serwer używany przez użytkownika / klienta jest zaufany, oznacza to, że użytkownik nie uwierzytelnił użytkownika na serwerze / aplikacji. Musisz zrobić coś więcej, aby uwierzytelnić użytkownika na serwerze / aplikacji.
Pauld
5
Ryan: Szyfrowanie SSL w dzisiejszych czasach wymaga niewielkiej mocy obliczeniowej w porównaniu do tego, czego użyłbyś do wygenerowania odpowiedzi za pomocą frameworka aplikacji internetowych, takiego jak Django lub Rails itp.
Cameron Walsh
4
Certyfikaty z Startcom są bezpłatne i powszechnie uznawane. cacert.org to otwarta alternatywa z mniejszym uznaniem
Dima Tisnek
17
To nie dotyczy pytania dotyczącego uwierzytelnienia.
Sam Stainsby
8

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?

najdziwniejszy
źródło
2
Certyfikaty z podpisem własnym są bezpłatne, ale AFAIK nadal potrzebujesz statycznego adresu IP.
dF.
8
@dF nie ma wymogu posiadania statycznego adresu IP, z wyjątkiem pewnych wymagań licencyjnych dotyczących komercyjnych opłaconych certyfikatów.
Chris Marisic
Jeśli masz kontrolę nad magazynami certyfikatów na obu końcach (klientach i serwerze), może to być opłacalna opcja, ale ... zarządzanie i dystrybucja certyfikatów jest prawdopodobnie znacznie bardziej złożona w środowisku produkcyjnym niż w środowisku programistycznym. Pamiętaj, aby zrozumieć złożoność tej alternatywy przed jej zaangażowaniem.
ALED
5

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 .

ZaDDaZ
źródło
9
Wymyślenie łańcucha, który wygeneruje taki sam hasz md5, ponieważ poprawna treść może być znacznie łatwiejsza niż powinna, ale wymyślenie złej wersji prawidłowej zawartości o takiej samej wartości jest nadal zbyt trudne. Dlatego md5 nie jest już używany do skrótów haseł, ale nadal służy do weryfikacji pobrań.
Tim Gautier
1

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

LiorH
źródło