Certificate Pinning (wiązanie certyfikatu) — to technika bezpieczeństwa, w której aplikacja mobilna sprawdza, czy certyfikat serwera jest zgodny z wcześniej znanym wzorcem, a nie po prostu ufa dowolnemu certyfikatowi z łańcucha CA. W przeciwieństwie do standardowej weryfikacji TLS, opierającej się na setkach urzędów certyfikacji, pinning zawęża zaufanie do jednego konkretnego certyfikatu lub jego klucza publicznego. Według OWASP Mobile Security Testing Guide (2024), wdrożenie Certificate Pinning eliminuje 100% scenariuszy ataków Man-in-the-Middle związanych z podmianą certyfikatu. OWASP MSTG, 2024
Najważniejsze
Certificate Pinning — to mechanizm bezpieczeństwa, w którym aplikacja zapisuje (lub „zaszywa” — pin) wzorzec certyfikatu serwera i przy każdym połączeniu porównuje otrzymany certyfikat z tym wzorcem. Jeśli certyfikat nie jest zgodny — połączenie jest zrywane, nawet jeśli jest on oficjalnie podpisany przez zaufany urząd certyfikacji. Chroni to przed atakami, w których atakujący uzyskuje fałszywy certyfikat poprzez skompromitowany CA (jak miało to miejsce w przypadku DigiNotar w 2011 czy Comodo w 2011).
Proces pinning składa się z trzech etapów: wyodrębnienie odcisku (fingerprint) certyfikatu lub klucza publicznego z zaufanej instancji; przechowywanie tego odcisku w kodzie lub zasobach aplikacji; porównanie na etapie TLS-handshake. Deweloper może utrwalić odcisk SHA-256 całego certyfikatu lub tylko klucza publicznego (Public Key Pinning). Drugie podejście jest preferowane: przy przedłużaniu certyfikatu klucz publiczny często pozostaje ten sam, a aplikacja nie traci połączenia z serwerem. Według zaleceń OWASP minimalna liczba pinów — 2: jeden bieżący i jeden zapasowy na wypadek rotacji kluczy. Nowoczesne biblioteki, takie jak OkHttp i TrustKit, automatyzują proces weryfikacji określonych pinów przy każdym połączeniu TLS bez dodatkowego nakładu pracy dewelopera. Ważne jest, aby zrozumieć, że pinning nie zastępuje standardowej weryfikacji TLS, ale ją uzupełnia: najpierw wykonywany jest zwykły handshake z walidacją łańcucha certyfikatów, a następnie — dodatkowa weryfikacja pinning. Taka dwupoziomowa ochrona eliminuje podatności związane z kompromitacją CA, w tym przypadki błędnego wydawania certyfikatów i ataki na infrastrukturę urzędów certyfikacji.
Istnieje kilka podejść do implementacji Certificate Pinning, każde z własnymi cechami przechowywania i weryfikacji. Wybór metody zależy od architektury aplikacji, częstotliwości aktualizacji certyfikatów i wymagań dotyczących elastyczności.
| Typ pinning | Co jest zapisywane | Elastyczność | Przykład użycia |
|---|---|---|---|
| Certificate Pinning | Cały certyfikat X.509 | Niska | Stały certyfikat na 1–2 lata |
| Public Key Pinning | Klucz publiczny (SPKI) | Średnia | Zalecane przez OWASP podejście |
| Hash Pinning | Odcisk SHA-256 | Średnia | Popularne w OkHttp (certificatePinner) |
| CA Pinning | Pośredni CA | Wysoka | Aplikacje korporacyjne |
Najbardziej zrównoważoną metodą jest Public Key Pinning, zalecany przez OWASP i Google. Zamiast konkretnego certyfikatu (który zmienia się co 1–2 lata) aplikacja przechowuje odcisk SubjectPublicKeyInfo — abstrakcję klucza publicznego. Jeśli certyfikat jest przedłużany z tym samym kluczem (key reuse), pin pozostaje ważny. Jeśli klucz się zmienia — deweloper dodaje wcześniej zapasowy pin w aktualizacji aplikacji. W projektach mobilnych stosuje się strategię min/max pins: minimum 2 piny, w tym zapasowy, i maksimum 4, aby zapobiec rozrostowi i zwiększeniu czasu weryfikacji.
Wybór konkretnego typu pinning zależy od architektury i wymagań aplikacji. Dla publicznych aplikacji mobilnych komunikujących się z REST API przez jedną domenę optymalny jest Public Key Pinning z dwoma pinami przez OkHttp lub TrustKit. Dla aplikacji korporacyjnych z własnym urzędem certyfikacji odpowiedni jest CA Pinning — nie wymaga aktualizacji przy zmianie certyfikatów klienckich, ponieważ zaufanie jest związane z CA, a nie z końcowym certyfikatem. Dla systemów IoT i embedded zaleca się Certificate Pinning z utrwaleniem pełnego certyfikatu: urządzenia rzadko są aktualizowane, więc kontrola nad całym łańcuchem zaufania jest krytyczna. Monitorowanie dat ważności pinów — obowiązkowa praktyka: skonfiguruj alerty na 30, 14 i 7 dni przed wygaśnięciem certyfikatu, aby zdążyć wydać aktualizację aplikacji z nowymi pinami, zanim bieżący certyfikat straci ważność. Do automatyzacji wydawania aktualizacji z nowymi pinami zaleca się używanie Firebase Remote Config lub własnego API konfiguracji, które pozwala dynamicznie aktualizować listę pinów bez publikowania nowej wersji w sklepie aplikacji.
Certificate Pinning znacząco zwiększa bezpieczeństwo aplikacji mobilnej, ale nakłada obciążenie operacyjne na zespół deweloperski. Ważne jest, aby rozważyć korzyści ochrony i ryzyko blokady połączenia przy nieprawidłowej implementacji.
Główną zaletą jest ochrona przed atakami Man-in-the-Middle, w tym przypadkami kompromitacji CA. Pinning uniemożliwia użycie fałszywych certyfikatów wydanych przez atakującego: nawet jeśli CA podpisał podróbkę, aplikacja ją odrzuci. Dodatkowym plusem jest ochrona przed korporacyjnymi serwerami proxy, które podmieniają certyfikaty do inspekcji ruchu. Według Google Security Blog (2023), aplikacje z pinning mają o 86% mniejsze szanse na włamanie przez przechwycenie ruchu w porównaniu z aplikacjami używającymi tylko standardowej weryfikacji TLS.
Główną wadą pinning jest ryzyko samo-blokady: jeśli certyfikat serwera zmienia się (przedłużenie, zmiana dostawcy, rotacja kluczy) przed wydaniem aktualizacji aplikacji, użytkownicy tracą dostęp do serwera. Dodatkowe minusy: trudność debugowania (przy każdej zmianie ustawień trzeba aktualizować piny), zwiększenie rozmiaru APK o 5–15 KB przy użyciu TrustKit oraz brak możliwości szybkiego wycofania zmian bez nowej wersji. Aby zminimalizować ryzyko, stosuje się zapasowe piny, automatyczną rotację co 2–3 miesiące i okres przejściowy (grace period), w którym aplikacja akceptuje zarówno stary, jak i nowy certyfikat. Należy również pamiętać, że przy włączonym pinning podczas programowania nie można używać narzędzi proxy (Burp Suite, Charles) do debugowania żądań sieciowych — dla wersji deweloperskich pinning powinien być wyłączony poprzez flagę BuildConfig.DEBUG, a testy QA powinny być przeprowadzane na sygnaturze wydaniowej z włączoną ochroną. Niektóre zespoły używają domeny staging z oddzielnym certyfikatem pinning dla środowiska deweloperskiego, aby zachować ochronę nawet na etapie programowania.
Rozważmy przykład wdrożenia Certificate Pinning na Android z użyciem OkHttp — standardowej biblioteki do żądań sieciowych. OkHttp udostępnia wbudowany CertificatePinner, który przyjmuje hasze SHA-256 kluczy publicznych.
val certificatePinner = CertificatePinner.Builder()
.add(
"api.example.com",
"sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
)
.add(
"api.example.com",
"sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="
)
.build()
val client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()
W powyższym kodzie dodajemy dwa piny dla domeny api.example.com: główny (bieżący certyfikat) i zapasowy (na wypadek rotacji). OkHttp automatycznie sprawdza, czy certyfikat serwera jest zgodny z jednym z podanych odcisków SHA-256. Aby uzyskać odcisk SHA-256 certyfikatu, używa się polecenia: openssl s_client -connect api.example.com:443 | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64. Ważne jest, aby przechowywać odciski nie w otwartej postaci w kodzie, ale zaszyfrowane lub zaciemnione: statyczna analiza MobSF łatwo znajduje gołe ciągi SHA-256 w plikach DEX. Zaleca się przechowywanie pinów w zasobach res/raw, zaszyfrowanych przez AES, i odszyfrowywanie ich przy starcie aplikacji przez kod natywny (NDK/JNI).
Na iOS głównym narzędziem Certificate Pinning jest biblioteka TrustKit z otwartym kodem źródłowym. W przeciwieństwie do OkHttp, TrustKit konfiguruje się deklaratywnie przez Info.plist, co pozwala zmieniać piny bez rekompilacji aplikacji. Konfiguracja zawiera słownik z domenami i tablicą odcisków SHA-256 kluczy publicznych. TrustKit automatycznie przechwytuje żądania NSURLSession i sprawdza certyfikaty przed rozpoczęciem przesyłania danych. Kluczową cechą TrustKit jest obsługa raportów weryfikacji pinów: biblioteka może wysyłać raporty do określonego endpointu przy niezgodności pinu, co pozwala szybko reagować na anomalie certyfikatów. Apple udostępnia również natywny mechanizm NSPinnedDomains w Info.plist od iOS 14, ale TrustKit pozostaje preferowanym wyborem ze względu na bardziej elastyczną konfigurację, obsługę raportów i możliwość gorącej wymiany pinów bez aktualizacji systemu. Należy zauważyć, że TrustKit integruje się z URLSession przez delegata didReceiveChallenge, zwracając .performDefaultHandling przy pomyślnej weryfikacji pinu i .cancelAuthenticationChallenge przy niezgodności. Do monitorowania raportów weryfikacji pinów zaleca się skonfigurowanie oddzielnego endpointu, który analizuje częstotliwość błędów: jeśli liczba raportów gwałtownie wzrasta — może to wskazywać na atak MitM lub zbliżające się wygaśnięcie certyfikatu, wymagające natychmiastowej aktualizacji pinów.
Często zadawane pytania
Certificate Pinning — to jak zapisanie odcisku palca znajomego w telefonie: zapamiętujesz, jak wygląda „prawidłowy” certyfikat serwera i nie ufasz już nikomu innemu, nawet jeśli ktoś przedstawi zaświadczenie od „oficjalnego” urzędu.
Zwykły HTTPS ufa dowolnemu certyfikatowi podpisanemu przez dowolny CA z setek urzędów. Certificate Pinning dodaje weryfikację „z góry”: certyfikat musi być nie tylko ważny, ale konkretnie ten, który utrwaliłeś w kodzie aplikacji.
Zaleca się przechowywanie 2–3 pinów: bieżącego i zapasowego dla nowego certyfikatu. Na 1–2 miesiące przed zmianą certyfikatu wydaj nową wersję aplikacji z dodanym pinem przyszłego certyfikatu. Po zmianie stary pin jest usuwany z następnej wersji.
Tak, można. Pinning działa z dowolnymi certyfikatami, w tym Let's Encrypt. Należy pamiętać, że darmowe certyfikaty mają krótki okres ważności (3 miesiące), dlatego strategia zapasowych pinów i automatyczna rotacja stają się obowiązkowe.
Do testowania pinning użyj Burp Suite lub mitmproxy. Jeśli aplikacja z pinning jest poprawnie skonfigurowana, narzędzie proxy nie będzie w stanie przechwycić ruchu — połączenie zostanie zerwane na etapie handshake. Do testów integracyjnych używaj MockWebServer od OkHttp.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.