Czy można wdrożyć zaawansowany zestaw zabezpieczeń tylko po to, aby przez przypadek zapomnieć go użyć? Dziś opowiem, jak powstała podatność umożliwiająca wejście na konto dowolnego użytkownika w większości systemów Ministerstwa Sprawiedliwości i kilku innych usługach publicznych. Przeprowadzenie tak poważnego ataku nie wymagało znajomości programowania ani nawet użycia jakichkolwiek specjalistycznych narzędzi hakerskich.
Wcześniejsza część mojego badania dotyczyła dodatku do przeglądarki ułatwiającego składanie podpisów kwalifikowanych pod dokumentami i logowanie się do różnych usług. Analizowaliśmy więc maszynerię działającą prawie wyłącznie po stronie klienta. Zaintrygowany wynikami z poprzedniej części stwierdziłem, że skoro tam zdarzyło się “trafienie krytyczne”, to koniecznie trzeba się również przyjrzeć algorytmom po stronie serwera. Tym razem spróbujemy zaatakować serwisy administracji publicznej obsługujące logowanie podpisem kwalifikowanym.
Seria “Badanie e-podpisów”
Artykuł stanowi część cyklu opisującego mój hobbystyczny projekt badania bezpieczeństwa oprogramowania związanego z obsługą podpisów kwalifikowanych.
- Zdalne wykonanie kodu w SzafirHost – [CVE-2026-26928] [Badanie e-podpisów, cz. 1]
- Hakowanie e-Sądu YubiKeyem – [Badanie e-podpisów, cz. 2]
- Ominięcie uwierzytelniania w ZUS-ie i systemach e-Zdrowia, czyli o krok od cyberchaosu – [CVE-2026-9058] [Badanie e-podpisów, cz. 3]
| Streszczenie całej serii w postaci niewymagającej od czytelnika posiadania rozległej wiedzy technicznej znajduje się w odrębnym artykule: “Krytyczna podatność umożliwiająca całkowite ominięcie logowania w ZUSie, e-Sądzie i systemach e-Zdrowia”. |
Co to jest logowanie podpisem kwalifikowanym?
W uproszczeniu:
- Strona internetowa generuje plik XML, który można rozumieć jako “oświadczenie o chęci zalogowania się”.
- Użytkownik podpisuje podpisem kwalifikowanym plik XML, używając do tego specjalnego oprogramowania.
- Złożenie podpisu powoduje, że do oryginalnego pliku XML zostaną doklejone dodatkowe parametry (zgodnie ze standardem podpisów XAdES):
- certyfikat zawierający nasze imię, nazwisko i PESEL – wystawiony przez uprawniony podmiot;
- podpis cyfrowy złożony przez nasze urządzenie do generowania podpisów;
- informacje o upoważnionym podmiocie, który wydał nasz certyfikat kwalifikowany;
- Podpisany plik jest wysyłany do backendu określonej aplikacji internetowej.
- Serwer weryfikuje podpis pod plikiem XML. Zostajemy uwierzytelnieni na stronie internetowej z jednoczesnym potwierdzeniem naszej fizycznej tożsamości obywatela.

Dzięki takim specyficznym właściwościom, ta metoda logowania jest chętnie wykorzystywana przez serwisy administracji publicznej.

Koncepcja wózka sklepowego
Wytłumaczę pomysł na atak przez nieco przyziemną analogię. Niegdyś duże wózki sklepowe były zabezpieczone w taki sposób, że do niewielkiego urządzenia z tyłu wózka trzeba było włożyć monetę, na przykład dwuzłotówkę, aby zwolnić blokadę i zyskać możliwość jeżdżenia wózkiem po sklepie. Oczywiście ten oficjalny sposób nie był jedynym, wszak zamiast monety można było włożyć kawałek plastiku o zbliżonych wymiarach. Istniały również specjalne metalowe klucze, które pozwalały oszukać blokadę.

