2009-10-28 15 views
8

Pytanie: Czy ta technika uwierzytelniania API jest łatwa do hakowania?Uwierzytelnianie interfejsu API i możliwość hackowania

apiKey = "123456789" 
apiCallId = "1256341451" 
apiSecret = "67d48e91ab2b7471d4be2a8c2e007d13" 
sig = md5(apiKey + apiCallId + apiSecret) = 09c297a354219f173bfc49c2e203ce03 

gdzie

  • apiKey: niektóre unikalny identyfikator dla użytkownika
  • apiCallId: unikatowy liczb całkowitych, które muszą być coraz większej wartości (np UNIX Time Stamp)
  • apiSecret: String znany tylko do użytkownika i nas - nie przekazano w adresie URL
  • sig: "Unhackable" podpis tej funkcji API - skrót MD5

Przykład wywołania API:

http://api.domain.com/?apiKey=123456789&apiCallId=1256341451&sig=09c297a354219f173bfc49c2e203ce03&param1=x&param2=y 

Ten interfejs API nie wymaga sesję i nie jest przeznaczony do 3rd party do korzystania w imieniu użytkownika. Zamiast tego ma być używany przez samego użytkownika.

Bardzo podoba mi się prostota tego. Wymóg, aby apiCallId był wyjątkowy i zawsze się zwiększał, oznacza ponowne użycie numeru sig, więc czuję, że jest bezpieczny (chroniony przed atakami powtórki), ale nie jestem ekspertem.

Inne interfejsy API używają wszystkich parametrów GET posortowanych alfabetycznie podczas obliczania sig, ale nie widzę powodu, dla którego jest to konieczne, jeśli uwzględni się apiCallId.

Spróbuj zhakować to teraz, zanim zostanie wdrożone i zwolnione.

Cieszę się z wszelkich opinii, sugestii i edukacji bezpieczeństwa.

Odpowiedz

13

To, co robisz, wydaje się rozsądnie rozsądne, z wyjątkiem nie sprawdzania parametrów (co będzie dość dużym problemem).

Coś, co jest bardzo podobny do swojego projektu, który może być mądry, aby skopiować to Amazon Web Services Request Authentication Scheme

W szczególności upewnij się, że schemat kodowania dla parametrów jest jednoznaczna i odwracalna; Amazon screwed this up w jednym punkcie. Ucz się na błędach. :)

Kryptograficznie rzecz biorąc, to, co robisz, nie jest nazywane podpisem, ale raczej kodem uwierzytelniania wiadomości (MAC). MAC może zostać utworzony i zweryfikowany przez każdego, kto ma ten tajny klucz (termin "podpis" jest zwykle zarezerwowany dla schematów kluczy publicznych, takich jak DSA lub RSA). MD5 (msg || K) jest znanym i rozsądnie rozsądnym MAC; Nie jestem pewien, czy tęskniłeś za tym przez przypadek czy celowo, ale metoda, która wydaje się na powierzchni równoważna, MD5 (K || msg), jest dość niepewna, ponieważ dziwactwo jak MD5 (i większość innych skrótów funkcje) oznacza, że ​​jeśli znasz H (m), możesz łatwo obliczyć H (m || m2) dla dowolnego m2 - więc jeśli używasz MD5 (K || param1 = 5), ktoś może wyciągnąć to z drutu a następnie utwórz MD5 (K || param1 = 5, param2 = 666). (To może być trochę bardziej techniczny niż jesteś zainteresowany, ale nazywa się to length extension property).

Jednak podczas gdy MD5 (K || msg) jest prawdopodobnie "w porządku", lepiej jest użyć czegoś takiego jak HMAC, ponieważ został on faktycznie zaprojektowany jako MAC. MD5 ma wiele problemów, ale nic bezpośrednio nie wpływa na jego użycie jako MAC (jednak - MD4 zostało złamane w ten sposób). Tak więc w celu zabezpieczenia przyszłości (i audytu) użyj HMAC z SHA-1 lub SHA-256. Nawet jeśli nie chcesz pobierać biblioteki kryptograficznej, HMAC jest dość prosty i dostępne są znane wartości dla SHA-1 i SHA-2, dzięki czemu możesz sprawdzić swój kod.

+0

Niesamowita odpowiedź i uwielbiam szczegóły techniczne. "erickson" wskazał, że przechwytywanie (człowiek-w-środku) jest możliwe dzięki powyższym. Czy masz jakieś zalecenia, jak zapobiec tego typu atakom? Wydaje mi się, że wykracza to poza pierwotne pytanie. Czy używa go HTTPS (a nie HTTP)? –

+1

Jeśli MAC obejmuje wszystkie dane, _ i_ nie ma drugiego zestawu danych wejściowych, który jest kanoniczny dla tego samego wejścia do MAC (jest to ważne, jak nauczył się Amazon), i zapewniasz, że nie ma możliwości wykonania powtórnych ataków (twój licznik schemat, prawidłowo wdrożony, wydaje się być w porządku), a twój MAC jest bezpieczny, wtedy powinieneś być bezpieczny przed MITM. Dzieje się tak dlatego, że atakujący nie ma opcji - może zmodyfikować wartość parametru lub API i spróbować go wysłać, ale nie będzie możliwości wygenerowania prawidłowej wartości adresu MAC, więc połączenie powinno zostać odrzucone. –

