szukaj

07.02.2025 | 10:07

avatar

Antoni Mróz

Mały, ale ciekawy incydent w PKOl (i jak przez przypadek trafić na podobne)

Polski Komitet Olimpijski pozazdrościł najwyraźniej wycieku z Polskiej Agencji Antydopingowej i postanowił dorzucić coś od siebie. Na szczęście – jest to „tylko” wyciek części strony internetowej olimpijski.pl zawartej w przypadkowo upublicznionym folderze .git. Na nieszczęście – znajdował się tam czteroletni backup bazy danych WordPressa.

Ten artykuł czekał kilka miesięcy na publikację
Informacje o podatności otrzymaliśmy w momencie, gdy wokół Polskiego Komitetu Olimpijskiego trwało spore zamieszanie polityczno-organizacyjne, więc postanowiliśmy trochę poczekać, by nie brać w nim udziału. Podatność jest ponadczasowa, więc nic nie szkodzi opisać ją dzisiaj.

To nie jest aż tak poważny incydent

Obecność danych na serwerze PKOl zgłosił nam jeden z Czytelników, który pragnął pozostać anonimowy. Wewnątrz nieświadomie udostępnionej bazy oraz plików strony trudno się doszukać danych wrażliwych, tak jak w przypadku wycieku z POLADA. W zasadzie większość elementów, takich jak artykuły czy opisy igrzysk, i tak jest dostępna publicznie. Niemniej ujawnienie kodu źródłowego strony i zainstalowanych wtyczek oraz hashy haseł administratorów to nadal wpadka, która nie powinna się zdarzyć.

Odzyskiwanie źródeł

Git to narzędzie do kontroli wersji – używają go programiści, by dokumentować i śledzić zmiany tworzonego kodu. W kodzie źródłowym często znajdują się informacje, które nie powinny być publicznie dostępne, jak np. klucze dostępowe czy hasła. Czasem jednak twórcy stron WWW popełniają błąd i na serwerze klienta umieszczają, obok właściwej strony, także niewidoczne gołym okiem, ale dostępne publicznie repozytorium jej kodu źródłowego.

Publiczny folder repozytorium Git wykryć jest bardzo łatwo – wystarczy do tego specjalna wtyczka DotGit do przeglądarki, która automatycznie sprawdza każdą odwiedzaną witrynę i po wykryciu podatnego katalogu pokazuje odpowiednie powiadomienie. Można zatem dalej zwiedzać internet i przez przypadek raz na miesiąc trafić na podatną witrynę. Wtyczka umożliwia także pobranie całego takiego katalogu. W tym przypadku udało się ściągnąć 204 MB kodu źródłowego jednym kliknięciem. Tak po prostu.

Co ciekawe, administrator podjął nieskuteczną próbę zablokowania folderu przed dostępem z zewnątrz. Problem w tym, że ta blokada nie działała na pliki i podkatalogi wewnątrz folderu. Zabezpieczenie zostało wdrożone, ale nie działało.

Może i „forbidden”, tylko co z tego?

Samo pobranie danych jednak nie wystarczy. Nie posiadają one formy czytelnej dla zwykłego człowieka – kod trzeba jeszcze wypakować. Do tego celu można zastosować polecenie git reset --hard, jednakże skorzystanie z takiego narzędzia jak GitTools pozwala na więcej. Kiedy .git pobierze się tylko częściowo, GitTools jest w stanie odratować, co tylko się da, podczas gdy linia poleceń potrafi się poddać nawet przy podstawowych komendach.

Nawet proste odczytanie listy commitów wcale nie jest takie łatwe!

GitTools przywrócił 55 wersji kodu, gdzie każda wersja przedstawia kolejne zmiany w kodzie witryny (tzw. commity). W każdym katalogu z wersją umieszczona jest też notatka z metadanymi – commit-meta.txt.

Jeden z commitów

Proces zbierania metadanych można zautomatyzować, tworząc skrypt czytający rekursywnie takie pliki.

Jak się okazuje, kolejno numerowane wersje rozjeżdżają się chronologicznie. Podczas ręcznej analizy danych w pierwszym lepszym katalogu udało mi się znaleźć zrzut bazy danych pkol.sql. Po dokładniejszej analizie zauważyłem, że znajdował się on w 54 z 55 wersji. Co wyróżniało tę jedną? W commicie z 27 lipca 2024 08:50:21 nie było ani jednego pliku. Dlaczego? Może sortowanie chronologiczne przyniesie nam odpowiedź.

Jak się okazuje, „pusty” commit z 27 lipca jest najnowszy, co wygląda na kolejną próbę zabezpieczenia plików. Przecież sam sens istnienia systemów wersjonowania polega na tym, że starsze wersje plików można dowolnie przywracać. Usunięcie plików w najnowszym commicie nie spowoduje, że one magicznie znikną. Nadal tam będą, tylko przykryte kolejnymi warstwami.

Spokojnie, to tylko wersja deweloperska?

W niezabezpieczonym repozytorium znajdował się katalog wp-content, służący w WordPressie do przechowywania m.in. plików wtyczek czy motywów (a w tym wypadku także i baz danych) oraz README.md z instrukcjami dla deweloperów. Notatka ta sugerowała, że zawarta wewnątrz baza danych była stworzona do celów testowych.