Dlaczego to działało? Oficjalna specyfikacja, co prawda, nakazywała włożenie dwóch złotych, ale urządzenie w praktyce nie weryfikowało, czy użyliśmy prawdziwej monety, czy też włożyliśmy do slotu cokolwiek dostatecznie podobnego.
“Podrobiona” karta do podpisu
Spróbujmy dosłownie przenieść tę banalną koncepcję na grunt podpisów elektronicznych i stworzyć “wytrych”. W tym przypadku będzie nim fałszywa karta do podpisu kwalifikowanego, która:
- rozmawia identycznym protokołem, co prawdziwa karta od któregoś z uprawnionych wystawców, oraz
- przedstawia mój prawdziwy certyfikat podpisu kwalifikowanego, ale
- składany przez kartę podpis cyfrowy będzie losowym bezsensownym ciągiem bajtów.
Gdyby udało się pójść taką ścieżką, moglibyśmy takiej karty spróbować użyć niemal wszędzie, w dodatku działałoby z nią oryginalne oprogramowanie.
Pliki XML podpisane z użyciem takiej fałszywej karty będą miały prawidłową strukturę, ale oczywiście nie mają prawa przejść weryfikacji zgodnej ze standardem XAdES. W teorii ten atak nie ma prawa działać, oczywiście, o ile mechanizmy weryfikacji wszystkich aplikacji operujących na e-podpisach są zaimplementowane tak, jak należy.

Stworzenie takiego narzędzia chaosu wymaga kupienia niezaprogramowanej karty typu “JavaCard”, a później napisania dla niej firmware w sposób zgodny z powyższym pomysłem, wgrania go na kartę, skonfigurowania jej i… gotowe.
No prawie. Nie trzeba było długich chwil refleksji, aby dojść do wniosku, że opracowanie takiego narzędzia od podstaw generuje zbyt duży nakład czasowy, biorąc pod uwagę znikome szanse na zadziałanie ataku. Od tej pory poszedłem ścieżką przerabiania gotowych rozwiązań.
Po kilku godzinach młócenia kodu z GitHuba zrezygnowałem również z tego pomysłu, okazało się bowiem, że idealne rozwiązanie cały czas leżało przede mną na biurku, a był nim YubiKey 5.
Atak z użyciem YubiKeya
YubiKey posiada moduł PIV (Personal Identity Verification), który działa prawie tak samo jak karta do podpisu kwalifikowanego i można się z nim komunikować przez interfejs PKCS#11, dokładnie tak jak z prawdziwą kartą. Dzięki temu nie będzie trzeba zbyt wiele ingerencji, aby “przestawić” oryginalne oprogramowanie do współpracy z YubiKeyem.
W dodatku istnieje wygodny interfejs graficzny, który umożliwi nam przeprowadzenie całej operacji.

Najpierw użyjemy funkcji “Generate” i wygenerujemy na YubiKeyu klucz prywatny RSA 2048 wraz z pasującym do niego samodzielnie wygenerowanym i podpisanym certyfikatem (ang. self-signed). Następnie zaimportujemy na ten slot mój certyfikat kwalifikowany.
Oczywiście, spowoduje to absurdalną konfigurację YubiKeya – na jednym slocie będzie prawdziwy certyfikat kwalifikowany oraz kompletnie niepasujący do niego klucz prywatny. Gdy będziemy chcieli coś takim narzędziem podpisać, to wygenerowany podpis zawsze będzie technicznie błędny. Z kolei sam podpisany plik wraz z całą swoją strukturą zostanie faktycznie wygenerowany. Dokładnie o to nam tutaj chodzi.
Jedyne, co musimy zrobić, to wejść na jakąś stronę obsługującą logowanie podpisami kwalifikowanymi i spróbować użyć naszego klucza USB. Co prawda, na początku oprogramowanie do składania podpisów twierdzi, że nie było w stanie znaleźć żadnych certyfikatów, ale wystarczy wskazać w ustawieniach, że nasza “karta kwalifikowana” do działania potrzebuje dodatkowej biblioteki, po czym wskazać plik DLL z modułem PKCS#11 dla YubiKeya.
Pora na testy. Pierwszym obiektem eksperymentalnym był Moduł Tożsamość Ministerstwa Sprawiedliwości, przez który chciałem zalogować się do Portalu Rejestrów Sądowych. I ku mojemu ogromnemu zdziwieniu, udało się…
Podatne podmioty
Mając gotowe narzędzie, zgodnie z założeniami, mogłem szybko i wygodnie przetestować wszystko, co się nawinęło. Opisaną techniką byłem w stanie włamać się do:
- wszystkich serwisów obsługujących logowanie przez Moduł Tożsamość Ministerstwa Sprawiedliwości, między innymi:
- Portalu Rejestrów Sądowych,
- e-Sądu w Lublinie,
- Krajowego Rejestru Zadłużonych,
- Repozytorium Tytułów Wykonawczych;
- e-Serwisu Urzędu Dozoru Technicznego (eudt.gov.pl);
- usług elektronicznych Publicznych Służb Zatrudnienia (praca.gov.pl);
- portalu e-dokumenty – Centrum Informatycznych Usług Wspólnych Olsztyna (edokumenty.olsztyn.eu).
Jedynym warunkiem do przeprowadzenia ataku było posiadanie pliku z certyfikatem kwalifikowanym ofiary, który jeszcze nie wygasł i nie został odwołany. Skąd go pozyskać?
Kwestia certyfikatu
Wystarczy, że będziemy w posiadaniu dowolnego dokumentu opatrzonego przez tę osobę podpisem kwalifikowanym. Certyfikat podpisującego będzie tam załączony i można go trywialnie wyeksportować, również za pomocą konwencjonalnych narzędzi.

