ASP.NET MVC - GET 请求上的 CSRF
ASP.NET MVC - CSRF on a GET request
我们有一个 ASP.NET MVC 应用程序。通过使用 @Html.AntiForgeryToken
和 ValidateAntiForgeryToken
属性,所有 POST 请求(表单提交)都已免受 CSRF 攻击。
控制器上的一种操作方法是 GET,它 returns 向用户报告(包含来自数据库的数据的 pdf 文件)。签名是:
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetReport()
{
// get data from db
return GetReport();
}
以下是我针对此操作测试 CSRF 所遵循的步骤:
- 用户登录应用程序
- 登录后,用户打开以下 HTML 文件并单击“提交”按钮:
- 报告已下载。
问题:
这可以被视为 CSRF 攻击吗?
如果是,如何缓解?由于操作方法是 GET 请求,我如何使用 MVC 的 CSRF 方法(在操作方法上应用 @Html.AntiForgeryToken
和 ValidateAntiForgeryToken
)。
HTML 文件:
<html>
<body>
<form action="https://<baseurl>/Analysis/GetReport">
<input type="submit" value="Submit request" />
</form>
</body>
</html>
简而言之,您刚才描述的是不是 XSRF 攻击的例子...
什么是 XSRF 攻击?
CSRF
和XSRF
都用来形容所谓的Cross Site Request Forgery
。这是恶意网站利用您在另一个网站上的身份验证状态来执行欺诈性跨站点请求的地方。
示例:网上银行。
银行
假设您 authenticated
在您银行的网站上,并且您的银行网站包含一个 form
来创建新交易,一切都非常简单...
<!-- Your bank -->
<form action="/send_moneh" method="POST">
<input type="text" name="amount" />
<input type="text" name="accountNumber" />
<input type="submit" value="Send Money" />
</form>
恶意网站
现在让我们想想您也正在访问的 Malicious website
,假设它还包含一个 form
,一个隐藏的并且其值是预先填充的...
<!-- Malicious website -->
<form action="http://yourbank.com/send_moneh" method="POST">
<input type="hidden" name="amount" value="100.00"/>
<input type="hidden" name="accountNumber" value="123456" />
</form>
提交恶意网站上的表单后,HTTP request
将直接从 您发送到您的银行 ,因为您已通过银行的身份验证网站,可以接受交易。
本质上,攻击者通过伪造请求并使用您作为传递该请求的信使来使用您自己的身份验证。
如何预防?
你使用了一个防伪令牌,这个token
是一个包含随机值的字符串,令牌放在你的cookies
,除了你的HTML表格。
当您收到请求时,您验证该表单是否包含防伪令牌并且它与存储在您的 cookie 中的令牌相匹配。恶意站点无法看到您的网站在客户端上设置的令牌,如果没有此信息,XSRF 攻击就会停止。
如何在 ASP.NET MVC 中实现它?
在将处理请求的控制器操作上,添加属性 [ValidateAntiForgeryToken]
,并在 HTML 表单中添加 (@Html.AntiForgeryToken())
.
public class ExampleController : Controller
{
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult Test(Foo fooModel)
{
// do your thing...
return this.View();
}
}
<form action="/Example/test" method="POST">
@Html.AntiForgeryToken()
<input type="text" name="bar" />
<input type="submit" value="Submit" />
</form>
就是这样!
Tips/Pointers/Advice
Anti-Forgery Tokens 在执行 GET
请求时没有多大意义,事实上,将它们放在您不修改和持久化数据的任何地方都没有意义,因为任何 GET 请求都将返回给您的用户,而不是攻击者。
如果您正在创建、更新或删除数据...请确保您正在使用它。
通常在浏览器中safe methods do not have to be protected against CSRF because they do not make changes to the application, and even if they're returning sensitive information this will be protected by the Same Origin Policy。
如果您的网站是按照标准实施的,您的 GET 请求应该是安全的,因此不需要保护。
但是,在特定情况下可能会执行“跨站点 DoS”* 攻击。假设您的报告页面需要 10 秒来执行,数据库服务器上的使用率为 100% CPU,网络服务器上的使用率为 80% CPU。
您网站的用户知道永远不要在办公时间访问 https://<baseurl>/Analysis/GetReport
,因为它会杀死服务器并给其他用户带来糟糕的用户体验。
但是,Chuck 想要关闭您的 <baseurl>
网站,因为他不喜欢您或您的公司。
在他经常发帖的繁忙论坛上,http://forum.walkertexasranger.example.com
,他将他的签名设置为:
<img src="https://yoursite.example.org/Analysis/GetReport" width=0 height=0 />
他还知道贵公司的员工经常访问论坛,同时也经常登录 yoursite.example.org
。
每次您的员工阅读 Chuck 的一篇帖子时,身份验证 cookie 都会发送到 https://yoursite.example.org/Analysis/GetReport
,因此您的网站会处理请求并生成报告,而您的系统会因为 CPU 而下线被这些不断的请求吃掉了。
因此,即使该请求是 GET 请求并且不会对您的系统进行任何永久性更改(又名“安全”),但实际上每次 运行 都会让您的系统崩溃。因此,最好用一些CSRF预防方法来保护它。最简单的方法是转换它,以便只能通过 POST 请求生成报告,因此可以通过 AntiForgeryToken 验证请求。
*XSDoS,即跨站拒绝服务,是我创造的一个短语,所以不要去谷歌搜索。
我们有一个 ASP.NET MVC 应用程序。通过使用 @Html.AntiForgeryToken
和 ValidateAntiForgeryToken
属性,所有 POST 请求(表单提交)都已免受 CSRF 攻击。
控制器上的一种操作方法是 GET,它 returns 向用户报告(包含来自数据库的数据的 pdf 文件)。签名是:
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetReport()
{
// get data from db
return GetReport();
}
以下是我针对此操作测试 CSRF 所遵循的步骤:
- 用户登录应用程序
- 登录后,用户打开以下 HTML 文件并单击“提交”按钮:
- 报告已下载。
问题:
这可以被视为 CSRF 攻击吗?
如果是,如何缓解?由于操作方法是 GET 请求,我如何使用 MVC 的 CSRF 方法(在操作方法上应用 @Html.AntiForgeryToken
和 ValidateAntiForgeryToken
)。
HTML 文件:
<html>
<body>
<form action="https://<baseurl>/Analysis/GetReport">
<input type="submit" value="Submit request" />
</form>
</body>
</html>
简而言之,您刚才描述的是不是 XSRF 攻击的例子...
什么是 XSRF 攻击?
CSRF
和XSRF
都用来形容所谓的Cross Site Request Forgery
。这是恶意网站利用您在另一个网站上的身份验证状态来执行欺诈性跨站点请求的地方。
示例:网上银行。
银行假设您 authenticated
在您银行的网站上,并且您的银行网站包含一个 form
来创建新交易,一切都非常简单...
<!-- Your bank -->
<form action="/send_moneh" method="POST">
<input type="text" name="amount" />
<input type="text" name="accountNumber" />
<input type="submit" value="Send Money" />
</form>
恶意网站
现在让我们想想您也正在访问的 Malicious website
,假设它还包含一个 form
,一个隐藏的并且其值是预先填充的...
<!-- Malicious website -->
<form action="http://yourbank.com/send_moneh" method="POST">
<input type="hidden" name="amount" value="100.00"/>
<input type="hidden" name="accountNumber" value="123456" />
</form>
提交恶意网站上的表单后,HTTP request
将直接从 您发送到您的银行 ,因为您已通过银行的身份验证网站,可以接受交易。
本质上,攻击者通过伪造请求并使用您作为传递该请求的信使来使用您自己的身份验证。
如何预防?
你使用了一个防伪令牌,这个token
是一个包含随机值的字符串,令牌放在你的cookies
,除了你的HTML表格。
当您收到请求时,您验证该表单是否包含防伪令牌并且它与存储在您的 cookie 中的令牌相匹配。恶意站点无法看到您的网站在客户端上设置的令牌,如果没有此信息,XSRF 攻击就会停止。
如何在 ASP.NET MVC 中实现它?
在将处理请求的控制器操作上,添加属性 [ValidateAntiForgeryToken]
,并在 HTML 表单中添加 (@Html.AntiForgeryToken())
.
public class ExampleController : Controller
{
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult Test(Foo fooModel)
{
// do your thing...
return this.View();
}
}
<form action="/Example/test" method="POST">
@Html.AntiForgeryToken()
<input type="text" name="bar" />
<input type="submit" value="Submit" />
</form>
就是这样!
Tips/Pointers/Advice
Anti-Forgery Tokens 在执行 GET
请求时没有多大意义,事实上,将它们放在您不修改和持久化数据的任何地方都没有意义,因为任何 GET 请求都将返回给您的用户,而不是攻击者。
如果您正在创建、更新或删除数据...请确保您正在使用它。
通常在浏览器中safe methods do not have to be protected against CSRF because they do not make changes to the application, and even if they're returning sensitive information this will be protected by the Same Origin Policy。
如果您的网站是按照标准实施的,您的 GET 请求应该是安全的,因此不需要保护。
但是,在特定情况下可能会执行“跨站点 DoS”* 攻击。假设您的报告页面需要 10 秒来执行,数据库服务器上的使用率为 100% CPU,网络服务器上的使用率为 80% CPU。
您网站的用户知道永远不要在办公时间访问 https://<baseurl>/Analysis/GetReport
,因为它会杀死服务器并给其他用户带来糟糕的用户体验。
但是,Chuck 想要关闭您的 <baseurl>
网站,因为他不喜欢您或您的公司。
在他经常发帖的繁忙论坛上,http://forum.walkertexasranger.example.com
,他将他的签名设置为:
<img src="https://yoursite.example.org/Analysis/GetReport" width=0 height=0 />
他还知道贵公司的员工经常访问论坛,同时也经常登录 yoursite.example.org
。
每次您的员工阅读 Chuck 的一篇帖子时,身份验证 cookie 都会发送到 https://yoursite.example.org/Analysis/GetReport
,因此您的网站会处理请求并生成报告,而您的系统会因为 CPU 而下线被这些不断的请求吃掉了。
因此,即使该请求是 GET 请求并且不会对您的系统进行任何永久性更改(又名“安全”),但实际上每次 运行 都会让您的系统崩溃。因此,最好用一些CSRF预防方法来保护它。最简单的方法是转换它,以便只能通过 POST 请求生成报告,因此可以通过 AntiForgeryToken 验证请求。
*XSDoS,即跨站拒绝服务,是我创造的一个短语,所以不要去谷歌搜索。