Kluczowe Wnioski:
- Podatność w systemach administracji pozwalała na wygenerowanie certyfikatu z danymi innej osoby i ominięcie autoryzacji w ZUS, e-Sądzie i e-Zdrowiu.
- Brak właściwej kryptograficznej weryfikacji wystawcy (Trust Anchor) pozwala atakującym na wstrzyknięcie fałszywych certyfikatów.
- W systemie Gadnet stosujemy pełną weryfikację ścieżki certyfikacji RFC 5280 przy użyciu natywnych bibliotek (C-Rust), a nie “ręcznych” porównań kodu.
- Znane wpadki gigantów (np. Apple “goto fail”, Microsoft CurveBall) dowodzą, że kryptografię zawsze należy delegować sprawdzonym bibliotekom.
Dzisiaj rano obudziliśmy się w nowej rzeczywistości polskiego cyberbezpieczeństwa. Szokująca informacja o luce pozwalającej na wejście na konto dowolnego obywatela w usługach państwowych uświadomiła nam wszystkim, jak potężne skutki mogą mieć pozornie nudne “technikalia”. Gdy w GADNET od podstaw projektowaliśmy architekturę certyfikatów i weryfikację urządzeń IoT, bardzo rygorystycznie podchodziliśmy do kwestii infrastruktury klucza publicznego (PKI). To, co podczas naszych audytów bezpieczeństwa traktowaliśmy jako krytyczne i bezwzględne reguły do spełnienia, w kluczowych polskich systemach publicznych niestety zawiodło na niespotykaną dotąd skalę.
Weryfikacja e-podpisów, która zawiodła
Polski internet zelektryzowała informacja o krytycznej podatności w systemach eZUS, e-Sąd czy e-Zdrowie. Kluczowe jest tu doprecyzowanie: sama architektura państwowa nie posiadała “magicznej luki” – bezpośrednią przyczyną był krytyczny błąd wewnątrz oprogramowania Szafir (dostarczanego przez KIR), które te systemy integrowały do obsługi logowania. Zaimplementowana w tej konkretnej aplikacji logika w ogóle nie weryfikowała właściwie tego, czy karta do podpisu kwalifikowanego została wydana przez uprawniony do tego, zaufany podmiot.
W praktyce systemy te ufały spreparowanym danym na temat wystawcy zapisanym na sfałszowanym certyfikacie. Brak pełnego, kryptograficznego sprawdzenia łańcucha zaufania (Chain of Trust) pozwolił atakującym na samodzielne “wystawienie” sobie kart z imieniem, nazwiskiem i numerem PESEL dowolnej ofiary, co skutkowało pełnym ominięciem autoryzacji i logowaniem na konta obywateli.
Ręczna weryfikacja vs Kryptografia strukturalna
Aby zrozumieć różnicę, spójrzmy na zestawienie podejść. W ogólnej architekturze bezpieczeństwa GADNET celowo odeszliśmy od prostego, ręcznego “sprawdzania nazw”. Zamiast pisać własne, ryzykowne warunki weryfikacji w kodzie aplikacji, wykorzystujemy sprawdzone w branży mechanizmy do obsługi polityk (takie jak obiekt PolicyBuilder), które realizują ścisłą walidację całego łańcucha zgodnie ze standardem RFC 5280 paragraf 6.1. Oznacza to sprawdzanie ścieżki od klienta, przez wystawcę pośredniego, aż do Root CA, przy jednoczesnej kryptograficznej weryfikacji każdego podpisu cyfrowego na ścieżce certyfikacji.
| Funkcja | Ręczna weryfikacja (Naiwna) | GADNET PKI (RFC 5280) |
|---|---|---|
| Porównywanie wystawcy | Tylko pole “Issuer” | Weryfikacja kryptograficznego podpisu kluczem CA |
| Delegacja kodu | Własny, niesprawdzony kod | Natywne moduły kryptograficzne (C/Rust) np. z biblioteki cryptography |
| Walidacja uprawnień | Często pomijana | Wymagane Key Usage oraz EKU (Client Authentication) |
| Odporność na fałszerstwo | Podatne na fałszywe certyfikaty | Praktycznie niewykonalne obliczeniowo bez dostępu do klucza prywatnego CA |
Musimy jednak podkreślić absolutnie najważniejszy detal: sama weryfikacja kryptograficzna podpisu nie wystarczy, jeśli system ślepo zaufa każdemu certyfikatowi Root CA podanemu przez klienta. Pełna walidacja ścieżki chroni przed atakami tylko wtedy, gdy punkt kotwiczenia zaufania (Trust Anchor) to zamknięta, rygorystycznie kontrolowana lista autorytetów (w Polsce np. Narodowe Centrum Certyfikacji - NCCert). Dopiero połączenie matematycznego sprawdzenia podpisów z zamkniętą listą dozwolonych Root CA zamyka drogę atakującym.
Największe błędy we wdrożeniach PKI na świecie
Zła weryfikacja certyfikatów i błędna implementacja kryptografii to problemy stare jak sama branża IT. Historia pełna jest spektakularnych upadków:
- Apple “goto fail” (CVE-2014-1266): W 2014 roku świat wstrzymał oddech, gdy w kodzie Apple iOS i OS X znaleziono błąd. Podwójnie wpisana instrukcja
goto fail;w języku C powodowała bezwarunkowe ominięcie istotnej pętli weryfikującej podpisy SSL/TLS. Błąd pozwalał na przeprowadzanie potężnych ataków Man-in-the-Middle. - Microsoft CryptoAPI “CurveBall” (CVE-2020-0601): W 2020 roku odkryto lukę w bibliotece Windows Crypt32.dll. Kod Microsoftu źle walidował certyfikaty oparte o krzywe eliptyczne (ECC). Pozwalało to cyberprzestępcom na “podpisanie” złośliwego oprogramowania fałszywym certyfikatem, który udawał np. Microsoft, a system Windows całkowicie mu ufał.
- Debian i przewidywalne klucze (CVE-2008-0166): W 2008 roku opiekun pakietu OpenSSL w systemie Debian, chcąc usunąć ostrzeżenia analizatora kodu, usunął kluczowe linie odpowiadające za losowość generatora. Przez blisko 2 lata systemy generowały słabe klucze - istniało jedynie 32 768 możliwych wariantów.
Złota zasada kryptografii głosi: “Don’t roll your own crypto”. Choć twórcy podatnego oprogramowania nie implementowali własnej matematyki, popełnili błąd, próbując “ręcznie” obsłużyć logikę walidacji certyfikatów. Wnioski są bezlitosne: nie pisz własnych instrukcji warunkowych do sprawdzania wystawców - zamiast tego powierz całą weryfikację zaufanej, audytowanej bibliotece, która rygorystycznie i bezbłędnie zrealizuje każdy krok ze skomplikowanego standardu RFC. W Gadnet dokładnie tego się trzymamy.