Agile is a medium machine from HackTheBox. It involves extracting Werkzeug debug console pin with the help of Directory traversal vulnerability, getting credentials from chrome remote debugging window, and exploiting CVE in sudoedit to modify the file used in a cron running as root.
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| 256 f4bcee21d71f1aa26572212d5ba6f700 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCeVL2Hl8/LXWurlu46JyqOyvUHtAwTrz1EYdY5dXVi9BfpPwsPTf+zzflV+CGdflQRNFKPDS8RJuiXQa40xs9o=
| 256 65c1480d88cbb975a02ca5e6377e5106 (ED25519)
80/tcp open http syn-ack nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://superpass.htb
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Port 80 (HTTP)
Opening the website redirects to
http://superpass.htb/ . Add it in hosts file and we get the following page. Its password manager website.
After registering a user and logging, we get access to vault where we can add credentials and export them.
Exporting the vault, it gets downloaded in a CSV format. In the proxy, looking at the request to the download endpoint, there’s a parameter in which the name of file in specified.
If we change the filename, we can see that there’s a file not found error. It also reveals the path that files are stored in /tmp directory. Since, this shows error means that debug mode is enabled.
Also, by traversing the directory back, we can read files from server.
Error produced by app reveals the application path. Now, we can download the source code of the application.
Looking in the
app.py , we can see that debug is enabled. Since, this a flask app, we can try to access the debug console. We can do so by clicking the little this little command line icon.
But, it is PIN protected
Werkzeug Debug Console PIN Exploit
Since, we have file read vulnerability, we can generate this PIN by leaking all the necessary info from the server. The following resource provides the steps to generate the PIN.
Werkzeug / Flask Debug
init__.py file on server e.g. to check how the PIN is generated, but better to leak source code through file traversal…
To generate the console PIN, we need the following info, which we can easily get via the file read vulnerability.
- Username of the user running the Flask application.
- Module name of the Flask application.
- Application name of the Flask application.
- Path to the Flask
- MAC address of the server
- Machine ID from
/etc/machine-id. On newer systems, combine the ID from
/etc/machine-idwith the last part of the value from
/proc/<pid>/cgroup, split on the
We can get the username by reading the environment variables using file read vulnerability.
The module name will be
flask.app and the application name can found in the source code.
The path to Flask app.py can be found in the error page.
For the mac address first we need to find device id by reading the
/proc/net/arp file on the server.
After that, we can get MAC address by reading the
Also need to convert the MAC address to decimal. It can done by following
python3 -c 'print(int("00:50:56:b9:50:10".replace(":",""), 16))'
Next, we need Machine ID, which can be extracted from
/etc/machine-id and combine it with the output of
/proc/self/cgroup after the last slash (/)
After gathering all the required info, our script to generate the PIN will look like following.
from itertools import chain
probably_public_bits = [
'flask.app',# mod name
'wsgi_app',# app name
'/app/venv/lib/python3.10/site-packages/flask/app.py' # flask app.py
private_bits = [
'345052368912',# MAC Address
'ed5b159560f54721827644bc9b220d00superpass.service'# machine id
#h = hashlib.md5() # Changed in https://werkzeug.palletsprojects.com/en/2.2.x/changes/#version-2-0-0
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if not bit:
if isinstance(bit, str):
bit = bit.encode('utf-8')
cookie_name = '__wzd' + h.hexdigest()[:20]
num = None
if num is None:
num = ('%09d' % int(h.hexdigest(), 16))[:9]
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
rv = num
Running the script, we get the PIN.
After providing the PIN on debug console, we get access to python console.
Now, we can easily get a reverse shell.
config_prod.json file in the
/app directory, we get the credentials for mysql db.
The passwords table in the superpass database contains the plain-text credentials.
Using the credentials in the last row, we can login via SSH as corum user.
Privilege Escalation (corum -> edwards)
Checking users, there are three more users on the server.
Running linpeas for enumeration, it would appear that there is a
--remote-debugging-port flag being used in the chrome browser. Essentially, it means that this port is open and running Chrome.
With credentials for SSH, we can port forward this and perhaps access it from our machine to see what the user is doing.
Opening the url in our browser the page is empty.
Searching on google following resource comes to help.
Chrome Remote Debugger Pentesting | Exploit Notes
Chrome Remote Debugger is a tool that debugs web applications.
Following the above resource, open the
chrome://inspect/#devices in the chrome browser.
In the remote target section, we can see the superpass. Clicking on the inspect, following window opens which contains credentials of
Using the credentials, we can login as edward user.
Privilege Escalation (edwards -> root)
Now checking sudo permissions of edward user, it appears that edward can run some commands as
However, these leads to dead end. Searching on google, it appears that there’s a recent CVE-2023–22809 in the sudoedit.
The version on the server is vulnerable to this CVE.
Using this CVE, i tried to edit sudoers file but it did not work.
Next, running PSPY, it appears that a cron is running as root to activate the virtual environment.
Checking the permissions on it, the dev_admin group has write permissions on it and also it is a bash script.
So, we can edit using the above CVE and place a reverse shell in it.
export EDITOR='vim -- /app/venv/bin/activate'
sudo -u dev_admin sudoedit /app/config_test.json
When the cron is executed, we get a reverse shell as root.
- Werkzeug PIN Exploit: https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/werkzeug#werkzeug-console-pin-exploit
- Chrome Remote Debugging: https://exploit-notes.hdks.org/exploit/linux/privilege-escalation/chrome-remote-debugger-pentesting/
- Sudoedit CVE: https://www.synacktiv.com/sites/default/files/2023-01/sudo-CVE-2023-22809.pdf