Wrażliwe dane medyczne milionów Polaków na wyciągnięcie ręki

opensecurity.pl 1 miesiąc temu

Tekst ten zacząłem pisać na początku roku ze świadomością, iż będę mógł go opublikować dopiero za parę miesięcy. Jest 10 czerwca i właśnie z CERT Polska otrzymałem powiadomienie o upublicznieniu w formie wpisów CVE serii podatności, których dotyczyć będzie artykuł, co jednocześnie stanowi zielone światło dla jego publikacji. Na początek zerknijmy co umożliwiały zgłoszone do CERT-u i aktualnie załatane już podatności:

  • dostęp do dokumentacji medycznej pacjentów (w tym wyniki badań, historia wizyt i chorób, przepisywane leki, przypisy prowadzone przez lekarzy)
  • dostęp do danych osobowych (w tym dane adresowe i kontaktowe, daty urodzenia oraz numery PESEL)
  • możliwość modyfikacji powyższych danych
  • dostęp do certyfikatów lekarzy i systemu e-WUŚ NFZ
  • możliwość wyszukiwania i identyfikacji po numerze PESEL dowolnego pacjenta
  • do pewnego momentu możliwość ustalenia statusu szczepienia na COVID
  • możliwość wystawiania recept (również refundowanych)
  • możliwość wystawiania skierowań na badania
  • możliwość wystawiania zwolnień lekarskich (a przy okazji weryfikacji danych pracodawcy)

Jak do tego doszło?

Na przełomie 2023 i 2024 roku nasza branża żyła dużym wyciekiem danych medycznych z laboratoriów diagnostycznych Alab. Krótko po tych wydarzeniach odezwał się do mnie jeden z czytelników bloga z informacją, iż jest w posiadaniu danych o dużo bardziej sensacyjnym charakterze. Poinformował mnie, iż dane medyczne milionów Polaków są łatwo dostępne w Internecie i co więcej, w sprawie tej nikt nie chce nic zrobić pomimo, iż próbował nią zainteresować firmy za to odpowiedzialne oraz największe portale poświęcone cyberbezpieczeństwu. Podejrzewał choćby swego rodzaju zmowę milczenia w tym temacie.

Przyznam, iż początkowo mail od niego wydał mi się trochę zbyt sensacyjny i z braku wolnego czasu odłożyłem tę informację do weryfikacji na później. Czytelnik przypomniał mi się po jakimś czasie ponownie, co skłoniło mnie w końcu do przyjrzenia się sprawie bliżej. Przekazana mi przez niego dokumentacja dotyczyła kilku aplikacji pochodzących od różnych producentów i wykorzystywanych masowo w służbie zdrowia. Z aplikacji tych korzystają m.in. przychodnie i poradnie lekarskie, gabinety dentystyczne, apteki oraz lekarze prowadzący indywidualną praktykę.

Problem w dużym skrócie sprowadzał się do tego, iż bazy danych tych aplikacji dostępne są w Internecie, a dostęp do nich odbywa się zawsze przy użyciu tych samych (ale różnych dla wszystkich producenta) zaszytych w kodzie danych uwierzytelniających. Podatność ta określana jest mianem 'hard-coded credentials’ i w macierzy MITRE przypisano jej identyfikator CWE-798.

Hard-coded credentials – jak je znaleźć

Podejrzeń, iż dana aplikacja może zawierać ów podatność możemy nabrać już na etapie instalacji. jeżeli w trakcie tego procesu nie jesteśmy proszeni o zdefiniowanie nowego użytkownika lub hasła dla administratora bazy danych to jest to pierwsza czerwona flaga. Kolejnym sygnałem może być brak w oficjalnej dokumentacji informacji na temat tego jak zmienić hasło administratora bazy. A niektórzy producenci praktycznie wprost przyznają się do tego, iż hasła są na stałe zaszyte w aplikacji ostrzegając w procesie instalacji by nie zmieniać domyślnych haseł.

Czasami jednak problem powstaje na życzenie samego administratora instalującego aplikację. Na przykład instalator aplikacji KS-Apteka firmy Kamsoft podpowiada w procesie instalacji, iż domyślne hasła warto zmienić, jednak sugestię tę można było zignorować, w efekcie czego w Internecie dało się namierzyć serwery baz danych Firebird i zalogować do nich domyślnymi danymi widocznymi w instalatorze:

