使用DocumentFragment和innerHTML以富文本注释存储XSS预防

时间:2015-04-23 07:33:03

标签: javascript xss innerhtml richtext

我想知道是否有人能够确认这是否安全,因为我似乎无法在网上找到任何参考,也没有关于SO的其他问题,特别是处理这个"解决方案&# 34;到XSS。

我需要在页面中嵌入富文本评论。显然XSS的风险很高,所以我的计划是在DocumentFragment中对innerHTML进行临时DIV,然后使用预先定义的tagNames白名单和我认为安全的属性名称来递归树,删除任何不安全的。然后我可以将这个现在安全的HTML移动到我的真实文档中。

这是一种安全的方式吗?通过DocumentFragment执行此操作是否有任何方式可以触发XSS攻击?我希望它能够与真实文档隔离开来,从而避免用户事件触发,这可能会导致任何攻击。

1 个答案:

答案 0 :(得分:2)

我不建议您编写自己的反XSS库,因为恶意用户必然会知道您未考虑的漏洞。我建议使用第三方库,例如Google Caja HTML Sanitiser

查看了您的笔,如果var unsafe = '\u003Cimg src=1 onerror=alert(\u0027XSS_attack_in_progress\u0027)\u003E', //var unsafe = '<h3>Hello</h3><h4>World</h4>', whitelistTags = ['h1', 'h2', 'h3', 'b', 'i', 'em', 'strong', 'u'], testNode = document.getElementById('testNode'); makeSafeAndAddToDoc(unsafe, testNode); function makeSafeAndAddToDoc(unsafe, targetParent) { var safeDocFrag = document.createDocumentFragment(), containerDiv = safeDocFrag.appendChild(document.createElement("DIV")), nextChild; containerDiv.innerHTML = unsafe; while ((nextChild = containerDiv.firstChild)) { if (isSafe(nextChild)) { safeDocFrag.appendChild(containerDiv.firstChild); console.debug(safeDocFrag.children); } else { containerDiv.removeChild(nextChild); } } safeDocFrag.removeChild(containerDiv); targetParent.appendChild(safeDocFrag); } function isSafe(testNode) { var tag = testNode.tagName && testNode.tagName.toLowerCase(), isTextNode = testNode.nodeType === 3; if (!isTextNode && whitelistTags.indexOf(tag) === -1) { console.warn('Removing unsafe element: ', testNode.tagName); return false; } for (var i = 0; i < testNode.childNodes.length; i++) { if (!isSafe(testNode.childNodes[i])) { testNode.removeChild(testNode.childNodes[i]); i--; } } return true; }#testNode { min-width: 10px; min-height: 10px; border: 1px solid red; }代码被转义,您的代码仍然容易出错:

<div id="testNode"></div>
locator.all(by.css('.whatever'))
    .map(function(element){
        return {
            ele: element,
            name: element.getText()
        };
    })
    .then(function(elements){
         if (elements[x].name ==='sth') {
         //do something on elements[x].ele
         }
    });
Lang::get('messages.test', ['name' => 'Dayle'])