„confing” zamiast „config” mnie trochę rani
Fragment pliku README.md.
„Jeżeli macie plik baza.sql w repozytorium, to możecie go sobie zaimportować do lokalnie postawionego projektu”

Analiza zrzutu danych wskazuje na co najmniej trzy argumenty przemawiające za tym, że jest to stara kopia zapasowa, na dodatek nieprzystosowana do rozwijania wtyczek i motywów WordPressa.

Po pierwsze, zrzut bazy pochodzi z 2020 roku. Czteroletnia baza danych zamieszczona razem ze współczesnymi wtyczkami, które to wymagają najnowszych wersji WordPressa, to bardzo kiepska mieszanka.

Aby odtworzyć to środowisko, musiałem pobrać archaiczną wersję WordPressa oraz starego XAMPP-a z przestarzałym PHP-em.

Zawarte w repozytorium wtyczki są wręcz za nowe, więc nie chcą ruszyć na przestarzałym PHP. Trzeba było doinstalować obok nowszego XAMPP-a, zmigrować stronę i uruchomić pluginy.

Stare…
i nowe (1929)

Oczywiście, po drodze nie obyło się bez ostrzeżeń i dodatkowych błędów. Po co więc trzymać starą bazę danych razem z kodem źródłowym, skoro jest tak przeszkadzająca w prawidłowym odtwarzaniu środowiska? Pomijam już fakt, że zamieszczenie bazy aktualnej również byłoby karygodne.

Po drugie, baza nie była gotowa, żeby od razu ją wgrać do środowiska testowego. Trzeba było samodzielnie pozmieniać niektóre ustawienia, aby WordPress nie przekierowywał w kółko na wersję produkcyjną.

Bez zmiany siteurl i home to nie ruszy

Po trzecie, w bazie można znaleźć skróty haseł użytkowników WordPressa. Nawet jeżeli oryginalne hasła były długie i losowe, to ich skróty zawarte w repozytorium kodu mogą umożliwić próbę ich odzyskania.

Na szczęście po odpytaniu API WordPressa produkcyjnej wersji strony można stwierdzić, że część kont użytkowników znajdujących się w starej kopii bazy już nie istnieje. Ogranicza to problem, ale go nie eliminuje, bo nadal kilka kont z wersji „testowej” znajduje się także w publicznej wersji witryny.

Trochę kapiszon, ale niesmak pozostał

Nie wyciekły ani dane wrażliwe, ani nic nadzwyczajnego – najbardziej wartościowe znalezisko to „zaledwie” kilka hashy do kont WordPressa. W razie gdyby ewentualny napastnik uzyskał dostęp do bazy i udałoby mu się „złamać” hashe, a hasła pozostały przez kilka lat niezmienione, mógłby uzyskać dostęp administracyjny do witryny. Na szczęście nic nie wskazuje na to, by do takiej sytuacji doszło.

Strona nie umożliwia także użytkownikom zostawiania komentarzy, więc w ujawnionej bazie nie znajdziemy adresów IP czy adresów e-mail użytkowników. Martwią jedynie nieudolne próby zabezpieczenia wystawionego folderu .git poprzez regułę blokującą nierekursywnie oraz „pusty” commit, który nie usuwał de facto niczego.

Wykrytą podatność zgłosiliśmy PKOl i tego samego dnia została ona usunięta.

Podsumowanie

Wdrożenia WordPress+Git są (z niezrozumiałego dla mnie powodu) dość często spotykaną sytuacją. Zwykłe zainstalowanie wtyczki DotGit pozwoliłoby uniknąć wtopy związanej z upublicznieniem katalogu repozytorium. Niestety, nie każdy na ten pomysł wpada i co chwilę można natrafić na publiczne .gity na popularnych stronach WWW. Dla komfortu psychicznego i większego bezpieczeństwa jestem za separowaniem WordPressa od systemów wersjonowania. Może i cierpi na tym wygoda, ale pozwala to uniknąć wpadki.

Powrót

Komentarze

  • avatar
    2025.02.07 14:09 t

    Wydaje mi się, że to „zabezpieczenie” o którym piszecie to standardowe zachowanie apache dla plików i katalogów których nazwa zaczyna się od kropki

    Odpowiedz
    • avatar
      2025.02.07 20:23 Antoni Mróz

      Albo źle coś robię, albo nie ma takiego standardowego zabezpieczenia. Machnąłem szybko w Dockerku kontener z obrazem httpd:latest i po prostu dostałem całego .gita. Może wersja Dockerowa tego ficzera nie ma, ale nie wydaje mi się. Jedyne zmiany jakie dołożyłem to załadowanie mod_info. Screeny tutaj: https://imgur.com/a/CGBo0K1.

      Odpowiedz

Zostaw odpowiedź

Jeśli chcesz zwrócić uwagę na literówkę lub inny błąd techniczny, zapraszamy do formularza kontaktowego. Reagujemy równie szybko.

Mały, ale ciekawy incydent w PKOl (i jak przez przypadek trafić na podobne)

Komentarze