使用jquery.append时如何防止XSS /注入?

时间:2019-03-22 22:18:25

标签: jquery append xss

我正在为我的网站上的用户制作一个javascript代码编辑器。我构建的功能之一是自定义控制台。 用户可以在其代码中编写console.log,并将记录的字符串添加到页面上的div上,如下所示:

  function toConsole(str) {
    var myconsole = document.getElementById("console-text");

    var message = document.createElement("span");
    message.append(str);

    myconsole.append(message);
}

str设置为用户输入到console.log中的任何字符串。附加此字符串可以在我的页面上运行恶意代码吗? (.append() jQuery api页面说“是”,但我似乎无法理解它来解释我用html编写的任何内容)

如果是这样,我如何防止这种情况发生,如何进行测试以确保其安全性?

3 个答案:

答案 0 :(得分:0)

您可以使用text()将内容作为textNode插入,这将导致该内容不是作为标记而是作为纯文本呈现在页面上。

var stringContainingHtmlAndJavascript = '<div><b>This will be bold</b></div>';

$(document.body).text(stringContainingHtmlAndJavascript);
$(document.body).append(stringContainingHtmlAndJavascript);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

答案 1 :(得分:0)

正如塔普拉(Taplar)所说,有不同的方法。 您还可以将HTML添加到临时标签中,然后提取文本。 请参阅我的第三个示例来做到这一点。

$(function() {
  var stringContainingHtmlAndJavascript = '<div><b>This will be bold</b></div>';

  $('.test1').append(stringContainingHtmlAndJavascript);
  $('.test2').text(stringContainingHtmlAndJavascript);
  $('.test3').text($('<i/>').append(stringContainingHtmlAndJavascript).text());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="test1"></div>
<div class="test2"></div>
<div class="test3"></div>

答案 2 :(得分:0)

我会建议您.parseHTML()使用 bemol ,如文档中所述。

正如方法名称所说,

.parseHTML()解析一个字符串来解释HTML。
第三个参数keepScripts默认为false ...将其设置为true将打开脚本的大门。

因此“通常会删除” 脚本标签。如果根本找不到HTML或文本,它将返回undefined(如演示案例3)。因此,您可能需要添加一个if条件,以避免附加文本“ undefined”

所以...在下面的演示中,我按原样使用了您发布的“脚本追加” ...我只是添加了HTML解析方法。

重要,情况#1至#4是安全的... 但是#5是违约行为。如果解析的HTML中有一个内联on [event]属性,它将通过“脚本过滤器” 并可以执行。

$(".console_ok").on("click",function(){
  toConsole( $(this).prev(".console_input").val() );
});

function toConsole(str) {

  str = $.parseHTML(str)[0];

  var myconsole = document.getElementById("console-text");
  var message = document.createElement("span");
  message.append(str);

  myconsole.append(message);
}
input{
  width: 60em;
}
#console-text{
  height:8em;
  width:20em;
  background-color: #bbb;
  border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

console.log test #1:<input class="console_input" value="Just text">
<button class="console_ok">OK</button><br>
<br>
console.log test #2:<input class="console_input" value="<h1>Some HTML</h1>">
<button class="console_ok">OK</button><br>
<br>
console.log test #3:<input class="console_input" value="<script>alert('A script!!!');</script>">
<button class="console_ok">OK</button><br>
<br>
console.log test #4:<input class="console_input" value="<div style='height:20px;background-color:red;'><script>alert('A script!!!');</script>And some <b>bold</b> text...</div>">
<button class="console_ok">OK</button><br>
<br>
console.log test #5:<input class="console_input" value="<img src='invalid-path' onerror='alert(`JS EXECUTES HERE!!!`);'>">
<button class="console_ok">OK</button><br>
<br>

My console:<br>
<div id="console-text"></div>

(请以全页模式运行)
CodePen

您会注意到[0]之后的$.parseHTML(str) ...这是从jQuery对象中获取DOM元素,因为您的函数是纯JS。您的函数也可以这样写(做完全相同的事情)

function toConsole(str) {

  str = $.parseHTML(str);

  var myconsole = $("#console-text");
  var message = $("<span>");
  message.append(str);

  myconsole.append(message);
}