Swoją drogą 'sysdba’ z hasłem 'masterkey’ do domyślny użytkownik serwera bazy danych Firebird, którego spotkać można nie tylko w powyższej aplikacji. jeżeli używacie w swoich środowiskach systemu korzystającego z tego silnika baz danych, to warto przyjrzeć się ich konfiguracjom.

Co jednak jeżeli instalator ani dokumentacja systemu nie wspomina nic na temat domyślnych haseł, a my nabraliśmy podejrzeń, iż mogą one być na stałe zaszyte w kodzie? Zobaczmy na przykładzie aplikacji „drEryk Gabinet” w jaki sposób przechowywane były tam hasła.

Plik instalatora dostarczany w formacie wykonywalnym (drErykSetup.exe) rozpakowujemy np. przy użyciu 7-zipa. W otrzymanym folderze znajdziemy podfolder o nazwie $TEMP, a w nim plik o nazwie create_roles.sql z następującą zawartością:

Objaśnienie dla mniej technicznych czytelników – powyżej widzimy polecenia języka SQL, dzięki których tworzone są na serwerze role użytkowników, przypisywane im uprawnienia i definiowane hasła. Zakryte fragmenty zawierają hashe haseł w formacie md5. Problem mamy zatem dwojaki – po pierwsze zakodowane na stałe hasła, po drugie ich hashe generowane są z użyciem algorytmu MD5, który od dawna uznawany jest za niewystarczająco bezpieczny ze względu na łatwość łamania takich haseł. W artykule pt. „Łamanie haseł na Teslach V100 – pół terahasha na sekundę” opisywałem m.in. jak dzięki ogólnodostępnych maszyn AWS możemy łamać takie hasła z prędkością 442 GH/s (442 miliardy hashy na sekundę!). A z kolei w tym filmie wyliczałem, iż 8 znakowe hasło złamiemy w ten sposób w niecałe 3 godziny za około 270 zł (4 lata temu).

A co gdyby twórca aplikacji postarał się bardziej i generował hashe z pomocą bezpieczniejszego algorytmu, np. SHA-256? Z ich łamaniem byłoby trudniej, ale łamanie hashy to nie jedyna metoda wyciągnięcia z aplikacji zakodowanych danych uwierzytelniających. Możemy np. posłużyć się API Monitorem i podsłuchiwać wywołania funkcji w bibliotekach używanych przez aplikację. I tak przyglądając się bibliotece libpq.dll natrafić mogliśmy na wywołanie funkcji PQconnectdb, do której przekazywane były parametry połączenia z bazą danych:

Zakryte powyżej nazwa użytkownika i hasło odpowiadają tym zdefiniowanym w pliku create_roles.sql i przez długi czas używane były jako domyślne przy każdej instalacji aplikacji. Hasło składa się z ośmiu znaków – duże i małe litery oraz cyfry, bez znaków specjalnych. I podkreślić należy, iż jest to jedna z popularniejszych aplikacji, a już kilka lat temu producent chwalił się ponad 8. tysiącami sprzedanych licencji.

Jak ustalić skalę problemu?

Tysiące przychodni, gabinetów i lekarzy korzystających z podatnej aplikacji to już wydaje się spory problem. A przypomnijmy, iż to tylko jedna z kilku aplikacji, w których podatność ta została zidentyfikowana. Ale jak ustalić ile serwerów baz danych dla powyższych systemów rzeczywiście jest dostępnych w Internecie? Przecież są to aplikacje, które instalowane powinny być w lokalnych, zamkniętych sieciach.

Na ostatnim obrazku z API Monitora, w wywołaniu połączenia z bazą danych widoczny jest numer portu 5491. I jest to informacja w tym wypadku bardzo przydatna, ponieważ aplikacja drEryk, mimo iż korzysta z serwera PostgreSQL, to właśnie na tym porcie, a nie na domyślnym 5432 nawiązuje połączenie z bazą. Możemy więc pokusić się o przeskanowanie wszystkich puli adresów IP przypisanych do Polski i znalezienie otwartych portów 5491. Jak to zrobić? Pule adresowe dla poszczególnych państw znajdziemy np. na stronie https://www.ipdeny.com/ipblocks/. Plik pl.zone zawierający aktualnie ponad 4 tys. bloków adresowych przekazujemy jako parametr do narzędzia masscan wraz ze wskazaniem portu 5491:

