XSS预防和.innerHTML [英] XSS prevention and .innerHTML

查看:200
本文介绍了XSS预防和.innerHTML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我允许用户将数据作为参数插入到JS innerHTML 函数时,如下所示:

When I allow users to insert data as an argument to the JS innerHTML function like this:

element.innerHTML = "User provided variable";

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

I understood that in order to prevent XSS, I have to HTML encode, and then JS encode the user input because the user could insert something like this:

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

只有HTML或只有JS编码无效,因为 .innerHTML 方法在将输入插入页面之前解码输入。使用HTML + JS编码,我注意到 .innerHTML 只解码JS,但HTML编码仍然存在。

Only HTML or only JS encoding would not help because the .innerHTML method as I understood decodes the input before inserting it into the page. With HTML+JS encoding, I noticed that the .innerHTML decodes only the JS, but the HTML encoding remains.

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

But I was able to achieve the same by double encoding into HTML.

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

My question is: Could somebody provide an example of why I should HTML encode and then JS encode, and not double encode in HTML when using the .innerHTML method?

推荐答案


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

Could somebody provide an example of why I should HTML encode and then JS encode, and not double encode in HTML when using the .innerHTML method?

当然。

假设服务器在您的JavaScript中填充了用户提供的数据那么你将不得不使用JS编码来实现它。

Assuming the "user provided data" is populated in your JavaScript by the server, then you will have to JS encode to get it there.

以下是服务器端的伪代码,但是在前端的JavaScript中:

This following is pseudocode on the server-side end, but in JavaScript on the front end:

var userProdividedData = "<%=serverVariableSetByUser %>";
element.innerHTML = userProdividedData;

与ASP.NET <%=%> 输出服务器端变量而不进行编码。如果用户好并提供值 foo ,则会导致呈现以下JavaScript:

Like ASP.NET <%= %> outputs the server side variable without encoding. If the user is "good" and supplies the value foo then this results in the following JavaScript being rendered:

var userProdividedData = "foo";
element.innerHTML = userProdividedData;

到目前为止没有问题。

现在假设恶意用户提供值; alert(xss attack!); // 。这将呈现为:

Now say a malicious user supplies the value "; alert("xss attack!");//. This would be rendered as:

var userProdividedData = ""; alert("xss attack!");//";
element.innerHTML = userProdividedData;

这将导致XSS漏洞利用,其中代码实际上是在上面的第一行中执行的。

which would result in an XSS exploit where the code is actually executed in the first line of the above.

为了防止这种情况,正如你所说的JS编码。 OWASP XSS预防备忘单规则#3 说:

To prevent this, as you say you JS encode. The OWASP XSS prevention cheat sheet rule #3 says:


除了字母数字字符外,使用\xHH格式转义所有小于
256的字符,以防止切换出数据值
进入脚本上下文或另一个属性。

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

所以为了防止这种情况,你的代码将是

So to secure against this your code would be

var userProdividedData = "<%=JsEncode(serverVariableSetByUser) %>";
element.innerHTML = userProdividedData;

其中 JsEncode 根据OWASP推荐进行编码。

where JsEncode encodes as per the OWASP recommendation.

这可以防止上述攻击,因为它现在呈现如下:

This would prevent the above attack as it would now render as follows:

var userProdividedData = "\x22\x3b\x20alert\x28\x22xss\x20attack\x21\x22\x29\x3b\x2f\x2f";
element.innerHTML = userProdividedData;

现在你已经针对XSS保护了你的JavaScript变量赋值。

Now you have secured your JavaScript variable assignment against XSS.

然而,如果恶意用户提供< img src =xxonerror =alert('xss attack')/> ,该怎么办?值?这对于变量赋值部分来说没问题,因为它只是转换成与上面相同的十六进制实体。

However, what if a malicious user supplied <img src="xx" onerror="alert('xss attack')" /> as the value? This would be fine for the variable assignment part as it would simply get converted into the hex entity equivalent like above.

然而行

element.innerHTML = userProdividedData;

会导致警告('xss attack')在浏览器呈现内部HTML时执行。这将是基于DOM的XSS 攻击。

would cause alert('xss attack') to be executed when the browser renders the inner HTML. This would be a DOM Based XSS attack.

这就是你需要HTML编码的原因。这可以通过以下函数完成:

This is why you would need to HTML encode too. This can be done via a function such as:

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() 功能。

or could be done via JQuery's text() function.


我还有一个问题:你提到我们必须JS编码
,因为攻击者可以输入; alert(xss attack!); // 。但是,如果我们
将使用HTML编码而不是JS编码,那么这也不会
HTML编码符号并使这次攻击无法进行,因为我们
将: var userProdividedData =& quot ;;警报(& quot; xss
attack!& quot;);&#x2F;&#x2F;;

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

