Secure Sockets Layer (SSL)—obecnie technicznie znany jako Transport Layer Security(TLS)—jest wspólnym budulcem dla szyfrowanej komunikacji między klientami i serwerami. Możliwe, żeaplikacja może nieprawidłowo używać protokołu SSL, tak aby złośliwe podmioty mogły przechwycić dane aplikacji przez sieć., Aby pomóc Ci upewnić się, że nie dzieje się tak w Twojej aplikacji, w tym artykule omówiono typowe pułapki podczas korzystania z bezpiecznych protokołów sieciowych i rozwiązano niektóre większe obawy dotyczące korzystania z infrastruktury klucza publicznego (PKI).
powinieneś również przeczytać przegląd AndroidSecurity, a także PermissionsOverview.
koncepcje
w typowym scenariuszu użycia SSL serwer jest skonfigurowany z certyfikatem zawierającym klucz publiczny oraz pasujący klucz prywatny., W ramach uścisku dłoni między Klientem SSL a serwerem serwer udowadnia, że posiada klucz prywatny, podpisując swój certyfikat kryptografią klucza publicznego.
jednak każdy może wygenerować własny certyfikat i klucz prywatny, więc proste handshakedoesn ' t udowodnić nic o serwerze poza tym, że serwer zna klucz prywatny, który pasuje do klucza publicznego certyfikatu. Jednym ze sposobów rozwiązania tego problemu jest posiadanie przez Klienta zestawu jednego lub więcej certyfikatów, którym ufa. Jeśli certyfikat nie znajduje się w zestawie, nie należy ufać serwerowi.,
istnieje kilka wad tego prostego podejścia. Serwery powinny być w stanie z czasem zmieniać mocniejsze klucze („key rotation”), które zastępują klucz publiczny w systemie na nowy. Niestety, teraz aplikacja kliencka musi zostać zaktualizowana ze względu na co zasadniczo zmienia się konfiguracja serwera. Jest to szczególnie problematyczne, jeśli serwer nie jest pod kontrolą twórcy aplikacji, na przykład jeśli jest to usługa internetowa innej firmy. Thisapproach ma również problemy, jeśli aplikacja musi rozmawiać z arbitralnymi serwerami, takimi jak przeglądarka internetowa lub aplikacja poczty.,
aby zaradzić tym wadom, serwery są zazwyczaj konfigurowane z certyfikatami od znanych emitentów zwanych organami certyfikującymi (CAs).Platforma hosta zazwyczaj zawiera listę dobrze znanych CAs, że to trusts.As Android 4.2 (Jelly Bean), Android zawiera obecnie ponad 100 CAs, które są aktualizowane w każdym wydaniu. Podobnie jak serwer, Urząd Certyfikacji posiada certyfikat i klucz prywatny. Wystawiając certyfikat dla serwera, urząd certyfikacji podpisuje certyfikat serwera za pomocą swojego klucza prywatnego. Theclient może następnie sprawdzić, czy serwer posiada certyfikat wydany przez urząd certyfikacji znany platformie.,
jednak przy rozwiązywaniu niektórych problemów, Korzystanie z CAs wprowadza inny. Ponieważ CA issuescertificates dla wielu serwerów, nadal potrzebujesz jakiegoś sposobu, aby upewnić się, że rozmawiasz z serwerem, który chcesz. Aby temu zaradzić, certyfikat wydany przez CA identyfikuje serwer z określoną nazwą, taką jak gmail.com lub wildcarded zestaw hostów, takich jak *.google.com.
poniższy przykład uczyni te pojęcia nieco bardziej konkretnymi., W poniższym fragmencie z wiersza poleceń openssl
polecenie s_client
sprawdza informacje o certyfikatach serwera Wikipedii. Określa port 443, ponieważ jest to domyślne dla HTTPS. Polecenie wysyła wyjście openssl s_client
na openssl x509
, które formatuje informacje o certyfikatach zgodnie ze standardem X. 509. W szczególności polecenie pyta o temat, który zawiera informacje o nazwie serwera, oraz o Emitenta, który identyfikuje CA.,
widać, że certyfikat został wydany dla serwerów pasujących *.wikipedia.org bythe RapidSSL CA.
przykład HTTPS
zakładając, że masz serwer WWW z certyfikatem wydanym przez znany urząd certyfikacji, możesz złożyć bezpieczne żądanie za pomocą kodu:
tak, to naprawdę może być takie proste. Jeśli chcesz dostosować żądanie HTTP, możesz wysłać je do HttpURLConnection
., Dokumentacja systemu Android dlaHttpURLConnection
zawiera dalsze przykłady dotyczące postępowania z nagłówkami zapytań i odpowiedzi, publikowania treści, Zarządzania Plikami cookie, korzystania z serwerów proxy,buforowania odpowiedzi itd. Ale jeśli chodzi o szczegóły weryfikacji certyfikatów i nazw hostów, Androidframework dba o to za pośrednictwem tych interfejsów API.To jest miejsce, gdzie chcesz być, jeśli to w ogóle możliwe. To powiedziawszy, poniżej znajdują się inne kwestie.,
typowe problemy z weryfikacją certyfikatów serwera
Załóżmy, że zamiast odbierać zawartość z getInputStream()
, rzuca wyjątek:
może się to zdarzyć z kilku powodów, w tym:
- urząd certyfikacji, który wydał certyfikat serwera, był nieznany
- certyfikat serwera nie był podpisany przez urząd certyfikacji, ale był podpisany samodzielnie
- w konfiguracji serwera brakuje pośredniego certyfikatu serwera.ca
w poniższych sekcjach omówiono sposób rozwiązania tych problemów przy zachowaniu bezpieczeństwa połączenia z serwerem.,
nieznany urząd certyfikacji
w tym przypadkuSSLHandshakeException
występuje, ponieważ masz urząd certyfikacji, który nie jest zaufany przez system. Może być tak dlatego, że masz certyfikat od nowego urzędu certyfikacji, który nie jest jeszcze zaufany przez Androida lub Twoja aplikacja działa na starszej wersji bez urzędu certyfikacji. Częściej CA jest nieznany, ponieważ nie jest to publiczny CA, ale prywatny wydany przez organizację taką jak rząd,korporacja lub instytucja edukacyjna na własny użytek.
na szczęście możesz nauczyćHttpsURLConnection
ufać konkretnemu zestawowi CAs., Procedura może być trochę zawiła, więc poniżej znajduje się przykład, który pobiera określony CA z InputStream
, używa go do utworzenia KeyStore
,który jest następnie używany do tworzenia i inicjalizacjiTrustManager
. A TrustManager
jest tym, co systemyuses do walidacji certyfikatów z serwera i—tworząc jeden z KeyStore
z jednym lub więcej CAs-thosewill be the only CAs zaufanych przez to TrustManager
.,
biorąc pod uwagę nowy TrustManager
,przykład inicjalizuje nowy SSLContext
który zapewnia SSLSocketFactory
możesz użyć do zastąpienia domyślnegoSSLSocketFactory
zHttpsURLConnection
. W ten sposób theconnection wykorzysta Twój CAs do walidacji certyfikatu.
oto przykład użycia organizacyjnego CA z University of Washington:
z niestandardowym TrustManager
który wie o Twoim CAs,system jest w stanie potwierdzić, że twój certyfikat serwera pochodzi od zaufanego wystawcy.,
Uwaga:wiele stron internetowych opisuje słabe alternatywne rozwiązanie, którym jest zainstalowanieTrustManager
, które nic nie robi. Jeśli to zrobisz, równie dobrze możesz nie szyfrować swojej komunikacji, ponieważ każdy może zaatakować użytkowników w publicznym hotspocie Wi-Fi, używając sztuczek DNS, aby wysłać traffic użytkowników za pośrednictwem własnego proxy, który udaje Twój serwer. Atakujący może następnie odczytać hasła i inne dane osobowe., Działa to, ponieważ atakujący może wygenerować certyfikat acertificate i—bez TrustManager
, które faktycznie potwierdza, że certyfikat pochodzi z trustedsource—Twoja aplikacja może rozmawiać z każdym. Więc nie rób tego, nawet tymczasowo. Zawsze możesz sprawić, by Twoja aplikacja zaufała wystawcy certyfikatu serwera, więc po prostu to zrób.
certyfikat serwera z podpisem własnym
drugi przypadek SSLHandshakeException
jest spowodowany certyfikatem z podpisem własnym, co oznacza, że serwer zachowuje się jak własny CA.,Jest to podobne do nieznanego urzędu certyfikacji, więc możesz użyć tego samego podejścia z poprzedniej sekcji.
możesz utworzyć swój własnyTrustManager
, tym razem ufając bezpośrednio certyfikatowi serwera. Ma to wszystkie omówione wcześniej sposoby wiązania aplikacji bezpośrednio z certyfikatem, ale można je bezpiecznie wykonać. Należy jednak zachować ostrożność, aby upewnić się, że własnoręcznie podpisany certyfikat ma odpowiednio mocny klucz. Od 2012 r.akceptowalna jest 2048-bitowa sygnatura RSA z wykładnikiem 65537 expiringyearly., Podczas obracania klawiszy należy sprawdzić, czy nie ma zaleceń autorytetu (np. NIST) dotyczących tego, co jest akceptowalne.
brakujący pośredni urząd certyfikacji
trzeci przypadekSSLHandshakeException
występuje z powodu braku pośredniego CA. Większość publicznych certyfikatów nie podpisuje bezpośrednio certyfikatów serwera. Zamiast tego używają swojego głównego certyfikatu CA,zwanego głównym certyfikatem CA, do podpisywania pośrednich certyfikatów ca. Robią to, aby główny CA mógł być przechowywany w celu zmniejszenia ryzyka kompromisu., Jednak systemy operacyjne, takie jak Android typowo zaufają bezpośrednio tylko Root CAs, co pozostawia krótką lukę zaufania między servercertificate-podpisanym przez pośredni CA – a weryfikatorem certyfikatów, który zna root CA. Aby rozwiązać ten problem, serwer nie wysyła klientowi tylko jego Certyfikat podczas SSL handshake, ale łańcuch certyfikatów z serwera CA poprzez wszelkie półprodukty niezbędne do osiągnięcia zaufanego głównego CA.
aby zobaczyć jak to wygląda w praktyce, oto mail.google.,com certificatechain wyświetlany przezopenssl
s_client
polecenie:
pokazuje to, że serwer wysyła certyfikat dla poczty.google.comissued by the Thawte SGC CA, which is an intermediate CA, and a second certificat for the Thawte SGC ca issued by a Verisign CA, which is the primary CA that ' trusted by Android.
nierzadko jednak konfigurowanie serwera tak, aby nie zawierał niezbędnego CA., Na przykład, tutaj jest serwer, który może powodować błąd w przeglądarkach Android iwyjęcia w aplikacjach Android:
co jest interesujące, aby zauważyć tutaj jest to, że odwiedzanie tego serwera w większości przeglądarek desktopowych nie powoduje błędu, jak całkowicie nieznany CA lub własny podpis certyfikatu serwera byłby spowodowany. Dzieje się tak, ponieważ większość przeglądarek desktopowych buforuje zaufany pośredni CAs w czasie. Gdy przeglądarka odwiedzi i dowie się o pośrednim CA z jednej witryny, następnym razem nie będzie musiała mieć pośredniego CA w łańcuchu certyfikatów.,
niektóre witryny robią to celowo dla drugorzędnych serwerów internetowych używanych do obsługi zasobów. Na przykład, mogą mieć swoją główną stronę HTML obsługiwaną przez serwer z pełnym łańcuchem certyfikatów, ale mają serwery zasobów takich jak obrazy, CSS lub JavaScript nie zawierają teca, prawdopodobnie w celu zaoszczędzenia przepustowości. Niestety, czasami te serwery mogą dostarczaćserwis internetowy, do którego próbujesz zadzwonić z aplikacji na Androida, co nie jest tak wyrozumiałe.
istnieją dwa sposoby rozwiązania tego problemu:
- Skonfiguruj serwer tak, aby zawierał pośredni CA w łańcuchu serwerów., Większość CAs dostarcza dokumentację, jak to zrobić dla wszystkich popularnych serwerów internetowych. Jest to jedyne podejście, jeśli potrzebujesz witryny do pracy z domyślnymi przeglądarkami Android przynajmniej za pośrednictwem Androida 4.2.
- lub traktuj pośredni CA jak każdy inny nieznany CA i utwórz
TrustManager
, aby zaufać mu bezpośrednio, Jak to uczyniono w poprzednich dwóch sekcjach.
typowe problemy z weryfikacją nazwy hosta
jak wspomniano na początku tego artykułu,istnieją dwie kluczowe części weryfikacji połączenia SSL., Pierwsza weryfikacja certyfikatu pochodzi z zaufanego źródła, które było przedmiotem poprzedniej sekcji. Głównym celem tej sekcji jest druga część: upewnienie się, że serwer, na który chcesz wejść, prezentuje odpowiedni certyfikat. Jeśli tak się nie stanie, zazwyczaj zobaczysz błąd podobny do tego:
jednym z powodów, dla których może się to zdarzyć, jest błąd konfiguracji serwera. Serwer jest skonfigurowany z certyfikatem, który nie ma pola subject lub subject alternative name, które pasują do serwera, do którego próbujesz dotrzeć. Możliwe jest użycie jednego certyfikatu na wielu różnych serwerach., Na przykład, patrząc na google.com certyfikat zopenssl
s_client -connect google.com:443 | openssl x509 -text
możesz zobaczyć, że obiekt, który obsługuje*. google.com ale także temat alternatywne nazwy dla *.youtube.com,*.android.com i inni Błąd występuje tylko wtedy, gdy nazwa serwera, z którym się łączysz, nie jest wymieniona w certyfikacie jako akceptowalna.
Niestety może się to zdarzyć również z innego powodu: hosting wirtualny. Podczas udostępniania serwera dla więcej niż jednej nazwy hosta z HTTP, serwer WWW może stwierdzić z żądania HTTP/1.1, którego docelowa Nazwa hosta szuka klient., Niestety jest to skomplikowane z https, ponieważ serwer musi wiedzieć, który certyfikat zwrócić, zanim zobaczy HTTPrequest. Aby rozwiązać ten problem, nowsze wersje SSL, w szczególności TLSv.1.0 i nowsze, Obsługa wskazania nazwy serwera (SNI), która pozwala klientowi SSL określić nazwę hosta do serwera, aby można było zwrócić odpowiedni certyfikat.
HttpsURLConnection
obsługuje Androida 2.3. Jeden workaroundije musisz obsługiwać Androida 2.,2 (i starsze) polega na skonfigurowaniu alternatywnego hosta na unikalnym porcie, tak aby było jednoznaczne, który certyfikat serwera zwrócić.
bardziej drastyczną alternatywą jest zastąpienieHostnameVerifier
takim, który nie używa nazwy hosta wirtualnego, ale domyślnie zwracanego przez serwer.
Uwaga: WymianaHostnameVerifier
może być bardzo niebezpieczna, jeśli inny wirtualny host nie jest pod twoją kontrolą, ponieważ Anon-pathattacker może kierować ruch do innego serwera bez Twojej wiedzy.,
Jeśli nadal jesteś pewien, że chcesz zastąpić weryfikację nazwy hosta, oto przykład, który zastępuje weryfikatora dla jednego URLConnection
z takim, który nadal sprawdza, czy nazwa hosta jest co najmniej oczekiwana przez aplikację:
ale pamiętaj, jeśli znajdziesz się zastępując weryfikację nazwy hosta, szczególnie ze względu na hosting wirtualny, to nadal bardzo niebezpieczne, jeśli inny host wirtualny nie jest pod twoją kontrolą i powinieneś znaleźć alternatywny hosting. / align = „left” / ,
Ostrzeżenia o używaniu SSLSocket bezpośrednio
do tej pory przykłady skupiały się na HTTPS przy użyciuHttpsURLConnection
.Czasami aplikacje muszą używać protokołu SSL oddzielnie od HTTP. Na przykład aplikacja poczty e-mail może używać opcji SSL SMTP, POP3 lub IMAP. W takich przypadkach aplikacja chciałaby używać SSLSocket
bezpośrednio, podobnie jak HttpsURLConnection
wewnętrznie.
opisane techniki rozwiązywania problemów z weryfikacją certyfikatu dotyczą również SSLSocket
.,W rzeczywistości, podczas korzystania z niestandardowego TrustManager
, co jest przekazywane doHttpsURLConnection
jest SSLSocketFactory
.więc jeśli chcesz użyć niestandardowego TrustManager
zSSLSocket
wykonaj te same kroki i użyj SSLSocketFactory
, aby utworzyć swójSSLSocket
.
Uwaga:SSLSocket
nie wykonuje weryfikacji nazwy hosta. Do Twojej aplikacji należy weryfikacja własnej nazwy hosta, najlepiej przez wywołanie getDefaultHostnameVerifier()
z oczekiwaną nazwą hosta., Furtherbeware, że HostnameVerifier.verify()
nie wyrzuca wyjątku w przypadku błędu, ale zamiast tego zwraca wynik logiczny, który musisz bezwarunkowo sprawdzić.
oto przykład pokazujący, jak można to zrobić. Pokazuje, że podczas łączenia togmail.com port 443 bez wsparcia SNI, otrzymasz certyfikat formail.google.com. oczekuje się tego w tym przypadku, więc sprawdź, aby upewnić się, że certyfikat jest rzeczywiście dla mail.google.com:
Denylisting
SSL polega w dużej mierze na wydawaniu certyfikatów tylko odpowiednio zweryfikowanym właścicielom serwerów i domen., W rzadkich przypadkach CAs są oszukiwane lub, w przypadku Comodo lub DigiNotar, naruszane, co powoduje, że certyfikaty dla nazwy hosta mają być wydane dla innych niż właściciel serwera lub domeny.
aby zmniejszyć to ryzyko, Android ma możliwość dodawania pewnych certyfikatów lub nawet wszystkich CAs do denylist. Chociaż lista ta była historycznie wbudowana w system operacyjny, począwszy od Androida 4.2 lista ta może być zdalnie aktualizowana, aby poradzić sobie z przyszłymi kompromisami.,
Przypinanie
aplikacja może dodatkowo chronić się przed nieuczciwymi certyfikatami wydanymi przez atechnique, zwanymi przypinaniem. Jest to w zasadzie przy użyciu przykładu podanego w nieznanym przypadku CA, aby ograniczyć zaufany CAs aplikacji do małego zestawu znanego z użycia przez serwery aplikacji. Oznacza to, że jeden z pozostałych 100+ CAs w systemie może spowodować naruszenie bezpiecznego kanału aplikacji.
certyfikaty klientów
Ten artykuł koncentruje się na użytkowniku SSL w celu zabezpieczenia komunikacji z serwerami., SSL supportuje również pojęcie certyfikatów klienta, które pozwalają serwerowi zweryfikować tożsamość klienta. Choć poza zakresem tego artykułu, zastosowane techniki są zbliżone do specyfikacji TrustManager
.
Nogotofail: narzędzie do testowania bezpieczeństwa ruchu sieciowego
Nogotofail to narzędzie, które pozwala w łatwy sposób potwierdzić, że Twoje aplikacje są bezpieczne przed znanymi lukami TLS / SSL i błędnymi konfiguracjami. Jest to zautomatyzowane, wydajne i skalowalne narzędzie do testowania problemów z bezpieczeństwem sieci na dowolnym urządzeniu, na którym ruch sieciowy może być przeprowadzony.,
Nogotofail jest przydatny w trzech głównych przypadkach użycia:
- znajdowanie błędów i luk.
- sprawdzanie poprawek i obserwowanie regresji.
- zrozumienie, jakie aplikacje i urządzenia generują jaki ruch.
Nogotofail działa na Android, iOS, Linux, Windows, Chrome OS, OSX, w rzeczywistości każde urządzenie używane do łączenia się z Internetem. Jest łatwy w użyciu klient do konfigurowania ustawień i otrzymywania powiadomień na Androida i Linuksa, a także sam silnik ataku, który może być wdrożony jako router, serwer VPN lub proxy.