> masscan -iL pl.zone -p 5491 Starting masscan 1.3.2 (http://bit.ly/14GZzcT) at 2024-01-15 12:03:53 GMT Scanning 20928520 hosts [1 port/host] Discovered open port 5491/tcp on a.b.c.d Discovered open port 5491/tcp on a.b.c.d Discovered open port 5491/tcp on a.b.c.d Discovered open port 5491/tcp on a.b.c.d Discovered open port 5491/tcp on a.b.c.d Discovered open port 5491/tcp on a.b.c.d Discovered open port 5491/tcp on a.b.c.d . rate: 0.10-kpps, 0.02% done, 60:46:09 remaining, found=7

Jak widać powyżej przeskanowanie wszystkich ponad 20 milionów adresów na domowym komputerze i łączu zajmuje kilkadziesiąt godzin. Na szybkim łączu można pewnie zejść do kilku godzin. W każdym razie już po kilku chwilach skanowania zaczynamy otrzymywać listę adresów IP (powyżej zanonimizowane jako „a.b.c.d”), na których port 5491 został zidentyfikowany jako otwarty. Osobiście nie kontynuowałem pełnego skanowania, ale dla potwierdzenia, iż mamy rzeczywiście do czynienia z instancjami baz danych podatnej aplikacji dokonałem próby połączenia z jedną z nich i zakończyła się ona pomyślnie.

I tutaj przestroga, dla tych, którzy chcieliby podejmować się podobnych działań: nie róbcie tego – kodeks karny za tego typu aktywność przewiduje konkretne kary (nawet do 5 lat pozbawienia wolności). Ja pozwoliłem sobie na trochę więcej ze względu na fakt, iż jestem autorem serwisu zarejestrowanego jako czasopismo poświęcone cyberbezpieczeństwu i występuję w roli badacza-sprawozdawcy, ale co najważniejsze swoje ustalenia zgłosiłem do CERT-u, a CERT do producentów aplikacji i to im pozostawiłem dalsze kroki.

Wróćmy jeszcze na moment do czytelnika, który zgłosił się do mnie z prośbą o nagłośnienie problemu. Na mocy prawa prasowego poprosił mnie on o zapewnienie anonimowości i przedstawił się jako reprezentant zespołu badaczy. Wspólnie z tym zespołem badając temat na przestrzeni wielu miesięcy oszacował, iż dane zebrane w ogólnodostępnych bazach mogą dotyczyć nawet 10 milionów pacjentów. Tej informacji nie byłem jednak w stanie potwierdzić nie ryzykując konfliktu z prawem – musiałbym namierzyć i połączyć się z wszystkimi ogólnodostępnymi bazami, co przekraczałoby działania zmierzające do samego wykrycia i zgłoszenia podatności.

Co znajdowało się w bazach?

Po połączeniu z serwerem bazy danych jednej z podatnych aplikacji na uwagę zasługują dwie tabele – drt_patients oraz drt_users. Tabela drt_patients zawierała ponad 16 tysięcy rekordów:

Każdy z pacjentów w tabeli opisany mógł być dzięki ok. 100 pól. Znajdują się wśród nich takie dane jak imię, nazwisko, dane adresowe i kontaktowe (e-mail, telefon), data urodzenia. Pełna lista pól opisujących pacjenta widoczna jest na poniższym obrazku, ale nie wszystkie z nich i nie dla wszystkich pacjentów były wypełnione. Głównie występowały te podkreślone na czerwono, natomiast PESEL, NIP i numer dowodu raczej szczątkowo:

Jeszcze ciekawiej wygląda tabela drt_users zawierająca dane użytkowników aplikacji, czyli personelu medycznego. W tym wypadku lista pól opisujących pracownika wygląda następująco:

PESEL występuje tutaj w 100% przypadków, a poza nim pojawia się login i hasło do zarządzanego przez NFZ systemu e-WUŚ (Elektroniczne Weryfikacja Uprawnień Świadczeniobiorców). System ten pozwala po numerze PESEL zidentyfikować dowolną osobę w kraju i sprawdzić czy przysługują jej aktualnie świadczenia NFZ.

Świadomość personelu medycznego – dramat

Skupmy się przez chwilę nie na błędach aplikacji, ale na dramacie jakim jest świadomość tzw. personelu medycznego na temat cyberbezpieczeństwa. Tabela drt_users zawiera m.in. pytanie bezpieczeństwa oraz odpowiedź na nie. Ogromna większość pracowników jako pytanie bezpieczeństwa wybiera imię syna, córki, męża lub żony, zdarza się też ilość dzieci lub wiek. Ale uczcijmy teraz chwilą zadumy zaznaczonych poniżej na czerwono użytkowników, którzy jako pytanie bezpieczeństwa wybrali imię, a jako odpowiedź na nie wpisali imię… własne:

I przypomnijmy, iż konto każdego z powyższych pracowników daje w tym wypadku dostęp do danych wrażliwych 16 tysięcy pacjentów.

Kryptografia – nie róbcie tego w domu

W powyższej tabeli widzimy kolumnę usr_ewus_password, która jak już wspomniałem przechowuje hasła pracowników do systemu e-WUŚ. I tutaj natrafiamy na kolejny problem. Hasła te nie mogą być przechowywane w formie hashy, ponieważ aplikacja musi mieć możliwość skorzystania z tych haseł łącząc się z systemem NFZ w imieniu pracownika. Jednocześnie producent aplikacji słusznie nie chciał przechowywać ich w formie jawnej. Niestety żeby rozwiązać ten problem zdecydowano się na opracowanie własnego standardu kodowania haseł. I już na pierwszy rzut oka widzimy, iż coś jest tutaj nie tak. Hasło w formie zakodowanej dla ogromnej większości użytkowników rozpoczyna się od tego samego ciągu znaków: F7C87796DF33, co nie powinno mieć miejsca choćby gdyby hasła były do siebie bardzo podobne i zaczynały się tak samo. Nie bez powodu jedną z częściej powtarzanych rad w kontekście bezpieczeństwa jest ta mówiąca, by nie tworzyć własnej kryptografii.

Na potwierdzenie faktu, iż przyjęty standard kodowania haseł nie gwarantuje wysokiego poziomu bezpieczeństwa oddam na chwilę głos naszemu czytelnikowi, który pochylił się również nad tym zagadnieniem:

Kilka kolejnych eksperymentów i zauważamy, iż n-ty i n+1-wszy znak w „szyfrze” hasła zależy od n-tego znaku w haśle oraz od samego n. Generujemy tablicę haseł i ich szyfrów dla wszystkich ciągów jednakowych znaków i jesteśmy w stanie z szyfru odzyskać hasło.

Przesłał mi on też kod PHP realizujący to zadanie, ale ze względu na fakt, iż hasła przez cały czas przechowywane są w tym formacie nie będę go tutaj upubliczniał.

Certyfikaty lekarzy – robi się ciekawie

Kolejny wątek w naszej historii związany jest z tabelą drt_files. Zawiera ona certyfikaty lekarzy w formie plików PFX zabezpieczonych hasłem. Do czego lekarzom certyfikaty? Dzięki nim potwierdzają swoje uprawnienia do:

  • Wystawienia dowolnej recepty (również refundowanej)
  • Wystawienia skierowania na badania
  • Wystawienia zwolnienia lekarskiego (a przy okazji można też zweryfikować pracodawcę i dane adresowe pacjenta)

Do wszystkich powyższych działań potrzebny pozostało certyfikat przychodni, ale tak się składa, iż on również zapisany jest w bazie i to razem z hasłem żeby lekarz nie musiał już go wprowadzać. Do pełni (nie)szczęścia brakuje nam zatem tylko hasła do certyfikatu lekarza, które wprowadzane jest manualnie w chwili korzystania z certyfikatu.

Okazuje się jednak (co za zaskoczenie), iż część lekarzy jako hasła do certyfikatu używa tego samego hasła, którym logują się do aplikacji. A żeby było straszniej, hasła użytkowników aplikacji przechowywane są z użyciem tego samego algorytmu „szyfrującego”, co hasła do e-WUŚ. Czyli potencjalny intruz uzyskujący dostęp do bazy dzięki domyślnego (do niedawna) użytkownika i hasła mógł wejść w posiadanie kompletu danych pozwalających na podszycie się pod lekarza i wystawienie w jego imieniu recepty, skierowania bądź zwolnienia.

A co z certyfikatami, do których hasło nie jest takie samo jak hasło użytkownika? Bardzo często jest to po prostu 4-cyfrowy PIN. Jego złamanie jest możliwe np. dzięki narzędzia crackpkcs i w wielu przypadkach kończy się takim wynikiem:

Brute force attack - Starting 4 threads Alphabet: 0123456789 Min length: 1 Max length: 4 ********************************************************** Brute force attack - Thread 2 - Password found: 1111 **********************************************************

Które aplikacje były podatne?

W przekazanej mi przez czytelnika dokumentacji, poza wspomnianą już w artykule aplikacją drEryk i oprogramowaniem dla aptek Kamsoftu podatność została wskazana w systemach mMedica Asseco, Eurosoft Przychodnia oraz Simple Care. Przy czym z naszej korespondencji wynikało, iż czytelnik do tematu tego wrócił po dłuższej, co najmniej kilkunastomiesięcznej przerwie, na fali doniesień o wycieku z laboratoriów Alab.

Wspomniane na początku artykułu podejrzenia, iż w sprawie tej istnieje jakaś zmowa milczenia wynikały m.in. z faktu, iż na zgłoszenia czytelnika nie zareagował ani żaden z producentów oprogramowania, ani z branżowych portali, które próbował tym tematem zainteresować. Dla mnie wyjaśnienie tej tajemnicy jest jednak prozaiczne. Producenci oprogramowania, o ile nie prowadzą oficjalnych programów typu bug bounty, najczęściej właśnie po cichu próbują rozwiązać problem unikając rozgłosu. Moi koledzy z branży, którym zasięgów mogę jedynie pozazdrościć mają natomiast podobnych zgłoszeń pełne skrzynki i reagują na nie na tyle, na ile czas im pozwala. A choćby u mnie wiadomość ta musiała swoje przeleżeć zanim do niej wróciłem.

Po przekazaniu przeze mnie sprawy do CERT Polska pracownicy CERT-u kontaktowali się z każdym z producentów. W toku postępowania ustalili, iż Asseco oraz Kamsoft podatności w swoich aplikacjach wykryły już wcześniej wewnętrznie (a może był to efekt zgłoszenia ze strony czytelnika, na które nie doczekał się odpowiedzi?). W przypadku aplikacji drEryk, Eurosoft Przychodnia oraz SimpleCare producenci zobowiązali się natomiast do wyeliminowania podatności oraz przypilnowania aktualizacji u swoich klientów, czego dokonali w minionych tygodniach przed upublicznieniem niniejszego artykułu.

CERT Polska zakończył temat przypisując identyfikatory CVE podatnościom w trzech wymienionych aplikacjach CVE-2024-1228 (Eurosoft Przychodnia) CVE-2024-3699 (drEryk Gabinet) CVE-2024-3700 (SimpleCare) oraz publikując artykuł, w którym zawarł krótkie rekomendacje dotyczące definiowania haseł do baz danych i umożliwiania ich zmiany, a także udostępniania baz wyłącznie w ramach sieci lokalnych lub za pośrednictwem połączeń VPN z uwierzytelnianiem dwuskładnikowym.

Nie wiem czy to za sprawą działań CERT-u, ale system e-WUŚ od 6 maja wymaga również stosowania uwierzytelniania dwuskładnikowego.

Podziękowania

Poza zespołem CERT Polska i producentami podatnych aplikacji, którzy zareagowali na zgłoszenia podziękowania należą się chyba przede wszystkim czytelnikowi, który wraz z zespołem poświęcił wiele miesięcy najpierw na zbadanie tematu, a następnie na próby jego nagłośnienia. Nie do końca pewnie podobało się to autorom oprogramowania, ale bez wątpienia uchroniło nas przed trzęsieniem ziemi jakie nastąpiłoby gdyby podatności te namierzyła jakaś wroga grupa APT. Dziś pewnie czytalibyśmy nie o załatanych podatnościach a o danych wrażliwych milionów Polaków krążących po darknecie.

Dziękuję też kolegom, którzy na styczniowym spotkaniu Poznań Security Meetup po wstępnym zapoznaniu się z tematem zarekomendowali pilne zgłoszenie podatności do CERT Polska. Sam pewnie ociągałbym się nieco dłużej próbując najpierw kontaktów z producentami aplikacji. CERT ma jednak do tego dużo lepsze zaplecze kadrowe i umocowanie prawne, co daje mu odpowiednią siłę przebicia.

Zostaw e-mail aby otrzymać powiadomienia o nowościach oraz dostęp do wszystkich bonusowych materiałów przygotowanych wyłącznie dla subskrybentów.

Idź do oryginalnego materiału