什麼是跨站請求僞造(XSRF/CSRF)
在繼續之前如果不給你講一下什麼是跨站請求僞造(XSRF/CSRF)的話可能你會很懵逼,我爲什麼要了解這個,不處理又有什麼問題呢?
CSRF(Cross-site request forgery跨站請求僞造,也被稱爲“One Click Attack”或者Session Riding,通常縮寫爲CSRF或者XSRF,是一種對網站的惡意利用。儘管聽起來像跨站腳本(XSS),但它與XSS非常不同,並且攻擊方式幾乎相左。XSS利用站點內的信任用戶,而CSRF則通過僞裝來自受信任用戶的請求來利用受信任的網站。與XSS攻擊相比,CSRF攻擊往往不大流行(因此對其進行防範的資源也相當稀少)和難以防範,所以被認爲比XSS更具危險性。
CSRF在 2007 年的時候曾被列爲互聯網 20 大安全隱患之一。其他安全隱患,比如 SQL 腳本注入,跨站域腳本攻擊等在近年來已經逐漸爲衆人熟知,很多網站也都針對他們進行了防禦。然而,對於大多數人來說,CSRF 卻依然是一個陌生的概念。即便是大名鼎鼎的 Gmail, 在 2007 年底也存在着 CSRF 漏洞,從而被黑客攻擊而使 Gmail 的用戶造成巨大的損失。
跨站請求僞造(XSRF/CSRF)的場景
這裏爲了加深大家對“跨站請求僞造(XSRF/CSRF)”的理解可以看如下所示的圖:
如上圖所示:
-
用戶瀏覽位於目標服務器 A 的網站。並通過登錄驗證。
-
獲取到 cookie_session_id,保存到瀏覽器 cookie 中。
-
在未登出服務器 A ,並在 session_id 失效前用戶瀏覽位於 hacked server B 上的網站。ASP.NET Core MVC是如何處理跨站請求僞造(XSRF/CSRF)的?
ASP.NET Core MVC是如何處理跨站請求僞造(XSRF/CSRF)的?
[ValidateAntiForgeryToken]、[AutoValidateAntiforgeryToken]、[IgnoreAntiforgeryToken]
ValidateAntiForgeryToken實質上是一個過濾器,可應用到單個操作,控制器或全局範圍內。除了具有IgnoreAntiforgeryToken
屬性的操作,否則所有應用了這個屬性的Action都會進行防僞驗證。如下所示:
C#複製
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RemoveLogin(RemoveLoginViewModel account)
{
ManageMessageId? message = ManageMessageId.Error;
var user = await GetCurrentUserAsync();
if (user != null)
{
var result =
await _userManager.RemoveLoginAsync(
user, account.LoginProvider, account.ProviderKey);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
message = ManageMessageId.RemoveLoginSuccess;
}
}
return RedirectToAction(nameof(ManageLogins), new { Message = message });
}
ValidateAntiForgeryToken
屬性所修飾的操作方法包括 HTTP GET 都需要一個Token進行驗證。 如果ValidateAntiForgeryToken
特性應用於應用程序的控制器上,則可以應用IgnoreAntiforgeryToken
來對它進行重載以便忽略此驗證過程。
<script>
function btnSubmit() {
$.ajax({
type: "Post",
url: "/manager/menuedit",
data: {__RequestVerificationToken: $("input[name='__RequestVerificationToken']").val()},
headers: {
"X-CSRF-TOKEN": '@GetAntiXsrfRequestToken()'
},
dataType: "html",
success: function (ret) {
alert(JSON.stringify(ret));
},
error: function (err, scnd) {
alert(err.statusText);
}
});
}
</script>
<form>
@Html.AntiForgeryToken()
<input type="button" οnclick="btnSubmit()" value="提交 " />
</form>