【问题标题】:Security: innerHTML vs textContent with API安全性:innerHTML vs textContent 与 API
【发布时间】:2018-07-09 02:31:40
【问题描述】:

目前,我是否正在学习 API 以及如何将它们与动态网站一起使用。我编写了一些示例网站,从 API 获取数据。

我一直在使用innerHTML 将内容添加到我的页面。 我的老师在课堂上使用createElement textContentappendChild 将内容添加到他的页面。 当被问到时,他解释说 innerHTML 比 textContent 更不安全,例如如果 API 不可靠或被注入恶意代码,innerHTML 可以编辑整个 HTML,而不仅仅是带有 textContent 的内容。 ChaseMoskal 也尝试在此评论中解释 innerText vs innerHtml vs label vs text vs textContent vs outerText

我明白了基本的想法,但是,通过以下代码示例进行解释,我觉得两者都存在相同的安全问题。

var container = document.querySelector("#container");
var json1 = "Link to an image of my house";
var json2 = "Link to an image of my boat";
var jsonMaliciousCode = "maliciousCode3000"

// Create p element with innerHTML
container.innerHTML += "<a href=\""+maliciousCode+"\">" + json1 + "</a>";

// Create p element with textContent, href and appendChild
var innerExample = document.createElement('a');
innerExample.textContent = json2;
innerExample.href = maliciousCode;
container.appendChild(innerExample);

工作示例:https://jsfiddle.net/vh8hLhbj/4/

什么是我没有得到或错过的?

【问题讨论】:

  • 如果你要让用户设置元素的href,你可能至少要验证协议
  • 这不仅不安全,而且速度很慢并且会破坏你的 DOM。

标签: javascript html json security


【解决方案1】:

不同之处在于您的恶意代码的使用方式。 使用以下代码可能会显示出不同之处:

var container = document.querySelector("#container");
var json1 = "Link to an image of my house";
var json2 = "Link to an image of my boat";
var maliciousCode = "javascript:alert('test');\" xxx=\"maliciousCode3000\""

// Create p element with innerHTML
container.innerHTML += "<a href=\""+maliciousCode+"\">" + json1 + "</a>";

// Create p element with textContent, href and appendChild
var innerExample = document.createElement('a');
innerExample.textContent = json2;
innerExample.href = maliciousCode;
container.appendChild(innerExample);

这是小提琴:https://jsfiddle.net/vh8hLhbj/6/

您将看到第一个示例显示弹出窗口,而第二个示例没有。想象一下,如果是一些 javascript 访问 cookie,或者观看键盘输入。

【讨论】:

  • 很好的例子!我可以直观地看到存在差异,但是,从逻辑上讲,当我查看生成的 HTML 时,我感到很困惑。两个锚标记具有相同的 href 但行为不同。怎么会? &lt;a href="javascript:alert('test');" xxx="maliciousCode3000" "=""&gt;Link to an image of my house&lt;/a&gt;&lt;a href="javascript:alert('test');&amp;quot; xxx=&amp;quot;maliciousCode3000&amp;quot;"&gt;Link to an image of my boat&lt;/a&gt;
  • 他们没有相同的href,但是:第一个是:javascript:alert('test');第二个是:javascript:alert('test');&amp;quot; xxx=&amp;quot;maliciousCode3000&amp;quot;第二个不是正确的javascript,会抛出错误。
  • 我现在可以看到不同之处 - 使用检查器工具查看代码,两个锚点看起来相似。通过复制粘贴在这里,它显示了真正的区别。现在我只是想知道您是否可以指导我理解为什么 .href 将 \" 显示为 &quot ?那真的很有帮助!
  • 因为当你使用 .href 时,你基本上是在告诉浏览器:我放在那里的任何东西都会进入“href”属性。所以浏览器对变量中的所有文本进行编码以适应属性。在属性内安全地显示双引号的唯一方法是使用编码字符,即 "。您可以尝试其中的任何 html 代码,它将使用 & 版本进行编码。这实际上是您关于为什么这更安全的最初问题的答案:那里的任何代码都不会被解释,它会显示为纯文本。
  • 非常感谢!我现在尝试将恶意代码中的引号更改为 "但是,正如您所提到的,href 没有显示双引号?
【解决方案2】:

当您使用innerHTML 时,任何东西都可以在其中呈现,而您无法控制它。

检查以下示例。

var codeSnippet = "<div style='height:100px;width:100px;background-color:red' onclick='window.console.log(\"Anything!!!\");'><a href='#'>Click Here</a></div>";

document.getElementById('unsafe').innerHTML = codeSnippet;
document.getElementById('safe').textContent = codeSnippet;
<div id="unsafe">
</div>
<br>
<div id="safe">
</div>

【讨论】:

  • 在您的示例中,您以相同的方式使用 textContent 和 innerHTML,这不是有人使用 textContent 编写的方式,这使得您的答案难以理解。 (请参阅我的示例,因为两者都以适合功能的不同方式产生相同的内容)
猜你喜欢
  • 2014-08-17
  • 2013-04-07
  • 2014-02-14
  • 2020-11-10
  • 2013-08-25
  • 2012-09-05
  • 2016-01-28
  • 1970-01-01
相关资源
最近更新 更多