我提出的问题意味着以下内容:为什么我们不首先只编写HTML编码,而是保留HTML编码。那个?

I'm taking your question to mean the following: Rather than JS encoding followed by HTML encoding, why don't we don't just HTML encode in the first place, and leave it at that?

好吧,因为他们可以编码攻击,例如< img src =xxonerror =alert('xss attack') )/> 所有使用 \ xHH 格式编码以插入其有效负载 - 这将实现所需的HTML攻击序列而不使用HTML编码会影响的任何字符。

Well because they could encode an attack such as <img src="xx" onerror="alert('xss attack')" /> all encoded using the \xHH format to insert their payload - this would achieve the desired HTML sequence of the attack without using any of the characters that HTML encoding would affect.

还有一些其他攻击:如果攻击者输入 \ 然后他们可以强制浏览器错过收盘报价(因为 \ 是JavaScript中的转义字符)。

There are some other attacks too: If the attacker entered \ then they could force the browser to miss the closing quote (as \ is the escape character in JavaScript).

这将呈现为:

var userProdividedData = "\";

哪个会触发JavaScript错误,因为它不是正确终止的语句。如果应用程序在显着位置呈现,这可能会导致拒绝服务。

which would trigger a JavaScript error because it is not a properly terminated statement. This could cause a Denial of Service to the application if it is rendered in a prominent place.

另外说有两个用户控制的数据:

Additionally say there were two pieces of user controlled data:

var userProdividedData = "<%=serverVariableSetByUser1 %>" + ' - ' + "<%=serverVariableSetByUser2 %>";

用户可以输入 \ in第一个和;警报('xss'); // 在第二个。这会将字符串连接更改为一个大的赋值,然后是XSS攻击:

the user could then enter \ in the first and ;alert('xss');// in the second. This would change the string concatenation into one big assignment, followed by an XSS attack:

var userProdividedData = "\" + ' - ' + ";alert('xss');//";

由于这些边缘情况,建议遵循OWASP指南,因为它们接近防弹你可以得到。您可能认为将 \ 添加到HTML编码值列表中可解决此问题,但是在以这种方式呈现内容时,还有其他原因使用JS后跟HTML,因为此方法也适用于属性值中的数据:

Because of edge cases like these it is recommended to follow the OWASP guidelines as they are as close to bulletproof as you can get. You might think that adding \ to the list of HTML encoded values solves this, however there are other reasons to use JS followed by HTML when rendering content in this manner because this method also works for data in attribute values:

<a href="javascript:void(0)" onclick="myFunction('<%=JsEncode(serverVariableSetByUser) %>'); return false">

尽管是单引号还是双引号:

Despite whether it is single or double quoted:

<a href='javascript:void(0)' onclick='myFunction("<%=JsEncode(serverVariableSetByUser) %>"); return false'>

甚至没有报价:

<a href=javascript:void(0) onclick=myFunction("<%=JsEncode(serverVariableSetByUser) %>");return false;>

如果您在评论中提到的HTML编码实体值:

If you HTML encoded like mentioned in your comment an entity value:

onclick ='var userProdividedData =& quot ;;'(缩短版)

代码实际上是先通过浏览器的HTML解析器运行,所以 userProdividedData 将是

the code is actually run via the browser's HTML parser first, so userProdividedData would be

";;

而不是

&quot;;

所以当你把它添加到 innerHTML 调用你会再次使用XSS。注意< script> 块不会通过浏览器的HTML解析器,除了结束< / script> 标记,但是那是另一个故事

so when you add it to the innerHTML call you would have XSS again. Note that <script> blocks are not processed via the browser's HTML parser, except for the closing </script> tag, but that's another story.

它始终是明智地编码为 late 尽可能如上所示。然后如果你需要在anythin中输出值g不是JavaScript上下文(例如一个实际的警告框不呈现HTML,然后它仍然会正确显示。)

It is always wise to encode as late as possible such as shown above. Then if you need to output the value in anything other than a JavaScript context (e.g. an actual alert box does not render HTML, then it will still display correctly).

也就是说,上面我可以调用

That is, with the above I can call

alert(serverVariableSetByUser);

和设置HTML一样简单

just as easily as setting HTML

element.innerHTML = escapeHTML(userProdividedData);

在这两种情况下,它都会正确显示而不会导致某些字符中断输出或导致不良代码执行。

In both cases it will be displayed correctly without certain characters from disrupting output or causing undesirable code execution.

这篇关于XSS预防和.innerHTML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