可以使用"new DOMParser.parseFromString"吗?比"createElement"更安全? [英] Can a "new DOMParser.parseFromString" be safer than "createElement"?

查看:88
本文介绍了可以使用"new DOMParser.parseFromString"吗?比"createElement"更安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个脚本,尝试删除不安全的内容(我将其用于浏览器扩展):

I create a script for try remove insecure content (I'm using it for browser extensions):

var str = "<strong>Hello</strong> mundo <script src="http://site/badscript.js"></script>";
CreateDOM(str);

function RemoveAttrs(target)
{
    var attrs = target.attributes, currentAttr;
    var validAttrs = [ "href", "class", "id", "target" ];

    for (var i = attrs.length - 1; i >= 0; i--) {
        currentAttr = attrs[i].name;

        if (attrs[i].specified && validAttrs.indexOf(currentAttr) === -1) {
            target.removeAttribute(currentAttr);
        }

        if (
            currentAttr === "href" &&
            /^(#|javascript[:])/gi.test(target.getAttribute("href"))
        ) {
            target.parentNode.removeChild(currentAttr);
        }
    }
}

function RemoveEls(target)
{
    var current;

    //Remove elements insecure (blacklist)
    var list = target.querySelectorAll("script,link,...");

    for (var i = list.length - 1; i >= 0; i--) {
        current = list[i];
        current.parentNode.removeChild(current);
    }

    //Remove insecure attributes (whitelist)
    list = target.getElementsByTagName("*");

    for (i = list.length - 1; i >= 0; i--) {
        RemoveAttrs(list[i]);
    }

    return target;
}

function CreateDOM(MinhaString)
{
     var tmpDom = document.createElement("div");
     tmpDom.innerHTML = MinhaString;

     tmpDom = RemoveEls(tmpDom);

     //Inject in container
     document.getElementById("container").appendChild(tmpDom);
}

我在为Opera和Google Chorme创建的插件中使用了此脚本,但是网站主持人("addons.opera.com")对我说:

I'm using this script in an addon I created for opera and Google Chorme, however the site moderator ("addons.opera.com") said to me this:

您的cleanDomString方法不安全,请替换:tmpDom.innerHTML =数据;使用:var tmpDom =(新DOMParser).parseFromString(data,"text/html").body;

Your cleanDomString method is not safe, please replace: tmpDom.innerHTML = data; with: var tmpDom = (new DOMParser).parseFromString(data, "text/html").body;

并删除:var tmpDom = document.createElement("div");

and remove: var tmpDom = document.createElement("div");

或使用: https://github.com/operatester/safeResponse/blob/1.1/safeResponse.js

dmichnowicz;2016年5月30日,世界标准时间上午8:46:57

dmichnowicz; May 30, 2016 8:46:57 AM UTC

代码如下:

var str = "<strong>Hello</strong> mundo <script src="http://site/badscript.js"></script>";
CreateDOM(str);

function RemoveAttrs(target)
{
    var attrs = target.attributes, currentAttr;
    var validAttrs = [ "href", "class", "id", "target" ];

    for (var i = attrs.length - 1; i >= 0; i--) {
        currentAttr = attrs[i].name;

        if (attrs[i].specified && validAttrs.indexOf(currentAttr) === -1) {
            target.removeAttribute(currentAttr);
        }

        if (
            currentAttr === "href" &&
            /^(#|javascript[:])/gi.test(target.getAttribute("href"))
        ) {
            target.parentNode.removeChild(currentAttr);
        }
    }
}

function RemoveEls(target)
{
    var current;

    //Remove elements insecure (blacklist)
    var list = target.querySelectorAll("script,link,...");

    for (var i = list.length - 1; i >= 0; i--) {
        current = list[i];
        current.parentNode.removeChild(current);
    }

    //Remove insecure attributes (whitelist)
    list = target.getElementsByTagName("*");

    for (i = list.length - 1; i >= 0; i--) {
        RemoveAttrs(list[i]);
    }

    return target;
}

function CreateDOM(MyString)
{
     var tmpDom = (new DOMParser).parseFromString(MyString, "text/html").body;

     tmpDom = RemoveEls(tmpDom);

     //Inject in container
     document.getElementById("container").appendChild(tmpDom);
}

我进行了更改,但是我想了解它使我的代码更安全.对我来说,他们似乎都在做同一件事.

I made the change, but I would like to understand what it became safer my code. For me they both seem to do the same thing.

有什么区别(安全术语)?

What are the differences (terms of their safety)?

推荐答案

有效地,您当前的代码并不安全. innerHTML 不会在创建的< script> 元素中运行脚本,但是会运行事件处理程序内容属性.

Effectively, your current code is not safe. innerHTML doesn't run scripts in created <script> elements, but it does run event handler content attributes.

function createDOM(str) {
  document.createElement("div").innerHTML = str;
}
createDOM('<img src="//" onerror="console.log(\'You are pwned!\')" />');

function createDOM(str) {
  new DOMParser().parseFromString(str, "text/html");
}
createDOM('<img src="//" onerror="console.log(\'You are safe\')" />');

但是,请注意,如果您只想操作不受信任的HTML字符串中的DOM元素,则 DOMParser 可提供安全性.就像一个沙盒.但是,如果您将这些元素添加到当前文档中,则它们仍然可以运行JS.

However, note that DOMParser provides safety if you only want to manipulate the DOM elements from an untrusted HTML string. It's like a sandbox. But if then you get these elements and append it in the current document, they will still be able to run JS.

function createDOM(str) {
  document.body.appendChild(new DOMParser().parseFromString(str, "text/html").body);
}
createDOM('<img src="//" onerror="console.log(\'You are pwned!\')" />');

如果您确实需要这样的东西,我会使用一小段允许的元素和属性的白名单,并去除其他所有内容.

If you really need something like this, I would use a small whitelist of allowed elements and attributes, and get rid of everything else.

这篇关于可以使用"new DOMParser.parseFromString"吗?比"createElement"更安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