
CakePHP 5.4.2 - 高 - リモート - プロキシ - trustedProxies が任意の REMOTE_ADDR からの X-Forwarded-* を信頼する
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cakephp-trusted-proxies
解説記事: https://abraxaslabs.tech/research/cakephp-trusted-proxies
分類: HTTPS リダイレクトバイパス / IP・ホスト偽装 到達範囲: リモート
CakePHP 5.4.2 (887b641) - Cake Software Foundation
trustedProxies => ['10.0.0.1'] を指定した HttpsEnforcerMiddleware は setTrustedProxies を呼び出し、これが trustProxy = true を設定するものの、そのリストを REMOTE_ADDR と比較することは一切ない。その結果、scheme()、host()、clientIp() は攻撃者の X-Forwarded-Proto / X-Forwarded-For / X-Forwarded-Host / X-Real-IP を信用してしまう。
デフォルトのミドルウェアは trustedProxies が null であり、この問題は有効化されない。 ドキュメントに記載されたロードバランサ構成が、この脆弱性に晒されるケースである。リストに記載されたプロキシではない未認証の HTTP クライアントが、HTTPS リダイレクトを回避し、クライアント IP と Host を偽装できる。
| ID | CVE 未採番 |
| 分類 | HTTPS リダイレクトバイパス / IP・ホスト偽装 |
| 到達範囲 | リモート(未認証の HTTP。アプリが trustedProxies を設定している場合) |
| CWE | CWE-441, CWE-346 |
| CVSS | High: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N |
| 製品 | CakePHP |
| 影響を受けるバージョン | 5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63) |
| 認証 | 不要。アプリが HttpsEnforcerMiddleware の trustedProxies を設定している場合 |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1 のみ |
trustedProxies を有効化したアプリ(典型的なリバースプロキシでの HTTPS 強制)が必要である。リストに記載されたプロキシ IP から接続する必要はない。
| 権限 | メソッド / シンク | ラボで実証済みか推測か |
|---|---|---|
| HTTPS リダイレクト / HSTS パスを回避 | X-Forwarded-Proto: https を付けた HTTP の GET / | ラボで実証済み。200、scheme=https、JSON 内に証跡 |
clientIp() を偽装 | X-Forwarded-For: 203.0.113.50 | ラボで実証済み。client_ip=203.0.113.50 |
host() を偽装 | X-Forwarded-Host: spoof.invalid | ラボで実証済み。host=spoof.invalid |
X-Real-IP 経由で偽装 | X-Real-IP: 198.51.100.9 | ラボで実証済み。client_ip=198.51.100.9 |
clientIp() をキーとする IP ACL / レート制限をバイパス | 同じ偽装 | 推測。RateLimitMiddleware のデフォルト remote_addr はこのバグではない |
| ネガティブコントロール | /control(trustedProxies なし)で同じ転送ヘッダー | ラボで実証済み。依然として https へ 301 |
この残存点については結論済み: デフォルトは trustedProxies => null であり、ラボでは REMOTE_ADDR 自体が依然として Docker ブリッジ IP(192.168.208.1 であり、リストに記載された 10.0.0.1 ではない)。RCE ではない。クッキージャーのバグでもない。
cakephp/cakephp 5.4.2 を固定した。ServerRequest::setTrustedProxies():
public function setTrustedProxies(array $proxies): void
{
$this->trustedProxies = $proxies;
$this->trustProxy = true;
$this->uri = $this->uri->withScheme($this->scheme());
}
HttpsEnforcerMiddleware は trustedProxies が非 null のときは常にこれを呼び出します。リストされた IP は後で XFF チェーンに対する array_diff として使用され、接続元ピアのチェックとしては使われません。
すでに記録されている誤った解釈:デフォルトのミドルウェアをこの残存物とみなすこと(実際はそうではない);RateLimitMiddleware の x-forwarded-for を同じバグと呼ぶこと(5.4.1 の bakery はすでにそのデフォルトを remote_addr に移している);REMOTE_ADDR 自体がスプーフィングされたと主張すること。茶番:リバースシェル。
python3 cakephp-trusted-proxies-Abraxas-Labs.py
または
cd lab
./run.sh
Composer cakephp/cakephp 5.4.2 を PHP 8.3 で使用。小さなアプリ: / は trustedProxies => ['10.0.0.1'] を使用し、/control は使用しない。127.0.0.1:19430 でのループバック HTTP。
/ -> 301 https。/control -> 301 https。X-Forwarded-Proto: https 付きで GET / -> 200、スキーム https、trust_proxy=true、REMOTE_ADDR は 10.0.0.1 ではない。/ -> client_ip=203.0.113.50、host=spoof.invalid。X-Real-IP 付きで GET / -> client_ip=198.51.100.9。SUCCESS cakephp-trusted-proxies pin=5.4.2 how=app remote-addr=192.168.208.1 listed-proxy=10.0.0.1 proto-bypass=200 control-redirect=301 client-ip=203.0.113.50 host=spoof.invalid x-real-ip=198.51.100.9 CAKEPHP-TRUSTED-PROXIES-WITNESS
REMOTE_ADDR が信頼済みプロキシのリストに含まれている場合にのみ、転送ヘッダーを尊重します(Symfony の isFromTrustedProxy())。空のリストでは信頼を有効にしてはなりません。
887b641de9f7aba06071f98f17edcbc573cbcf63)src/Http/ServerRequest.php · src/Http/Middleware/HttpsEnforcerMiddleware.phpGNU Affero GPL v3.0。LICENSE を参照してください。ループバックラボ専用です。保証はありません。