我正在研究一些遗留应用程序并且好奇这是否是一个可行的XSS漏洞?
码:
<div id="demo"></div>
<script>
document.getElementById("demo").innerHTML = '<script src="/me.js"></script>';
</script>
我不这么认为,但那里有比我聪明的人。这有变化吗?
这本身是无害的:
document.getElementById("demo").innerHTML = '<script src="/me.js"></script>';
HTML5指定不应执行使用innerHTML插入的标记。 1
然而(并且因为你问),可能有一个遥远的机会(诚然),这仍然可以被利用:
// This is the backdoor that an attacker has to inject somehow
Object.defineProperty(Element.prototype, 'innerHTML', {
set: function (value) {
const script = document.createElement('script');
script.textContent = `alert('gotcha! ${value}')`;
document.body.appendChild(script);
}
});
// This is what you're doing in your app
document.getElementById("demo").innerHTML = '<script src="/me.js"><\/script>';
<div id="demo"></div>
正如您所看到的,解析和提取URL并将脚本重新注入页面很容易。
如今,使用innerHTML
很可能会被劝阻。例:
警告:如果您的项目是经过任何形式的安全审核的项目,则使用innerHTML很可能会导致您的代码被拒绝。例如,如果您在浏览器扩展中使用innerHTML并将扩展名提交到addons.mozilla.org,则不会通过自动审核流程。 1
React有一种有趣的方式(恕我直言)阻止你使用它:
dangerouslySetInnerHTML是React在浏览器DOM中使用innerHTML的替代品。通常,从代码设置HTML是有风险的,因为很容易无意中将您的用户暴露给跨站点脚本(XSS)攻击。因此,您可以直接从React设置HTML,但是您必须键入dangerouslySetInnerHTML并使用__html键传递对象,以提醒自己这很危险。 2
最后,我认为值得一提的是epascarello和E. Sundin都有一个有效的观点。我们知道<script>
在通过innerHTML
注入时不会加载和/或执行,但这并不意味着你是安全的:
<div id="demo"></div>
<script>
document.querySelector('#demo').innerHTML =
'<img src="x.gif" onerror="alert(42)">';
</script>
参考