ASP.NET MVC XSS 防护
ASP.NET MVC XSS protection
根据OWASP XSS page,需要针对不同的上下文使用不同的XSS保护技术。但是,在 ASP.NET MVC Razor 视图中,我们只有 @
符号可以在 HTML 元素内部内容的上下文中转义数据。 HTML 属性、CSS、javascript 上下文和其他属性呢?
HTML 元素内容
这是安全的,并且会按预期工作:
<div>@data</data>
HTML元素属性
这是不安全的,可以被利用:
<div style="background: @color"></div>
JavaScript
虽然这不安全:
<script>
var value = @value;
</script>
安全的解决方案是:
<script>
var value = @Json.Encode(value);
</script>
CSS
这是不安全的,可以被利用:
<style>
.box { background : @color; }
</style>
razor 的一大优点是它默认执行所有 HTML 编码。除非您使用 @Html.Raw()
,否则很难使您的页面易受攻击。您通常必须显式地使变量呈现为 html。
你还有Html.Encode()
if you need it. There is also HttpUtility.JavaScriptStringEncode()
关于更新后的漏洞代码:
@{var js = "alert(1);";}
<script>var value = @js</script>
我认为您使用此代码会违反规则 0。您正在将任意字符串插入到脚本标记中,并期望它不会被执行。我实际上在你的例子中得到了一个语法错误(警告),但它仍然会 运行。如果你用引号把它包起来,你就安全了。
@{var js = "\"alert(1);";}
<script>var value = "@js"; alert(value);</script>
输出:
"alert(1);
请注意,我放入字符串中的引号被转义为 "
,使我无法跳出字符串,因此我无法注入 js。
我很想看看是否有人有办法在不把它放在引号中的情况下对其进行消毒,但我持怀疑态度。
更新 2:
处理 CSS
您提供的示例与转义字符串无关,更多的是关于将不受信任的 CSS 插入您的页面。为此,您需要可以解析 CSS 的东西。例如,并不是您希望对值进行编码,您只是希望它不包含危险的东西,例如 url(javascript:)、行为、绑定等。您需要CSS 过滤工具。
HTML 属性
如果你这样做你是安全的:
<div data-color="@color"></div>
由于 razor 对引号进行编码,您将无法提前终止字符串。这就像防止 XSS 一样简单(除非 razor 中存在一些未知的漏洞)。您的 Json.Encode()
使用相同的想法。
但是,如果你这样做,你是在做一些冒险的事情:
<div @attribute></div>
同样,这里并不是您需要转义字符串,您需要的是可以过滤任何危险内容的属性的东西。事实上,以这种方式做事真的很麻烦,我建议不要这样做。这是一个糟糕的设计,因为它搞砸了你的关注点分离,并使你的应用程序很难免受 XSS 攻击。如果您想更改样式,您应该做的是添加 CSS 类。如果您需要根据剃刀中的变量设置属性,请使用其他东西,而不是将其注入 HTML 并希望对其进行过滤。
例如:
@{
var disabled = isDivDisabled ? "disabled" : "";
}
<div @disabled><div>
根据OWASP XSS page,需要针对不同的上下文使用不同的XSS保护技术。但是,在 ASP.NET MVC Razor 视图中,我们只有 @
符号可以在 HTML 元素内部内容的上下文中转义数据。 HTML 属性、CSS、javascript 上下文和其他属性呢?
HTML 元素内容
这是安全的,并且会按预期工作:
<div>@data</data>
HTML元素属性
这是不安全的,可以被利用:
<div style="background: @color"></div>
JavaScript
虽然这不安全:
<script>
var value = @value;
</script>
安全的解决方案是:
<script>
var value = @Json.Encode(value);
</script>
CSS
这是不安全的,可以被利用:
<style>
.box { background : @color; }
</style>
razor 的一大优点是它默认执行所有 HTML 编码。除非您使用 @Html.Raw()
,否则很难使您的页面易受攻击。您通常必须显式地使变量呈现为 html。
你还有Html.Encode()
if you need it. There is also HttpUtility.JavaScriptStringEncode()
关于更新后的漏洞代码:
@{var js = "alert(1);";}
<script>var value = @js</script>
我认为您使用此代码会违反规则 0。您正在将任意字符串插入到脚本标记中,并期望它不会被执行。我实际上在你的例子中得到了一个语法错误(警告),但它仍然会 运行。如果你用引号把它包起来,你就安全了。
@{var js = "\"alert(1);";}
<script>var value = "@js"; alert(value);</script>
输出:
"alert(1);
请注意,我放入字符串中的引号被转义为 "
,使我无法跳出字符串,因此我无法注入 js。
我很想看看是否有人有办法在不把它放在引号中的情况下对其进行消毒,但我持怀疑态度。
更新 2:
处理 CSS您提供的示例与转义字符串无关,更多的是关于将不受信任的 CSS 插入您的页面。为此,您需要可以解析 CSS 的东西。例如,并不是您希望对值进行编码,您只是希望它不包含危险的东西,例如 url(javascript:)、行为、绑定等。您需要CSS 过滤工具。
HTML 属性如果你这样做你是安全的:
<div data-color="@color"></div>
由于 razor 对引号进行编码,您将无法提前终止字符串。这就像防止 XSS 一样简单(除非 razor 中存在一些未知的漏洞)。您的 Json.Encode()
使用相同的想法。
但是,如果你这样做,你是在做一些冒险的事情:
<div @attribute></div>
同样,这里并不是您需要转义字符串,您需要的是可以过滤任何危险内容的属性的东西。事实上,以这种方式做事真的很麻烦,我建议不要这样做。这是一个糟糕的设计,因为它搞砸了你的关注点分离,并使你的应用程序很难免受 XSS 攻击。如果您想更改样式,您应该做的是添加 CSS 类。如果您需要根据剃刀中的变量设置属性,请使用其他东西,而不是将其注入 HTML 并希望对其进行过滤。
例如:
@{
var disabled = isDivDisabled ? "disabled" : "";
}
<div @disabled><div>