
CakePHP 5.4.2 - Élevé - À distance - Proxy - trustedProxies honore X-Forwarded-* depuis n'importe quel REMOTE_ADDR
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cakephp-trusted-proxies
Write-up : https://abraxaslabs.tech/research/cakephp-trusted-proxies
Classe : contournement de redirection HTTPS / usurpation IP-hôte Portée : distante
CakePHP 5.4.2 (887b641) - Cake Software Foundation
HttpsEnforcerMiddleware avec trustedProxies => ['10.0.0.1'] appelle setTrustedProxies, qui définit trustProxy = true et ne compare jamais la liste à REMOTE_ADDR. Ensuite, scheme(), host() et clientIp() honorent les en-têtes de l'attaquant X-Forwarded-Proto / X-Forwarded-For / X-Forwarded-Host / X-Real-IP.
Le middleware par défaut a trustedProxies à null et n'active pas ce comportement. La configuration documentée pour les répartiteurs de charge est le cas exposé. Un client HTTP non authentifié qui n'est pas le proxy listé peut contourner la redirection HTTPS et usurper l'IP du client et l'en-tête Host.
| ID | pas encore de CVE |
| Classe | contournement de redirection HTTPS / usurpation IP-hôte |
| Portée | distante (HTTP non authentifié ; application avec trustedProxies défini) |
| CWE | CWE-441, CWE-346 |
| CVSS | Élevé : 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N |
| Produit | CakePHP |
| Affecté | 5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63) |
| Auth | aucune. Application avec HttpsEnforcerMiddleware trustedProxies défini |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
Nécessite une application ayant activé trustedProxies (application typique de renforcement HTTPS derrière un reverse-proxy). Pas besoin de se connecter depuis une IP de proxy listée.
| Privilège | Méthode / sink | Prouvé en lab ou déduit |
|---|---|---|
| Contourner la redirection HTTPS / le chemin HSTS | GET / HTTP avec X-Forwarded-Proto: https | Prouvé en lab. 200, scheme=https, témoin dans le JSON |
Usurper clientIp() | X-Forwarded-For: 203.0.113.50 | Prouvé en lab. client_ip=203.0.113.50 |
Usurper host() | X-Forwarded-Host: spoof.invalid | Prouvé en lab. host=spoof.invalid |
Usurper via X-Real-IP | X-Real-IP: 198.51.100.9 | Prouvé en lab. client_ip=198.51.100.9 |
Contourner une ACL IP / limitation de débit basée sur clientIp() | Même usurpation | Déduit. La valeur par défaut remote_addr de RateLimitMiddleware n'est pas concernée par ce bug |
| Contrôle négatif | Mêmes en-têtes forwarded sur /control (sans trustedProxies) | Prouvé en lab. Toujours 301 vers https |
Clos sur ce point restant : trustedProxies => null par défaut ; REMOTE_ADDR lui-même reste l'IP du bridge Docker dans le lab (192.168.208.1, et non le 10.0.0.1 listé). Pas de RCE. Pas un bug de cookie-jar.
J'ai épinglé 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 l'appelle chaque fois que trustedProxies est non nul. Les IP listées sont ensuite utilisées comme un array_diff sur la chaîne XFF, et non comme une vérification du pair connecté.
Fausses pistes déjà consignées : traiter le middleware par défaut comme ce reliquat (ce n'est pas le cas) ; qualifier le x-forwarded-for de RateLimitMiddleware du même bug (la bakery 5.4.1 a déjà déplacé cette valeur par défaut vers remote_addr) ; prétendre que REMOTE_ADDR lui-même était usurpé. Théâtre : un reverse shell.
python3 cakephp-trusted-proxies-Abraxas-Labs.py
ou
cd lab
./run.sh
Composer cakephp/cakephp 5.4.2 dans PHP 8.3. Petite application : / utilise trustedProxies => ['10.0.0.1'] ; /control ne l'utilise pas. HTTP en boucle locale sur 127.0.0.1:19430.
/ sans en-têtes de transfert -> 301 https./control avec proto/for/host/real-ip -> 301 https./ avec X-Forwarded-Proto: https -> 200, schéma https, trust_proxy=true, REMOTE_ADDR n'est pas 10.0.0.1./ avec XFF + Host -> client_ip=203.0.113.50, host=spoof.invalid./ avec 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
Ne prendre en compte les en-têtes transférés que lorsque REMOTE_ADDR figure dans la liste des proxys de confiance (Symfony isFromTrustedProxy()). Une liste vide ne doit pas activer la confiance.
887b641de9f7aba06071f98f17edcbc573cbcf63)src/Http/ServerRequest.php · src/Http/Middleware/HttpsEnforcerMiddleware.phpGNU Affero GPL v3.0. Voir LICENSE. Laboratoire en boucle locale uniquement. Aucune garantie.