La Content-Security-Policy
metaetiqueta le permite reducir el riesgo de ataques XSS al permitirle definir desde dónde se pueden cargar los recursos, evitando que los navegadores carguen datos desde cualquier otra ubicación. Esto dificulta que un atacante inyecte código malicioso en su sitio.
Me golpeé la cabeza contra una pared de ladrillos tratando de averiguar por qué estaba recibiendo errores de CSP uno tras otro, y no parecía haber instrucciones claras y concisas sobre cómo funciona. Así que aquí está mi intento de explicar brevemente algunos puntos de CSP, principalmente concentrándome en las cosas que encontré difíciles de resolver.
Por brevedad, no escribiré la etiqueta completa en cada muestra. En cambio, solo mostraré la content
propiedad, por lo que una muestra que dice content="default-src 'self'"
significa esto:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
1. ¿Cómo permitir múltiples fuentes?
Simplemente puede enumerar sus fuentes después de una directiva como una lista separada por espacios:
content="default-src 'self' https://example.com/js/"
Tenga en cuenta que no hay comillas alrededor de parámetros distintos de los especiales , como 'self'
. Además, no hay dos puntos ( :
) después de la directiva. Solo la directiva, luego una lista de parámetros separados por espacios.
Todo por debajo de los parámetros especificados está implícitamente permitido. Eso significa que en el ejemplo anterior, estas serían fuentes válidas:
https://example.com/js/file.js
https://example.com/js/subdir/anotherfile.js
Estos, sin embargo, no serían válidos:
http://example.com/js/file.js
^^^^ wrong protocol
https://example.com/file.js
^^ above the specified path
2. ¿Cómo usar diferentes directivas, qué hacen cada una?
Las directivas más comunes son:
default-src
La política predeterminada para cargar JavaScript, imágenes, CSS, fuentes, solicitudes AJAX, etc.
script-src
define fuentes válidas para archivos javascript
style-src
define fuentes válidas para archivos CSS
img-src
define fuentes válidas para imágenes
connect-src
define objetivos válidos para XMLHttpRequest (AJAX), WebSockets o EventSource. Si se realiza un intento de conexión a un host que no está permitido aquí, el navegador emulará un 400
error
Hay otros, pero estos son los que es más probable que necesites.
3. ¿Cómo usar múltiples directivas?
Defina todas sus directivas dentro de una metaetiqueta terminándolas con un punto y coma ( ;
):
content="default-src 'self' https://example.com/js/; style-src 'self'"
4. ¿Cómo manejar los puertos?
Todo menos los puertos predeterminados debe permitirse explícitamente agregando el número de puerto o un asterisco después del dominio permitido:
content="default-src 'self' https://ajax.googleapis.com http://example.com:123/free/stuff/"
Lo anterior resultaría en:
https://ajax.googleapis.com:123
^^^^ Not ok, wrong port
https://ajax.googleapis.com - OK
http://example.com/free/stuff/file.js
^^ Not ok, only the port 123 is allowed
http://example.com:123/free/stuff/file.js - OK
Como mencioné, también puede usar un asterisco para permitir explícitamente todos los puertos:
content="default-src example.com:*"
5. ¿Cómo manejar diferentes protocolos?
Por defecto, solo se permiten protocolos estándar. Por ejemplo, para permitir WebSockets ws://
, deberá permitirlo explícitamente:
content="default-src 'self'; connect-src ws:; style-src 'self'"
^^^ web sockets are now allowed on all domains and ports
6. ¿Cómo permitir el protocolo de archivo file://
?
Si intentas definirlo como tal, no funcionará. En cambio, lo permitirá con el filesystem
parámetro:
content="default-src filesystem"
7. ¿Cómo usar scripts en línea y definiciones de estilo?
A menos que se permita explícitamente, no puede usar definiciones de estilo en línea, código dentro de <script>
etiquetas o en propiedades de etiqueta como onclick
. Los permites así:
content="script-src 'unsafe-inline'; style-src 'unsafe-inline'"
También tendrá que permitir explícitamente imágenes codificadas en línea base64:
content="img-src data:"
8. ¿Cómo permitir eval()
?
Estoy seguro de que mucha gente diría que no, ya que 'eval es malvado' y la causa más probable del inminente fin del mundo. Esas personas estarían equivocadas. Claro, definitivamente puede perforar agujeros importantes en la seguridad de su sitio con eval, pero tiene casos de uso perfectamente válidos. Solo tienes que ser inteligente al usarlo. Lo permites así:
content="script-src 'unsafe-eval'"
9. ¿Qué 'self'
significa exactamente ?
Puede 'self'
significar localhost, sistema de archivos local o cualquier cosa en el mismo host. No significa ninguno de esos. Significa fuentes que tienen el mismo esquema (protocolo), el mismo host y el mismo puerto que el archivo en el que se define la política de contenido. ¿Sirve su sitio a través de HTTP? No hay https para usted, a menos que lo defina explícitamente.
Lo he usado 'self'
en la mayoría de los ejemplos, ya que generalmente tiene sentido incluirlo, pero de ninguna manera es obligatorio. Déjalo afuera si no lo necesitas.
¡Pero espera un minuto! ¿No puedo usarlo content="default-src *"
y terminar con eso?
No. Además de las vulnerabilidades de seguridad obvias, esto tampoco funcionará como cabría esperar. Aunque algunos documentos afirman que permite cualquier cosa, eso no es cierto. No permite inlining o evals, por lo que realmente, realmente hace que su sitio sea más vulnerable, usaría esto:
content="default-src * 'unsafe-inline' 'unsafe-eval'"
... pero confío en que no lo harás.
Otras lecturas:
http://content-security-policy.com
http://en.wikipedia.org/wiki/Content_Security_Policy