
CakePHP 5.4.2 - Élevé - À distance - Cookie - Le cookie jar du client HTTP fait correspondre les domaines comme un suffixe d'expression régulière
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cakephp-cookie-suffix
Classe : Fuite / plantation de cookie Portée : Distante
CakePHP 5.4.2 (887b641) - Cake Software Foundation
CookieCollection::findMatchingCookies utilise preg_match('/' . preg_quote($domain) . '$/', $host). Il s'agit d'un suffixe de chaîne, et non d'une correspondance de domaine RFC 6265. Un cookie pour api.partner.com est envoyé à evilapi.partner.com. Un cookie pour bank.com est envoyé à notbank.com.
Cookie::createFromHeaderString() copie également le Domain= de Set-Cookie sans vérification par rapport à l'hôte de la réponse. addFromResponse depuis attacker.test avec Domain=victim.internal stocke ce cookie et l'attache ensuite à victim.internal.
Une application qui utilise Cake\Http\Client avec le jar par défaut sur plusieurs hôtes peut divulguer un cookie de session partenaire à un voisin confondu par suffixe, ou planter un cookie sur un hôte interne après avoir récupéré une URL attaquante. other.com ne correspond pas. Ce n'est pas un bug de cookie de navigateur. Le cakephp/app standard n'appelle pas un second hôte de lui-même.
| ID | pas encore de CVE |
| Classe | Fuite / plantation de cookie (correspondance de domaine par suffixe regex) |
| Portée | Distante (l'application utilise le jar Http Client sur plusieurs hôtes) |
| CWE | CWE-565, CWE-201 |
| CVSS | Élevé : 8.2 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N |
| Produit | CakePHP |
| Affecté | 5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63) |
| Auth | l'application utilise Cake\Http\Client avec le jar de cookies par défaut sur plusieurs hôtes |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
Nécessite une application qui conserve les cookies de Cake\Http\Client sur plus d'un hôte (OAuth, webhooks, une URL fournie par l'utilisateur, une seconde API).
| Privilège | Méthode / sink | Prouvé en lab ou déduit |
|---|---|---|
| Divulguer un cookie stocké à un voisin confondu par suffixe | CookieCollection::addToRequest pour https://evilapi.partner.com/ après un cookie de domaine api.partner.com | Prouvé en lab. Le Cookie de la requête est sid=SECRET. RFC 6265 ne correspondrait pas |
| Même fuite pour un suffixe enregistrable | Domaine du cookie bank.com, hôte de la requête notbank.com | Prouvé en lab. Le Cookie de la requête est sid=SECRET |
| Contrôle négatif | Hôte de la requête other.com | Prouvé en lab. Aucun en-tête Cookie |
| Planter un cookie pour un hôte interne | addFromResponse de Set-Cookie: sid=x; Domain=victim.internal depuis https://attacker.test/ | Prouvé en lab. Le domaine stocké est victim.internal ; la requête suivante vers cet hôte envoie sid=x |
| Fixation de session / session partenaire volée lors du prochain appel Client | sid planté ou divulgué utilisé comme session API | Déduit. Le lab s'arrête à l'oracle d'en-tête Cookie |
| L'envoi vers le même hôte fonctionne toujours | Domaine du cookie api.partner.com vers l'hôte api.partner.com | Prouvé en lab. Attendu, pas un bug |
Fermé sur ce reste : other.com ne correspond pas. Les jars de cookies de navigateur ne sont pas ce bug. Pas de shell. Pas de RCE non authentifiée sur une application squelette.
J'ai épinglé cakephp/cakephp 5.4.2 après GHSA-2qh5, GHSA-fxf7, GHSA-vjqc, et la note filename= de la 5.4.2. La correspondance des cookies de Http Client est un suffixe regex :
$pattern = '/' . preg_quote($domain, '/') . '$/';
if (!preg_match($pattern, $host)) {
continue;
}
addFromResponse ne passe l'hôte de la requête que comme valeur par défaut. Un attribut Domain= provenant de Set-Cookie l'écrase et est stocké.
Fausses pistes déjà consignées : traiter cela comme un bug de cookie de navigateur ; prétendre que other.com correspond aussi ; gonfler un oracle d'en-tête Cookie en ATO sans une application qui utilise le jar sur plusieurs hôtes. Théâtre : un reverse shell.
python3 cakephp-cookie-suffix-Abraxas-Labs.py
ou
cd lab
./run.sh
Git clone du tag 5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63) en PHP 8.3. Oracle HTTP en boucle locale sur 127.0.0.1:19420. Aucune origine HTTP supplémentaire n'est requise ; l'oracle exécute CookieCollection depuis le pin.
sid=SECRET domaine api.partner.com. addToRequest https://evilapi.partner.com/ -> Cookie: sid=SECRET.https://other.com/ -> aucun en-tête Cookie.https://api.partner.com/ envoie toujours sid=SECRET.bank.com -> https://notbank.com/ envoie sid=SECRET.addFromResponse depuis https://attacker.test/ avec Set-Cookie: sid=x; Domain=victim.internal; Path=/. La requête suivante https://victim.internal/ envoie sid=x.SUCCESS cakephp-cookie-suffix suffix-leak=yes control-other=yes plant-domain=yes how=cakephp-5.4.2 CAKEPHP-COOKIE-SUFFIX-WITNESS
Correspondance de domaine RFC 6265 (host === domain || str_ends_with($host, '.' . $domain)). Cookies host-only lorsque Domain est omis. Rejeter un Domain qui ne correspond pas au domaine de l'hôte de la requête. Rejeter les suffixes publics.
887b641de9f7aba06071f98f17edcbc573cbcf63)src/Http/Cookie/CookieCollection.php · src/Http/Cookie/Cookie.phpGNU Affero GPL v3.0. Voir LICENSE. Lab en boucle locale uniquement. Aucune garantie.