+1

Założę się, że wymuszenie, że identyfikator połączenia jest zawsze zwiększany przez tabelę bazy danych. Po prostu uważaj, aby zaktualizować go tylko po zaakceptowaniu poprawnego mac. W przeciwnym razie dowolny przypadkowy atakujący mógłby wysłać apiKey = your_id i apiCallId = 9999999999999999 ... oraz wartość MAC śmieci i spowodować łatwą odmowę usługi. Na HTTPS: możesz go użyć, zrób to - po pierwsze, będzie chronić poufność wejść API (i odpowiedzi RPC), i po prostu generalnie znacznie utrudni wszelkie ataki na twój auth. –

0

Zakładam, że znałem sekret, a następnie mogłem wygenerować sig i przekazać go. To, co robiłem dla jednego z moich startupów, to podejmowanie sig param jeszcze dalej, przez to, że sig polega na innych parametrach, a także requestID (UUID) i znaczniku czasu i przechowuje ten UUID (powody bezpieczeństwa na kilka godzin, aby odmówić hakerowi wywoływanie tej samej funkcji w kółko). W ten sposób nie możesz ponownie wywołać tego samego połączenia, musisz wygenerować nowy identyfikator UUID i jeśli haker zastąpi UUID w paramecie sig unieważnia, a on nie wie, jak wygenerować sig, ponieważ, poza tajemnicą, jesteśmy także generowanie podpisu na podstawie klucza wewnętrznego o długości 30 znaków. Więc essenity

MD5 (alfabetycznie Lista Params + APiKEY + callID + Secert + someLonginternalKey)

nie jestem pewien, czy odpowiedział na to pytanie, ale to inna droga robi bezpieczeństwo api

+0

P. Bezwstydna autopromocja, o tym powiem na Riadventure (Riadventure.com) –

+0

"Cóż, przypuszczam, że znałem sekret" to gra w większości interfejsów API. Twoje rozwiązanie zdecydowanie wydaje się bezpieczniejsze, ale czy jest to "bezpieczeństwo przez złożoność"? Nie chcę niepotrzebnie komplikować procesu. Dlaczego zaletą jest włączenie wszystkich parametrów? Dlaczego dodatkowy klucz sprawia, że ​​jest on mniej podatny na zhackowanie? –

+1

Dodatkowy klucz nie wymaga tylko dodatkowego wypełnienia, możesz to zignorować. Jednak dzięki hashowaniu parametrów w podpisie zapewnia to dane, które przekazujesz (tj.e param1 param2) jest zachowana integralność i pewność, że nikt go nie zmienił (człowiek w środku), tak jak powiedział inny post. –

2

Nie. Integralność pozostałych parametrów (param1 i param2 w twoim przykładzie) nie jest chroniona. Osoba atakująca może przechwycić połączenie i zmienić je tak, jak mu się podoba przed przesłaniem go dalej. apiCallId tylko zapobiega powtórkom, a nie zmianom pierwszego połączenia.

Nie jestem ekspertem. Jeśli zobaczyłem to od razu, prawdopodobnie inne problemy czają się.

+0

Ah-haaa ... przyczyną jest przechwytywanie. –

+0

Ale co to jest zatrzymanie przechwytywania jakichkolwiek wywołań API, nawet jeśli wszystkie parametry są używane w podpisie? –

+0

To, co mówi @erickson, to to, że parametry nie są szyfrowane i mogą być łatwo zmieniane i przekazywane dalej. Jeśli były również zaszyfrowane, to nie byłoby to możliwe. –

0

Proponuję użyć podpisów cyfrowych w tym przypadku, ponieważ są bardziej odpowiednie. Podpis cyfrowy na przykład na apikey jest więcej niż wystarczający. Nie potrzebujesz nawet apisecreta i jego haszu. Musisz tylko upewnić się, że podpis cyfrowy pozostanie prywatny (tak jak hash md5).

Jeśli chcesz zapobiec atakowi typu "powtórka", w każdym żądaniu potrzebujesz jakiejś przypadkowości. Więc proponuję następujące:

Server -> API: nonce (= niektórych liczb losowych)

API -> Server: Enc (nonce + podpis cyfrowy)

to jest szyfrowana z kluczem publicznym serwera, a podpis cyfrowy jest umieszczany z kluczem prywatnym serwera.

Teraz nie można przeprowadzić ataku powtórki. Jednak nadal istnieje problem człowieka w ataku środkowym, ale naprawienie tego nie jest tak banalne (ale całkiem wykonalne). Tak więc w zależności od poziomu bezpieczeństwa, jaki chcesz/potrzebujesz, możesz dostosować swoje środki techniczne.

Powiązane problemy