it-swarm.dev

Posso chiedere a un browser di non eseguire <script> s all'interno di un elemento?

È possibile dire ai browser di non eseguire JavaScript da parti specifiche di un documento HTML?

Piace:

<div script="false"> ...

Potrebbe essere utile come funzionalità di sicurezza aggiuntiva. Tutti gli script che voglio sono caricati in una parte specifica del documento. Non ci dovrebbero essere script in altre parti del documento e, se presenti, non dovrebbero essere eseguiti.

81
Seppo Erviälä

SÌ, puoi :-) La risposta è: Politica sulla sicurezza dei contenuti (CSP).

La maggior parte dei browser moderni supporta questo flag , che dice al browser di caricare solo il codice JavaScript da un file esterno attendibile e di impedire tutto il codice JavaScript interno! L'unico aspetto negativo è che non puoi utilizzare JavaScript incorporato in tutta la tua pagina (non solo per un singolo <div>). Anche se potrebbe esserci una soluzione alternativa includendo dinamicamente il div da un file esterno con una diversa politica di sicurezza, ma non ne sono sicuro.

Ma se puoi cambiare il tuo sito per caricare tutto JavaScript da file JavaScript esterni, puoi disabilitare JavaScript incorporato con questa intestazione!

Ecco un tutorial di Nizza con esempio: HTML5Rocks Tutorial

Se riesci a configurare il server per inviare questo flag di intestazione HTTP, il mondo sarà un posto migliore!

90
Falco

Puoi bloccare JavaScript caricato da <script>, Usando beforescriptexecute 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>

Si noti che beforescriptexecute è stato definito in HTML 5.0 ma è stato rimosso in HTML 5.1. Firefox è l'unico grande browser che lo ha implementato.

Nel caso in cui tu stia inserendo un gruppo non attendibile di HTML nella tua pagina, tieni presente che il blocco degli script all'interno di quell'elemento non fornirà maggiore sicurezza, perché l'HTML non attendibile può chiudere l'elemento sandbox, e quindi lo script verrà posizionato all'esterno ed eseguito.

E questo non bloccherà cose come <img onerror="javascript:alert('foo')" src="//" />.

13
Oriol

Domanda interessante, non credo sia possibile. Ma anche se lo è, sembra che sarebbe un trucco.

Se i contenuti di quel div non sono attendibili, è necessario evitare i dati sul lato server prima che vengano inviati nella risposta HTTP e resi nel browser.

Se desideri rimuovere solo <script> tag e consenti altri tag html, quindi rimuovili dal contenuto e lascia il resto.

Cerca nella prevenzione XSS.

https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet

8
cowls

JavaScript viene eseguito "inline", ovvero nell'ordine in cui appare nel DOM (in caso contrario, non si potrebbe mai essere sicuri che alcune variabili definite in uno script diverso fossero visibili quando lo si utilizzava per la prima volta ).

Ciò significa che in teoria potresti avere uno script all'inizio della pagina (ovvero il primo elemento <script>) Che controlla il DOM e rimuove tutti gli elementi <script> E i gestori di eventi all'interno del tuo <div>.

Ma la realtà è più complessa: il caricamento di DOM e script avviene in modo asincrono. Ciò significa che il browser garantisce solo che uno script può vedere la parte del DOM che è prima esso (cioè l'intestazione finora nel nostro esempio). Non ci sono garanzie per nulla oltre (questo è legato a document.write()). Quindi potresti vedere il prossimo tag di script o forse no.

Potresti aggrapparti all'evento onload del documento - che assicurerebbe di avere l'intero DOM - ma a quel tempo, il codice dannoso avrebbe già potuto essere eseguito. Le cose peggiorano quando altri script manipolano il DOM, aggiungendo script lì. Quindi dovresti controllare anche ogni modifica del DOM.

Quindi la soluzione @cowls (filtro sul server) è l'unica soluzione che può essere fatta funzionare in tutte le situazioni.

7
Aaron Digulla

Ho una teoria:

  • Avvolgi la parte specifica del documento all'interno di un tag noscript .
  • Utilizzare le funzioni DOM per eliminare tutti i tag script all'interno del tag noscript, quindi scartarne il contenuto.

Esempio di prova del concetto:

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>
1
Salman A

Se stai cercando di visualizzare il codice JavaScript nel tuo browser:

Utilizzando JavaScript e HTML, dovrai utilizzare entità HTML per visualizzare il codice JavaScript ed evitare che questo codice venga eseguito. Qui puoi trovare l'elenco delle entità HTML:

Se stai usando un linguaggio di scripting lato server (PHP, ASP.NET, ecc.), Molto probabilmente, c'è una funzione che sfuggirebbe a una stringa e convertire i caratteri speciali in entità HTML. In PHP, useresti "htmlspecialchars ()" o "htmlentities ()". Quest'ultimo copre tutti i caratteri HTML.

Se stai cercando di visualizzare il tuo codice JavaScript in modo piacevole, prova uno degli evidenziatori del codice:

1
Wissam El-Kik

Se si desidera riattivare i tag di script in un secondo momento, la mia soluzione era quella di rompere l'ambiente del browser in modo che qualsiasi script in esecuzione generasse un errore abbastanza presto. Tuttavia, non è totalmente affidabile, quindi non è possibile utilizzarlo come funzionalità di sicurezza.

Se provi ad accedere alle proprietà globali Chrome genererà un'eccezione.

setTimeout("Math.random()")
// => VM116:25 Uncaught Error: JavaScript Execution Inhibited  

Sto sovrascrivendo tutte le proprietà sovrascrivibili su window, ma potresti anche espanderlo per interrompere altre funzionalità.

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) {}
        }
    }
}
0
Matt Zeunert