Могу ли я попросить браузер не запускать s в элементе?


можно ли сказать браузерам не запускать JavaScript из определенных частей HTML-документа?

Как:

<div script="false"> ...

Это может быть полезно в качестве дополнительной функции безопасности. Все сценарии, которые я хочу, загружаются в определенную часть документа. В других частях документа не должно быть скриптов, и если они есть, их не следует запускать.

7 80

7 ответов:

да, вы можете : -) ответ:Политика Безопасности Контента (CSP).

большинство современных браузеров поддерживают этот флаг, который говорит браузеру только загружать код JavaScript из доверенного внешнего файла и запретить весь внутренний код JavaScript! Единственным недостатком является то, что вы не можете использовать встроенный JavaScript на всей странице (не только для одного <div>). Хотя может быть обходной путь путем динамического включения div из внешний файл с другой политикой безопасности, но я не уверен.

но если вы можете изменить свой сайт, чтобы загрузить все JavaScript из внешних файлов JavaScript, то вы можете полностью отключить встроенный JavaScript с этим заголовком!

вот хороший учебник с примерами: HTML5Rocks Учебник

Если вы можете настроить сервер для отправки этого флага HTTP-заголовка, мир будет лучше!

вы можете заблокировать JavaScript, загруженный <script>, используя beforescriptexecute событие:

<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>

отметим, что beforescriptexecute был определен в HTML 5.0, но был удален в HTML 5.1. Firefox является единственным крупным браузером, который реализовал ее.

в случае, если вы вставляете ненадежную кучу HTML на своей странице, имейте в виду, что блокирование скриптов внутри этого элемента не обеспечит большей безопасности, потому что ненадежный HTML может закрыть изолированный элемент, и таким образом скрипт будет размещен снаружи и запущен.

и этого не будет блокировать такие вещи, как <img onerror="javascript:alert('foo')" src="//" />.

интересный вопрос, я не думаю, что это возможно. Но даже если это так, похоже, что это будет Хак.

если содержимое этого div ненадежно, то вам нужно экранировать данные на стороне сервера, прежде чем они будут отправлены в HTTP-ответе и отображены в браузере.

Если вы только хотите удалить <script> теги и разрешить другие теги html, а затем просто удалить их из содержимого и оставить остальное.

посмотрите в XSS профилактика.

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

JavaScript выполняется "inline", т. е. в том порядке, в котором он появляется в DOM (если это не так, вы никогда не могли быть уверены, что какая-то переменная, определенная в другом скрипте, была видна, когда вы использовали ее в первый раз).

так что теоретически у вас может быть скрипт в начале страницы (т. е. первый <script> элемент), который просматривает DOM и удаляет все <script> элементы и обработчики событий внутри вашего <div>.

но реальность сложнее: загрузка DOM и скрипта происходит асинхронно. Это означает, что браузер только гарантирует, что скрипт может видеть часть DOM, которая является до (т. е. заголовок до сих пор в нашем примере). Нет никаких гарантий для чего-либо за пределами (это связано с document.write()). Таким образом, вы можете увидеть следующий тег сценария или, может быть, нет.

вы можете защелкнуться на onload событие документа - что бы убедиться, что вы получили весь DOM-но на в то время вредоносный код уже мог быть выполнен. Все становится хуже, когда другие скрипты манипулируют DOM, добавляя туда скрипты. Поэтому вам также придется проверять каждое изменение DOM.

таким образом, решение @cowls (фильтрация на сервере) является единственным решением, которое может быть сделано для работы во всех ситуациях.

Если вы хотите отобразить код JavaScript в вашем браузере:

используя JavaScript и HTML, вам придется использовать HTML entities чтобы отобразить код JavaScript и избежать выполнения этого кода. Здесь вы можете найти список HTML-сущности:

Если вы используете серверные скриптовые языки (PHP, ASP.NET и т. д.), скорее всего, есть функция, которая будет экранировать строку и конвертировать специальные символы в HTML-объекты. В PHP вы бы использовали " htmlspecialchars ()"или" htmlentities ()". Последний охватывает все символы HTML.

Если вы хотите отобразить свой код JavaScript в хорошем виде, попробуйте один из кода маркеры:

у меня есть теория:

  • оберните определенную часть документа внутри noscript тег.
  • используйте функции DOM, чтобы отбросить все script теги внутри noscript тег затем разверните его содержимое.

доказательство концепции пример:

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>

Если вы хотите повторно включить теги сценариев позже, мое решение состояло в том, чтобы сломать среду браузера, чтобы любой скрипт, который запускается, выдавал ошибку довольно рано. Однако это не совсем надежно, поэтому вы не можете использовать его в качестве функции безопасности.

при попытке доступа к глобальным свойствам Chrome выдаст исключение.

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

Я перезаписываю все перезаписываемые свойства на window, но вы также можете расширить его, чтобы сломать другие функции.

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) {}
        }
    }
}