
CakePHP 5.4.2 - Alta - Remoto - Cookie - O cookie jar do Http Client corresponde a domínios como um sufixo de regex
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cakephp-cookie-suffix
Classe: Vazamento / plantio de cookie Alcance: Remoto
CakePHP 5.4.2 (887b641) - Cake Software Foundation
CookieCollection::findMatchingCookies usa preg_match('/' . preg_quote($domain) . '$/', $host). Isso é um sufixo de string, não o domain-match da RFC 6265. Um cookie para api.partner.com é enviado para evilapi.partner.com. Um cookie para bank.com é enviado para notbank.com.
Cookie::createFromHeaderString() também copia o Domain= do Set-Cookie sem verificação contra o host da resposta. addFromResponse de attacker.test com Domain=victim.internal armazena esse cookie e depois o anexa a victim.internal.
Um aplicativo que usa Cake\Http\Client com o jar padrão em mais de um host pode vazar um cookie de sessão de parceiro para um irmão com confusão de sufixo, ou plantar um cookie em um host interno após buscar uma URL do atacante. other.com não corresponde. Este não é um bug de cookie de navegador. O cakephp/app padrão não chama um segundo host por conta própria.
| ID | sem CVE ainda |
| Classe | Vazamento / plantio de cookie (domain match por sufixo de regex) |
| Alcance | Remoto (app usa o jar do Http Client entre hosts) |
| CWE | CWE-565, CWE-201 |
| CVSS | Alto: 8.2 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N |
| Produto | CakePHP |
| Afetado | 5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63) |
| Auth | app usa Cake\Http\Client com o cookie jar padrão entre hosts |
| Licença | GNU Affero GPL v3.0 |
| Lab | apenas 127.0.0.1 |
Precisa de uma aplicação que mantenha cookies do Cake\Http\Client em mais de um host (OAuth, webhooks, uma URL fornecida pelo usuário, uma segunda API).
| Privilégio | Método / sink | Comprovado em lab ou inferido |
|---|---|---|
| Vazar um cookie armazenado para um irmão com confusão de sufixo | CookieCollection::addToRequest para https://evilapi.partner.com/ após um cookie com domínio api.partner.com | Comprovado em lab. O Cookie da requisição é sid=SECRET. A RFC 6265 não corresponderia |
| Mesmo vazamento para um sufixo registrável | Domínio do cookie bank.com, host da requisição notbank.com | Comprovado em lab. O Cookie da requisição é sid=SECRET |
| Controle negativo | Host da requisição other.com | Comprovado em lab. Sem cabeçalho Cookie |
| Plantar um cookie para um host interno | addFromResponse de Set-Cookie: sid=x; Domain=victim.internal de https://attacker.test/ | Comprovado em lab. O domínio armazenado é victim.internal; a próxima requisição para esse host envia sid=x |
| Fixação de sessão / sessão de parceiro roubada na próxima chamada do Client | sid plantado ou vazado usado como sessão de API | Inferido. O lab para no oráculo do cabeçalho Cookie |
| Envio no mesmo host ainda funciona | Domínio do cookie api.partner.com para host api.partner.com | Comprovado em lab. Esperado, não é um bug |
Fechado sobre este resíduo: other.com não corresponde. Cookie jars de navegador não são este bug. Sem shell. Não é RCE não autenticado em um app esqueleto.
Fixe em cakephp/cakephp 5.4.2 após GHSA-2qh5, GHSA-fxf7, GHSA-vjqc e a nota filename= da 5.4.2. A correspondência de cookies do Http Client é um sufixo de regex:
$pattern = '/' . preg_quote($domain, '/') . '$/';
if (!preg_match($pattern, $host)) {
continue;
}
addFromResponse passa o host da requisição apenas como padrão. Um atributo Domain= do Set-Cookie o sobrescreve e é armazenado.
Caminhos errados já registrados: tratar isso como um bug de cookie de navegador; afirmar que other.com também corresponde; inflar um oráculo de cabeçalho Cookie para ATO sem um app que use o jar entre hosts. Teatro: um reverse shell.
python3 cakephp-cookie-suffix-Abraxas-Labs.py
ou
cd lab
./run.sh
Git clone da tag 5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63) em PHP 8.3. Oráculo HTTP em loopback em 127.0.0.1:19420. Nenhuma origem HTTP extra é necessária; o oráculo executa CookieCollection a partir do pin.
sid=SECRET domínio api.partner.com. addToRequest https://evilapi.partner.com/ -> Cookie: sid=SECRET.https://other.com/ -> sem cabeçalho Cookie.https://api.partner.com/ ainda envia sid=SECRET.bank.com -> https://notbank.com/ envia sid=SECRET.addFromResponse de https://attacker.test/ com Set-Cookie: sid=x; Domain=victim.internal; Path=/. Próximo https://victim.internal/ envia sid=x.SUCCESS cakephp-cookie-suffix suffix-leak=yes control-other=yes plant-domain=yes how=cakephp-5.4.2 CAKEPHP-COOKIE-SUFFIX-WITNESS
Domain-match da RFC 6265 (host === domain || str_ends_with($host, '.' . $domain)). Cookies host-only quando Domain é omitido. Rejeitar Domain que não faça domain-match com o host da requisição. Rejeitar sufixos públicos.
887b641de9f7aba06071f98f17edcbc573cbcf63)src/Http/Cookie/CookieCollection.php · src/Http/Cookie/Cookie.phpGNU Affero GPL v3.0. Veja LICENSE. Apenas lab em loopback. Sem garantia.