
CakePHP 5.4.2 - Alto - Remoto - Proxy - trustedProxies honra X-Forwarded-* de qualquer REMOTE_ADDR
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cakephp-trusted-proxies
Análise: https://abraxaslabs.tech/research/cakephp-trusted-proxies
Classe: Bypass de redirecionamento HTTPS / falsificação de IP-host Alcance: Remoto
CakePHP 5.4.2 (887b641) - Cake Software Foundation
HttpsEnforcerMiddleware com trustedProxies => ['10.0.0.1'] chama setTrustedProxies, que define trustProxy = true e nunca compara a lista com REMOTE_ADDR. Depois disso, scheme(), host() e clientIp() passam a respeitar os cabeçalhos do atacante X-Forwarded-Proto / X-Forwarded-For / X-Forwarded-Host / X-Real-IP.
O middleware padrão tem trustedProxies nulo e não habilita isso. A configuração documentada de balanceador de carga é o caso exposto. Um cliente HTTP não autenticado que não é o proxy listado pode contornar o redirecionamento HTTPS e falsificar o IP do cliente e o Host.
| ID | ainda sem CVE |
| Classe | Bypass de redirecionamento HTTPS / falsificação de IP-host |
| Alcance | Remoto (HTTP não autenticado; app definiu trustedProxies) |
| CWE | CWE-441, CWE-346 |
| CVSS | Alto: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N |
| Produto | CakePHP |
| Afetado | 5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63) |
| Autenticação | nenhuma. App definiu trustedProxies em HttpsEnforcerMiddleware |
| Licença | GNU Affero GPL v3.0 |
| Laboratório | apenas 127.0.0.1 |
Requer um app que tenha habilitado trustedProxies (típico de enforce de HTTPS via proxy reverso). Não é necessário conectar a partir de um IP de proxy listado.
| Privilégio | Método / sink | Comprovado em laboratório ou inferido |
|---|---|---|
| Contornar redirecionamento HTTPS / caminho HSTS | GET / HTTP com X-Forwarded-Proto: https | Comprovado em laboratório. 200, scheme=https, testemunha no JSON |
Falsificar clientIp() | X-Forwarded-For: 203.0.113.50 | Comprovado em laboratório. client_ip=203.0.113.50 |
Falsificar host() | X-Forwarded-Host: spoof.invalid | Comprovado em laboratório. host=spoof.invalid |
Falsificar via X-Real-IP | X-Real-IP: 198.51.100.9 | Comprovado em laboratório. client_ip=198.51.100.9 |
Contornar ACL de IP / limite de taxa baseado em clientIp() | Mesma falsificação | Inferido. O padrão remote_addr do RateLimitMiddleware não é este bug |
| Controle negativo | Os mesmos cabeçalhos encaminhados em /control (sem trustedProxies) | Comprovado em laboratório. Ainda 301 para https |
Fechado sobre este resíduo: padrão trustedProxies => null; o próprio REMOTE_ADDR ainda é o IP da bridge do Docker no laboratório (192.168.208.1, não o 10.0.0.1 listado). Não é RCE. Não é um bug de cookie-jar.
Fixe a versão 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 chama isso sempre que trustedProxies não é nulo. Os IPs listados são posteriormente usados como um array_diff na cadeia XFF, não como uma verificação do peer que se conecta.
Caminhos errados já registrados: tratar o middleware padrão como este resquício (não é); chamar o x-forwarded-for do RateLimitMiddleware do mesmo bug (a bakery 5.4.1 já moveu esse padrão para remote_addr); alegar que o próprio REMOTE_ADDR foi falsificado. Teatro: um reverse shell.
python3 cakephp-trusted-proxies-Abraxas-Labs.py
ou
cd lab
./run.sh
Composer cakephp/cakephp 5.4.2 em PHP 8.3. App mínima: / usa trustedProxies => ['10.0.0.1']; /control não usa. HTTP em loopback em 127.0.0.1:19430.
/ sem cabeçalhos encaminhados -> 301 https./control com proto/for/host/real-ip -> 301 https./ com X-Forwarded-Proto: https -> 200, esquema https, trust_proxy=true, REMOTE_ADDR não é 10.0.0.1./ com XFF + Host -> client_ip=203.0.113.50, host=spoof.invalid./ com X-Real-IP -> 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
Só honrar cabeçalhos encaminhados quando REMOTE_ADDR estiver na lista de proxies confiáveis (Symfony isFromTrustedProxy()). Uma lista vazia não deve habilitar a confiança.
887b641de9f7aba06071f98f17edcbc573cbcf63)src/Http/ServerRequest.php · src/Http/Middleware/HttpsEnforcerMiddleware.phpGNU Affero GPL v3.0. Consulte LICENSE. Apenas laboratório em loopback. Sem garantias.