gpt4 book ai didi

javascript - XSS 预防和 .innerHTML

转载 作者:可可西里 更新时间:2023-11-01 02:51:56 26 4
gpt4 key购买 nike

当我允许用户将数据作为参数插入到 JS 中时 innerHTML像这样的功能:

element.innerHTML = “User provided variable”;

我明白为了防止 XSS,我必须对用户输入进行 HTML 编码,然后 JS 对用户输入进行编码,因为用户可以插入这样的内容:

<img src=a onerror='alert();'>

仅 HTML 或仅 JS 编码无济于事,因为 .innerHTML我所理解的方法在将输入插入页面之前对其进行解码。使用 HTML+JS 编码,我注意到 .innerHTML仅解码 JS,但保留 HTML 编码。

但是我能够通过双重编码到 HTML 来实现相同的目标。

我的问题是:有人可以提供一个示例,说明为什么我应该在使用 .innerHTML 时对 HTML 进行编码然后进行 JS 编码,而不是在 HTML 中进行双重编码。方法?

最佳答案

Could somebody provide an example of why I should HTML encode and thenJS encode, and not double encode in HTML when using the .innerHTMLmethod?


当然。
假设服务器在您的 JavaScript 中填充了“用户提供的数据”,那么您将必须对它进行 JS 编码才能获得它。
以下是服务器端的伪代码,但前端是 JavaScript:
var userProdividedData = "<%=serverVariableSetByUser %>";
element.innerHTML = userProdividedData;
像 ASP.NET <%= %>输出不编码的服务器端变量。如果用户“良好”并提供值 foo那么这会导致呈现以下 JavaScript:
var userProdividedData = "foo";
element.innerHTML = userProdividedData;
到目前为止没有问题。
现在假设恶意用户提供值 "; alert("xss attack!");// .这将呈现为:
var userProdividedData = ""; alert("xss attack!");//";
element.innerHTML = userProdividedData;
这将导致 XSS 漏洞利用,其中代码实际上在上面的第一行中执行。
为了防止这种情况,正如您所说,您进行了 JS 编码。 OWASP XSS prevention cheat sheet rule #3说:

Except for alphanumeric characters, escape all characters less than256 with the \xHH format to prevent switching out of the data valueinto the script context or into another attribute.


因此,为了防止这种情况,您的代码将是
var userProdividedData = "<%=JsEncode(serverVariableSetByUser) %>";
element.innerHTML = userProdividedData;
哪里 JsEncode按照 OWASP 建议进行编码。
这将防止上述攻击,因为它现在呈现如下:
var userProdividedData = "\x22\x3b\x20alert\x28\x22xss\x20attack\x21\x22\x29\x3b\x2f\x2f";
element.innerHTML = userProdividedData;
现在您已经针对 XSS 保护了您的 JavaScript 变量分配。
但是,如果恶意用户提供了 <img src="xx" onerror="alert('xss attack')" /> 怎么办?作为值(value)?这对于变量赋值部分很好,因为它会像上面一样简单地转换为等效的十六进制实体。
然而线
element.innerHTML = userProdividedData;
会导致 alert('xss attack')在浏览器呈现内部 HTML 时执行。这就像 DOM Based XSS攻击,因为它使用呈现的 JavaScript 而不是 HTML,然而,当它通过服务器时,它仍然被归类为反射型或存储型 XSS,具体取决于最初设置的值的位置。
这就是为什么您也需要进行 HTML 编码的原因。这可以通过一个函数来完成,例如:
function escapeHTML (unsafe_str) {
return unsafe_str
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/\"/g, '&quot;')
.replace(/\'/g, '&#39;')
.replace(/\//g, '&#x2F;')
}
制作你的代码
element.innerHTML = escapeHTML(userProdividedData);
或者可以通过 JQuery 的 text() 来完成功能。
关于评论中问题的更新

I just have one more question: You mentioned that we must JS encodebecause an attacker could enter "; alert("xss attack!");//. But if wewould use HTML encoding instead of JS encoding, wouldn't that alsoHTML encode the " sign and make this attack impossible because wewould have: var userProdividedData ="&quot;; alert(&quot;xss attack!&quot;);&#x2F;&#x2F;";


我认为您的问题意味着以下内容:与其先进行 JS 编码,然后再进行 HTML 编码,为什么我们不首先进行 HTML 编码,然后就这样呢?
好吧,因为他们可以编码诸如 <img src="xx" onerror="alert('xss attack')" /> 之类的攻击。全部使用 \xHH 编码格式以插入其有效负载 - 这将实现攻击所需的 HTML 序列,而无需使用 HTML 编码会影响的任何字符。
还有一些其他的攻击:如果攻击者输入了 \然后他们可以强制浏览器错过结束引号(因为 \ 是 JavaScript 中的转义字符)。
这将呈现为:
var userProdividedData = "\";
这会触发 JavaScript 错误,因为它不是一个正确终止的语句。如果应用程序在显眼位置呈现,这可能会导致应用程序拒绝服务。
另外说有两个用户控制的数据:
var userProdividedData = "<%=serverVariableSetByUser1 %>" + ' - ' + "<%=serverVariableSetByUser2 %>";
然后用户可以输入 \在第一和 ;alert('xss');//在第二。这会将字符串连接变成一个大任务,然后是 XSS 攻击:
var userProdividedData = "\" + ' - ' + ";alert('xss');//";
由于像这样的边缘情况,建议遵循 OWASP 指南,因为它们尽可能接近防弹。您可能认为添加 \到 HTML 编码值列表解决了这个问题,但是在以这种方式呈现内容时使用 JS 后跟 HTML 还有其他原因,因为此方法也适用于属性值中的数据:
<a href="javascript:void(0)" onclick="myFunction('<%=JsEncode(serverVariableSetByUser) %>'); return false">
不管是单引号还是双引号:
<a href='javascript:void(0)' onclick='myFunction("<%=JsEncode(serverVariableSetByUser) %>"); return false'>
甚至不加引号:
<a href=javascript:void(0) onclick=myFunction("<%=JsEncode(serverVariableSetByUser) %>");return false;>
如果您按照评论中提到的方式进行 HTML 编码,则为实体值: onclick='var userProdividedData ="&quot;;"' (缩短版)
代码实际上首先通过浏览器的 HTML 解析器运行,所以 userProdividedData将是
";;
代替
&quot;;
所以当你把它添加到 innerHTML调用你,你会再次遇到 XSS。请注意 <script>块不通过浏览器的 HTML 解析器处理,除了结束 </script>标签, but那是 another story .
如上所示,尽可能晚地编码总是明智的。然后,如果您需要在 JavaScript 上下文以外的任何内容中输出值(例如,实际的警报框不呈现 HTML,那么它仍将正确显示)。
也就是说,有了上面我可以调用
alert(serverVariableSetByUser);
就像设置 HTML 一样简单
element.innerHTML = escapeHTML(userProdividedData);
在这两种情况下,它都会正确显示,而不会中断输出或导致不良代码执行的某些字符。

关于javascript - XSS 预防和 .innerHTML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30661497/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com