Dodatkowo źródłowy dokument powinien być wystawiony przez ofiarę na przestrzeni ostatnich kilku miesięcy, tak aby certyfikat użyty do podpisu był jeszcze w granicach terminu ważności.
W tym miejscu należy koniecznie wspomnieć, że możliwość uzyskania czyjegoś pliku z certyfikatem nie jest podatnością bezpieczeństwa. Taka możliwość wynika ze sposobu działania całego systemu podpisów. Gdyby wszystko było zaimplementowane poprawnie, posiadanie takiego pliku nadal nie umożliwiłoby nam przeprowadzenia jakiegokolwiek ataku.
Możliwość złożenia podpisu w czyimś imieniu zależy od możliwości uzyskania dostępu do jego klucza prywatnego, a ten w przypadku podpisów kwalifikowanych zawsze znajduje się na fizycznym urządzeniu albo w chmurze wystawcy podpisów – to są komponenty odpowiedzialne za zabezpieczenie całego procesu. Tym samym dostępność pliku z certyfikatem nie niesie żadnych implikacji w tym kontekście.
Co dokładnie zawiodło?
O ile sama koncepcja podpisów kwalifikowanych jest bezpieczna pod względem kryptograficznym i faktycznym, o tyle tutaj zaszło coś wysoce niepokojącego na gruncie systemowym. Aplikacje w ogóle nie sprawdzały poprawności złożonych podpisów po stronie serwera. Wystarczył więc sam fakt przejścia procesu od początku do końca i przesłania komunikatu o określonej strukturze.
Mając to na uwadze, ciężko oprzeć się wrażeniu, że integratorzy po stronie podmiotów nie zrozumieli zasady działania całego ekosystemu. Dlaczego tak się stało? Trudno gdybać, ale masowy charakter podatności wskazuje na to, że użyte komponenty do weryfikacji podpisów mogły być niedostatecznie udokumentowane albo dokumentacja nie omawiała zagadnienia architektury procesu weryfikacji w wyczerpujący sposób.
Co więcej, przez co najmniej kilka lat nie wykrył tego żaden test penetracyjny, pomimo że podatność jest możliwa do odnalezienia w formule “black-box”. Czy nastąpiło tu dogmatyczne założenie, że jest to bezpieczny komponent i nie ma konieczności testowania bezpieczeństwa? A może był to element zakresu testów, ale pomijano go ze względu na brak rozpowszechnionych technik i standardów testowania tego typu mechanizmów? Te i wiele innych refleksji pozostawiam zainteresowanym.
Dodatkowo czarę goryczy przelewa fakt, że przeprowadzenie ataku nie wymagało użycia żadnego specjalistycznego “narzędzia hakerskiego”. Nie było też konieczności napisania chociaż jednej linijki kodu czy nawet komendy wiersza poleceń. Cały atak, jak zaprezentowałem, da się wykonać przez GUI, używając standardowych programów.
To jeszcze nie koniec…
Zainspirowany osiągniętymi rezultatami postanowiłem zainwestować w moje badanie dodatkowe kilkadziesiąt godzin i rozwinąć odkrytą technikę ataku, a to pozwoliło zhakować kolejne podmioty – te, które były odporne na sztuczki opisane w tym artykule.
Co jeszcze i w jaki sposób udało się zhakować, a także jak wyglądała obsługa tych podatności na osi czasu – o tym w kolejnej, ostatniej już części.
Następna część: Ominięcie uwierzytelniania w ZUS-ie i systemach e-Zdrowia, czyli o krok od cyberchaosu – [CVE-2026-9058] [Badanie e-podpisów, cz. 3]