Jak mogę się upewnić, że mój interfejs API REST odpowiada tylko na żądania generowane przez zaufanych klientów, w moim przypadku moje własne aplikacje mobilne? Chcę zapobiec niechcianym żądaniom pochodzącym z innych źródeł. Nie chcę, aby użytkownicy wpisywali klucz szeregowy lub cokolwiek innego, powinno to nastąpić za kulisami, podczas instalacji i bez wymaganej interakcji użytkownika.
O ile mi wiadomo, HTTPS służy wyłącznie do sprawdzania poprawności serwera, z którym się komunikujesz. Oczywiście używam HTTPS do szyfrowania danych.
Czy istnieje sposób na osiągnięcie tego?
Aktualizacja: użytkownik może wykonywać akcje tylko do odczytu, które nie wymagają zalogowania użytkownika, ale mogą także wykonywać akcje zapisu, które wymagają zalogowania użytkownika (uwierzytelnianie za pomocą tokena dostępu). W obu przypadkach chcę, aby interfejs API odpowiadał na żądania pochodzące tylko od zaufanych aplikacji mobilnych.
Interfejs API będzie również używany do rejestracji nowego konta za pośrednictwem aplikacji mobilnej.
Aktualizacja 2: Wygląda na to, że istnieje wiele odpowiedzi na to pytanie, ale szczerze mówiąc, nie wiem, którą z nich oznaczyć jako odpowiedź. Niektórzy twierdzą, że da się to zrobić, inni twierdzą, że nie da się tego zrobić.
Odpowiedzi:
Nie możesz
Nigdy nie można zweryfikować encji, żadnej encji , czy to osoby, klienta sprzętowego czy oprogramowania. Możesz jedynie zweryfikować, czy to, co mówią , jest poprawne, a następnie przyjąć uczciwość .
Na przykład, skąd Google wie, że loguję się na swoje konto Gmail? Po prostu pytają mnie o nazwę użytkownika i hasło, sprawdzają to , a następnie zakładają uczciwość, bo kto inny miałby te informacje? W pewnym momencie Google zdecydowało, że to nie wystarczy i dodało weryfikację behawioralną (szukając dziwnych zachowań), ale nadal polega na osobie, która je wykonała , a następnie zweryfikowała zachowanie .
To jest dokładnie to samo z weryfikacją klienta. Możesz jedynie zweryfikować zachowanie klienta, ale nie samego klienta.
Dzięki SSL możesz sprawdzić, czy klient ma ważny certyfikat, czy nie, więc możesz po prostu zainstalować aplikację, uzyskać certyfikat, a następnie uruchomić cały nowy kod.
Pytanie brzmi: dlaczego to takie ważne? Jeśli to naprawdę niepokoi, kwestionowałbym twój wybór grubego klienta. Być może powinieneś skorzystać z aplikacji internetowej (abyś nie musiał ujawniać swojego interfejsu API).
Zobacz także: Pokonanie sprawdzania poprawności certyfikatu SSL dla aplikacji na Androida
oraz: Jak bezpieczne są certyfikaty SSL klienta w aplikacji mobilnej?
źródło
Jestem pewien, że nie masz nic przeciwko logowaniu się użytkowników i komunikacji za pośrednictwem protokołu SSL, więc skupię się na tym, co uważam za bardziej interesującą część pytania: jak zapewnić, że Twoje działania tylko do odczytu - które mają nie wymagają użytkownika mają być uwierzytelnione - przyjmowane są wyłącznie z własnych aplikacji klienckich?
Przede wszystkim fNek wskazał na wcześniejszą odpowiedź - aplikacje klienckie znajdują się w rękach potencjalnie wrogich użytkowników. Można je badać, sprawdzać ich komunikację, dezasemblować kod. Nic, co zamierzam sugerować, nie pozwoli Ci zagwarantować, że ktoś nie dokona inżynierii wstecznej Twojego klienta i nie nadużyje interfejsu API REST. Ale powinno to stanowić barierę przed wszelkimi przypadkowymi próbami.
W każdym razie powszechnym podejściem jest:
np. wyobraź sobie
GET
prośbę o/products/widgets
Powiedzmy, że sekretem klienta jest „OH_HAI_I_IZ_SECRET”
Połącz czasownik HTTP, adres URL i klucz tajny:
I weź skrót SHA-1 tego:
Następnie prześlij to, aby prośba dotyczyła:
Wreszcie, aby uniemożliwić komuś przynajmniej ponowne odtwarzanie indywidualnych żądań, weź również znacznik czasu i dodaj go do parametrów i skrótu. np. teraz, w czasie uniksowym, jest 1384987891. Dodaj to do konkatenacji:
Hash że:
I wyślij:
Serwer sprawdzi skrót, a także sprawdzi, czy znacznik czasu jest aktualny (np. W ciągu 5 minut, aby pozwolić zegarom nie być idealnie zsynchronizowanym)
Ostrzeżenie! Ponieważ mówisz o aplikacjach mobilnych, istnieje wyraźne ryzyko, że czyjś telefon będzie miał nieprawidłowy zegar. Lub niewłaściwa strefa czasowa. Lub coś. Dodanie czasu do skrótu prawdopodobnie złamie niektórych legalnych użytkowników, więc używaj tego pomysłu ostrożnie.
źródło
Wszystkim zainteresowanym na Androidzie MOŻESZ sprawdzić, czy otrzymane żądanie zostało wysłane z Twojej aplikacji.
Krótko mówiąc, przesyłając aplikację do Google, podpisujesz ją unikalnym kluczem, który jest znany tylko Tobie (i Google).
Proces weryfikacji przebiega następująco:
pełny blog, który to wyjaśnia i jak go wdrożyć, można znaleźć tutaj: http://android-developers.blogspot.co.il/2013/01/verifying-back-end-calls-from-android.html
źródło
Ok, więc warto wspomnieć, zanim zacznę, że w przypadku większości aplikacji jest to ogromna przesada. W większości przypadków wystarczy mieć jeden ważny certyfikat i / lub token. Jeśli wymaga to robienia czegoś tak trudnego, jak dekompilowanie aplikacji, nawet większość hakerów nie będzie się tym przejmować, chyba że podasz bardzo cenne dane. Ale hej, gdzie jest zabawa w tej odpowiedzi?
Możesz więc skonfigurować kryptografię asymetryczną, podobnie jak podpis cyfrowy używany do podpisywania programów. Każda aplikacja może następnie mieć indywidualny certyfikat, który jest wystawiany przez pojedynczy urząd certyfikacji i weryfikowany, gdy użytkownik się łączy. (przy pierwszej rejestracji lub przy pierwszej instalacji) Po uwierzytelnieniu tego certyfikatu możesz dodatkowo zabezpieczyć aplikację, rejestrując ten certyfikat jako ważny dla jednego określonego identyfikatora urządzenia (takiego jak identyfikator Android )
źródło
Jak wspomniał @Morons w swojej odpowiedzi, bardzo trudno jest zweryfikować byt na drugim końcu połączenia.
Najprostszym sposobem na zapewnienie pewnego poziomu autentyczności jest sprawdzenie przez serwer jakiegoś sekretu, który zna tylko prawdziwa istota. Dla użytkownika może to być nazwa użytkownika i hasło. W przypadku oprogramowania, w którym nie ma użytkownika, możesz osadzić sekret.
Problem z tymi podejściami polega na tym, że musisz zaufać klientowi. Jeśli ktoś dokona inżynierii wstecznej Twojej aplikacji lub ukradnie hasło, może udawać, że jesteś Tobą.
Możesz podjąć kroki, aby utrudnić wydobycie tajnych informacji, zaciemniając je w pliku wykonywalnym. Narzędzia takie jak ProGuard, który jest zaciemniaczem dla Javy, mogą w tym pomóc, nie wiem zbyt wiele o zaciemnianiu w innych językach, ale prawdopodobnie istnieją podobne narzędzia. Korzystanie z połączenia TLS pomaga zapobiegać szpiegowaniu ruchu, ale nie zapobiega atakowi MITM. Przypinanie może pomóc rozwiązać ten problem.
Pracuję dla firmy o nazwie CriticalBlue (pełne ujawnienie!), Która ma produkt o nazwie Approov, który próbuje rozwiązać ten problem zaufania. Działa obecnie na Androida / iOS i zapewnia naszym serwerom mechanizm sprawdzania integralności aplikacji klienckiej. Robi to, zmuszając klienta do obliczenia odpowiedzi na losowe wyzwanie. Klient musi obliczyć odpowiedź za pomocą atrybutów zainstalowanego pakietu aplikacji, które są trudne do sfałszowania i zawiera kilka wyrafinowanych mechanizmów antysabotażowych.
Zwraca token, który można następnie przesłać jako dowód autentyczności do interfejsu API.
Ważną różnicą w tym podejściu jest to, że chociaż byłoby możliwe wyłączenie sprawdzania autentyczności na kliencie, to gdybyś to zrobił, nie dostaniesz tokena uwierzytelniającego, musisz zweryfikować swoją aplikację na serwerze. Biblioteka jest również ściśle związana z właściwościami pliku wykonywalnego, w którym się znajduje, więc bardzo trudno byłoby osadzić ją w fałszywej aplikacji i sprawić, by działała.
Istnieje analiza kosztów i korzyści, którą musi opracować każdy programista interfejsu API, aby zdecydować, jak prawdopodobne jest, że ktoś spróbuje zhakować swój interfejs API i jakie może to być kosztowne. Proste tajne sprawdzenie w aplikacji zapobiega trywialnym atakom, ale ochrona przed bardziej zdeterminowanym atakującym jest prawdopodobnie znacznie bardziej skomplikowana i potencjalnie kosztowna.
źródło
SSL zabezpieczy kanał komunikacji.
Pomyślne logowanie spowoduje wydanie tokena uwierzytelniającego zaszyfrowane połączenie.
Token uwierzytelnienia zostanie przekazany do interfejsu API REST we wszystkich kolejnych żądaniach.
źródło
Nie byłoby to zbyt bezpieczne, ale możesz dodać jakiś tajny kod lub nawet podpis cyfrowy. Wada: musi być uwzględniona w aplikacji, co ułatwia jej uzyskanie, jeśli wiesz, co robisz.
źródło
W rzeczywistości można użyć protokołu SSL do uwierzytelnienia zarówno klienta, jak i serwera. Lub, inaczej mówiąc, „tak, możesz używać certyfikatów klienta”.
Musisz ...
Aplikacja mobilna może przechowywać certyfikat w dowolnym miejscu. Ponieważ chcesz uwierzytelniania specyficznego dla aplikacji, powinieneś rozważyć przechowywanie certyfikatu w chronionym miejscu na dysku (w systemie Android możesz utworzyć tabelę „config” w bazie danych SQLite oraz wiersz dla certyfikatu i drugi dla klucza prywatnego) .
źródło