首页 > 解决方案 > 如何解决设置 innerHTML 导致转义序列扩展的问题?

问题描述

我试图避免我的服务器上的跨站点脚本漏洞。在任何用户输入的字符串嵌入 HTML 或发送到客户端 JavaScript 代码之前,它会被转义('<' 替换为 '<','&' 替换为 '&' 等)嵌入 HTML 时,此工作正常;生成的 HTML 代码在用户提供的字符串中不包含任何 HTML 元素。但是,当客户端 javascript 将 HTML 插入文档时,转义序列会扩展回它们的特殊字符,这可能导致用户输入的标签出现在文档 HTML 中。这大约是我正在做的事情,javascript客户端:

// response_data received from XMLHttpRequest and parsed as JSON
var s = "";
for (var i = 0; i < response_data.length; ++i) {
    s += "<p>";
    s += response_data[i];
    s += "</p>";
}
console.log(s);
elem.innerHTML = s;

假设用户"abcde <script>alert("Hello!");</script>"之前输入了字符串。那么 response_data 可能是["abcde &lt;script&gt;alert(&quot;Hello!&quot;);&lt;/script&gt;"]. 到控制台的打印显示 s 是"<p>abcde &lt;script&gt;alert(&quot;Hello!&quot;);&lt;/script&gt;</p>"。但是,当我分配 elem.innerHTML 时,我可以在 Inspect Element 中看到元素的内部 HTML 实际上是<p>abcde <script>alert("Hello!");</script></p>!我不认为它执行了,可能是因为 p 标签中有关脚本标签的一些浏览器安全功能,但它显然不是很好。我该如何解决这个问题?

代码片段(在创建的文本上运行和检查元素,它在 p 标签内显示一个脚本标签):

var div_elem = document.querySelector("div");
div_elem.innerHTML = "<p>&lt;script&gt;alert(&quot;Hello!&quot;);&lt;/script&gt;</p>";
<html>
  <head></head>
  <body>
    <div></div>
  </body>
</html>

标签: javascripthtmlescaping

解决方案


使用innerText,它就像innerHTML但它被视为纯文本并且不会解码 HTML 实体。 编辑:

将 innerHTML 设置为 p 标签,然后在标签上使用 innerText 设置实际文本

elem.innerHTML = "<p></p>";
elem.childNodes[0].innerText = s;

推荐阅读