¿Es posible decirle a los navegadores que no ejecuten JavaScript desde partes específicas de un documento HTML?
Me gusta:
<div script="false"> ...
Podría ser útil como característica de seguridad adicional. Todos los scripts que quiero se cargan en una parte específica del documento. No debe haber secuencias de comandos en otras partes del documento y, si las hay, no deben ejecutarse.
javascript
html
script-tag
Seppo Erviälä
fuente
fuente
script-src:"self"
que permite que solo se ejecuten scripts de su dominio en la página. Si está interesado, lea este artículo de Mike West sobre CSP .</div>
para cerrar este elemento DOM y luego comenzar uno nuevo<div>
que será hermano de aquel en el que los scripts no se están ejecutando?Respuestas:
SÍ, puede :-) La respuesta es: Política de seguridad de contenido (CSP).
La mayoría de los navegadores modernos admiten esta bandera , que le dice al navegador que solo cargue código JavaScript desde un archivo externo confiable y no permita todo el código JavaScript interno. El único inconveniente es que no puede usar JavaScript en línea en toda su página (no solo para una
<div>
). Aunque podría haber una solución al incluir dinámicamente el div de un archivo externo con una política de seguridad diferente, no estoy seguro de eso.Pero si puede cambiar su sitio para cargar todo JavaScript desde archivos JavaScript externos, ¡puede deshabilitar JavaScript en línea junto con este encabezado!
Aquí hay un buen tutorial con un ejemplo: HTML5Rocks Tutorial
Si puede configurar el servidor para enviar esta bandera de encabezado HTTP, ¡el mundo será un lugar mejor!
fuente
Puede bloquear JavaScript cargado por
<script>
, usandobeforescriptexecute
event:<script> // Run this as early as possible, it isn't retroactive window.addEventListener('beforescriptexecute', function(e) { var el = e.target; while(el = el.parentElement) if(el.hasAttribute('data-no-js')) return e.preventDefault(); // Block script }, true); </script> <script>console.log('Allowed. Console is expected to show this');</script> <div data-no-js> <script>console.log('Blocked. Console is expected to NOT show this');</script> </div>
Tenga en cuenta que
beforescriptexecute
se definió en HTML 5.0 pero se ha eliminado en HTML 5.1. Firefox es el único navegador importante que lo implementó.En caso de que esté insertando un grupo de HTML que no es de confianza en su página, tenga en cuenta que bloquear scripts dentro de ese elemento no proporcionará más seguridad, porque el HTML que no es de confianza puede cerrar el elemento de espacio aislado y, por lo tanto, el script se colocará afuera y se ejecutará.
Y esto no bloqueará cosas como
<img onerror="javascript:alert('foo')" src="//" />
.fuente
beforescriptexecute
event. Funciona en Firefox.beforescriptexecute
parece que no es compatible y no será compatible con la mayoría de los principales navegadores. developer.mozilla.org/en-US/docs/Web/Events/beforescriptexecutePregunta interesante, no creo que sea posible. Pero incluso si lo es, parece que sería un truco.
Si el contenido de ese div no es de confianza, entonces debe escapar de los datos en el lado del servidor antes de que se envíen en la respuesta HTTP y se muestren en el navegador.
Si solo desea eliminar
<script>
etiquetas y permitir otras etiquetas html, simplemente elimínelas del contenido y deje el resto.Analice la prevención de XSS.
https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet
fuente
JavaScript se ejecuta "en línea", es decir, en el orden en que aparece en el DOM (si ese no fuera el caso, nunca podría estar seguro de que alguna variable definida en un script diferente estaba visible cuando la usaba por primera vez ).
Eso significa, en teoría, que podría tener un script al principio de la página (es decir, el primer
<script>
elemento) que mira a través del DOM y elimina todos los<script>
elementos y controladores de eventos dentro de su<div>
.Pero la realidad es más compleja: la carga de DOM y script ocurre de forma asincrónica. Esto significa que el navegador solo garantiza que un script pueda ver la parte del DOM que está antes (es decir, el encabezado hasta ahora en nuestro ejemplo). No hay garantías para nada más allá de (esto está relacionado con
document.write()
). Por lo tanto, es posible que vea la siguiente etiqueta de secuencia de comandos o tal vez no.Podría aferrarse al
onload
evento del documento, lo que aseguraría que obtenga todo el DOM, pero en ese momento, el código malicioso ya podría haberse ejecutado. Las cosas empeoran cuando otros scripts manipulan el DOM y los agregan allí. Por lo tanto, también tendría que verificar cada cambio del DOM.Así que la solución @cowls (filtrado en el servidor) es la única solución que puede funcionar en todas las situaciones.
fuente
Si está buscando mostrar código JavaScript en su navegador:
Usando JavaScript y HTML, tendrá que usar entidades HTML para mostrar el código JavaScript y evitar que este código se ejecute. Aquí puede encontrar la lista de entidades HTML:
Si está utilizando un lenguaje de secuencias de comandos del lado del servidor (PHP, ASP.NET, etc.), lo más probable es que haya una función que escaparía de una cadena y convertiría los caracteres especiales en entidades HTML. En PHP, usaría "htmlspecialchars ()" o "htmlentities ()". Este último cubre todos los caracteres HTML.
Si está buscando mostrar su código JavaScript de una manera agradable, pruebe uno de los resaltadores de código:
fuente
Tengo una teoría:
noscript
etiqueta.script
etiquetas dentro de lanoscript
etiqueta y luego desenvuelva su contenido.Ejemplo de prueba de concepto:
window.onload = function() { var noscripts = /* _live_ list */ document.getElementsByTagName("noscript"), memorydiv = document.createElement("div"), scripts = /* _live_ list */ memorydiv.getElementsByTagName("script"), i, j; for (i = noscripts.length - 1; i >= 0; --i) { memorydiv.innerHTML = noscripts[i].textContent || noscripts[i].innerText; for (j = scripts.length - 1; j >= 0; --j) { memorydiv.removeChild(scripts[j]); } while (memorydiv.firstChild) { noscripts[i].parentNode.insertBefore(memorydiv.firstChild, noscripts[i]); } noscripts[i].parentNode.removeChild(noscripts[i]); } };
body { font: medium/1.5 monospace; } p, h1 { margin: 0; }
<h1>Sample Content</h1> <p>1. This paragraph is embedded in HTML</p> <script>document.write('<p style="color: red;">2. This paragraph is generated by JavaScript</p>');</script> <p>3. This paragraph is embedded in HTML</p> <h1>Sample Content in No-JavaScript Zone</h1> <noscript> <p>1. This paragraph is embedded in HTML</p> <script>document.write('<p style="color: red;">2. This paragraph is generated by JavaScript</p>');</script> <p>3. This paragraph is embedded in HTML</p> </noscript> <noscript> <p>1. This paragraph is embedded in HTML</p> <script>document.write('<p style="color: red;">2. This paragraph is generated by JavaScript</p>');</script> <p>3. This paragraph is embedded in HTML</p> </noscript>
fuente
<noscript>
etiqueta y luego inyectar lo que les gusta.Si desea volver a habilitar las etiquetas de secuencia de comandos más adelante, mi solución fue romper el entorno del navegador para que cualquier secuencia de comandos que se ejecute arroje un error bastante pronto. Sin embargo, no es totalmente confiable, por lo que no puede usarlo como función de seguridad.
Si intenta acceder a las propiedades globales, Chrome generará una excepción.
setTimeout("Math.random()") // => VM116:25 Uncaught Error: JavaScript Execution Inhibited
Estoy sobrescribiendo todas las propiedades sobrescribibles
window
, pero también podría expandirlo para romper otras funciones.window.allowJSExecution = inhibitJavaScriptExecution(); function inhibitJavaScriptExecution(){ var windowProperties = {}; var Object = window.Object var console = window.console var Error = window.Error function getPropertyDescriptor(object, propertyName){ var descriptor = Object.getOwnPropertyDescriptor(object, propertyName); if (!descriptor) { return getPropertyDescriptor(Object.getPrototypeOf(object), propertyName); } return descriptor; } for (var propName in window){ try { windowProperties[propName] = getPropertyDescriptor(window, propName) Object.defineProperty(window, propName, { get: function(){ throw Error("JavaScript Execution Inhibited") }, set: function(){ throw Error("JavaScript Execution Inhibited") }, configurable: true }) } catch (err) {} } return function allowJSExecution(){ for (var propName in window){ if (!(propName in windowProperties)) { delete windowProperties[propName] } } for (var propName in windowProperties){ try { Object.defineProperty(window, propName, windowProperties[propName]) } catch (err) {} } } }
fuente