faradaysecBy faradaysec|September 11, 2025|7 Minutes

Content-Security Policy (CSP) y cómo (no) confiar ciegamente en ella

Introducción

El Content-Security Policy (CSP) es una de las defensas más efectivas contra vulnerabilidades del tipo Cross-Site Scripting (XSS) y ataques relacionados con la carga de recursos maliciosos. Se implementa a través de la cabecera HTTP ‘Content-Security-Policy’, y permite al navegador aplicar restricciones sobre qué scripts, estilos, imágenes u otros recursos pueden cargarse y ejecutarse en una aplicación web.

Sin embargo, como toda medida de seguridad, su efectividad depende de la correcta configuración. Una CSP mal planteada puede dar una falsa sensación de seguridad y ser fácilmente evadida por un atacante.

Fundamentos básicos de CSP

Una política CSP está compuesta por directivas, que definen qué orígenes están permitidos para distintos tipos de recursos.

Ejemplo de una política básica:

Content-Security-Policy: script-src 'self' https://csp.faradaysec.com

Esto indica al navegador que solo puede cargar JavaScript desde el mismo dominio (‘self’) o desde csp.faradaysec.com. Un payload malicioso como este quedará bloqueado:

<script src="https://attacker.com/pwn.js"></script>

Pero estos sí funcionarán:

<script src="/js/app.js"></script>
<script src="https://csp.faradaysec.com/main.js"></script>

Además, dado que el valor unsafe-inline no se especifica en la política, se bloquean todos los scripts inline. Por lo tanto, los siguientes posibles intentos de XSS quedarían bloqueados y no se ejecutarían.

<script>alert(1)</script>

<img src=x onerror=alert(1) />

<a href="javascript:alert(1)">click</a>

Otras directivas comunes que existen son:

– style-src: Orígenes permitidos para hojas de estilo.
– img-src: Orígenes permitidos para imágenes.
– object-src: Orígenes permitidos para <object> o <embed>.
– connect-src: Orígenes permitidos para peticiones HTTP desde scripts.
– frame-ancestors: Protege contra Clickjacking.
– form-action: Controla a dónde pueden enviarse formularios.

Donde puede tomar valores como:

– * → Todos los orígenes permitidos.
– ‘none’ → Ninguno permitido.
– ‘self’ → El mismo origen de la aplicación.
– unsafe-inline → Permitir scripts inline (inseguro).
– unsafe-eval → Permitir eval() (inseguro).
– nonce-abc123 → Permitir solo scripts con ese nonce.
– sha256-… → Permitir scripts específicos por hash.

CSP seguras

Una buena práctica es partir de una configuración estricta e ir ajustando, como esta que dejamos acá:

Content-Security-Policy: default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; frame-ancestors 'self'; form-action 'self';

Esto limita todos los recursos al mismo origen, bloqueando inline JS y evitando iframes externos.

A modo de referencias al momento de hacer un pentest o una auditoría de seguridad, existen herramientas en Internet que pueden ayudar a entender la implementación actual:

– Google CSP Evaluator (https://csp-evaluator.withgoogle.com)
– OWASP CSP Cheat Sheet (https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html)

Algunos bypasses comunes

Para terminar con esta primera introducción, dejamos algunos ejemplo prácticos que hemos visto a lo largo de auditorías de seguridad:

Uso de JSONP (ejemplo con Google)

Cuando una CSP whitelistea un dominio que expone endpoints JSONP, es posible generar ejecución de código a través del parámetro ‘callback‘:

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

Una explotación para esto podría ser:

NOTA: Este endpoint en particular ya no ejecuta el callback como lo hacía en el pasado, ya que muchos proveedores han descontinuado o mejorado las implementaciones con JSONP por los tantos riesgos que presenta. Para pruebas actuales, se recomienda revisar el proyecto JSONBee, que recopila endpoints que todavía aceptan callbacks JSONP y pueden ser útiles para simular bypasses de CSP en entornos de laboratorio.

 

File upload + ‘self’

Si la política permite script-src ‘self’ y la aplicación permite subir archivos, podríamos subir un archivo .js y cargarlo desde el mismo dominio:

<script src="/uploads/avatar.jpg.js"></script>

Unsafe-inline / unsafe-eval

Si la política incluye estas directivas, se habilitan directamente payloads inline:

<script>alert('XSS')</script>

Exceso de confianza en subdominios

Si un subdominio de csp.faradaysec.com es vulnerable, un potencial atacante podría cargar contenido JS malicioso desde allí.

Content-Security-Policy: script-src 'self' https://*.csp.faradaysec.com

Conclusión

CSP es una gran implementación de defensa que ayuda a contener ataques que quizás en el código del backend podría llegar a ser vulnerable, pero no debe considerarse una solución definitiva, sino más bien una capa extra de seguridad. Incluso, una política débil o mal configurada puede ser más peligrosa que no tener ninguna.

A modo de conclusión, dejamos algunas recomendaciones generales para tener en cuenta al momento de implementar CSP:

– Usar default-src ‘none’ y habilitar solo lo necesario.
– Evitar el uso de unsafe-inline y unsafe-eval.
– Al momento de usar una wildcard (*), entender los subdominios expuestos en el dominio base.
– Validar funcionalidades como subida de archivos o APIs JSONP.
– Usar herramientas automáticas de forma continua para monitorear la implementación de CSP.

 

 

Capacitaciones, gestión de vulnerabilidades, servicios de red teaming o escaneo continuo… lo que necesites, ¡estamos para ayudarte! 🚀⚡

Contactanos para más información.

Related Posts

Privacy Preference Center