ASP.NET MVC與CSRF(跨站指令碼)攻擊

來源:互聯網
上載者:User

標籤:參考   通過   login   瀏覽器   test   區別   syn   orm   manage   

CSRF一 何為CSRF

CSRF(Cross-site request forgery跨站請求偽造,也被稱成為“one click attack”或者session riding,通常縮寫為CSRF或者XSRF,是一種對網站的惡意利用。需要注意的是,CSRF與XSS的區別,CSRF是其他網站進行對你的網站的攻擊。

關於CSRF的詳細資料請看:https://baike.baidu.com/item/CSRF/2735433

 

二 CSRF的危害

對CSRF進行簡單瞭解後,我們先來看看CSRF攻擊受害者需要幾步。

受害者必須依次完成兩個步驟:

  1.登入受信任網站A,並在本地產生Cookie。

  2.在不登出A的情況下,訪問危險網站B。

此時危險網站B擁有受害者在信任網站A的登入驗證cookie,假設Cookie沒有失效或者到期,那麼危險網站B就可以發起假冒的請求,來擷取受害者在信任網站A的資訊或者在受害者不知情的情況下,進行資金轉移等。

 

三 MVC是如何防止CSRF的

MVC架構主要通過在form內添加@Html.AntiForgeryToken()和在action上添加 [ValidateAntiForgeryToken]進行防止。

具體代碼如下:

1. 在cshtml頁面加上 @Html.AntiForgeryToken()

<section id="loginForm">
@using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
@Html.AntiForgeryToken()
<h4>使用本地帳戶登入。</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.PasswordFor(m => m.Password, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
@Html.CheckBoxFor(m => m.RememberMe)
@Html.LabelFor(m => m.RememberMe)
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="登入" class="btn btn-default" />
</div>
</div>
<p>
@Html.ActionLink("註冊為新使用者", "Register")
</p>
@* 為密碼重設功能啟用帳戶確認後,請啟用此項一次
<p>
@Html.ActionLink("Forgot your password?", "ForgotPassword")
</p>*@
}
</section>

2. 在相應的action方法上添加[ValidateAntiForgeryToken]

 

//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindAsync(model.Email, model.Password);
if (user != null)
{
await SignInAsync(user, model.RememberMe);
return RedirectToLocal(returnUrl);
}
else
{
ModelState.AddModelError("", "使用者名稱或密碼無效。");
}
}

// 如果我們進行到這一步時某個地方出錯,則重新顯示表單
return View(model);
}

 

3.MVC在預防CSRF上的原理

 @Html.AntiForgeryToken()方法會在瀏覽器上做兩件事:

  1. 頁面上加上一個標籤<input name="__RequestVerificationToken" type="hidden" value="密文A" />

  2. 在瀏覽器上產生一個名為__RequestVerificationToken的Cookie,值為“密文B”

form表單提交時,會將頁面上的密文A和瀏覽器的密文B一起提交給伺服器端,伺服器端分別對密文A和密文B進行解密,比對密文A和密文B解密後的明文字串是否相同,如果相同,則驗證通過。

那麼密文A和密文B是從何而來呢,其實是上面的@Html.AntiForgeryToken()方法隨機產生了一串明文,然後再對明文加密放在頁面和cookie內,但是加密出來的密文不同。密文A每次重新整理都會更新成不同的密文,但是一個瀏覽器進程內,COOKIE的密文好像不變(自己在firefox內試了幾次,有興趣的同學可以自己嘗試一下)

四 AJAX請求如何防止CSRF

上面說了MVC架構如何防止CSRF的,但是只限於FORM表單提交,那麼問題來了,在一般ajax請求時,沒有form表單提交,這個時候該如何防止CSRF呢?網路上有很多不錯的答案。我在寫該篇隨筆的時候也借鑒了很多前輩的方法。

下面介紹我的方法:

 

1. 在全域共用頁面,添加密文產生代碼:

@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "__AjaxAntiForgeryForm" }))
{
@Html.AntiForgeryToken()
}

2. 收緊ajax要求方法入口,寫擴充ajax方法避免重複工作,一定要注意黃色標記

$.extend({
  z_ajax: function (request) {
      var form = $(‘#__AjaxAntiForgeryForm‘);
      var antiForgery = $("input[name=‘__RequestVerificationToken‘]",form).val();
      var data = $.extend({ __RequestVerificationToken: antiForgery }, request.data);
      request = $.extend({
      type: "POST",
      dataType: "json",
      contentType: ‘application/x-www-form-urlencoded; charset=utf-8‘,
      }, request);
      request.data = data;

  $.ajax(request);
}

3. 在需要的POST請求上,添加[ValidateAntiForgeryToken]

[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult Test(string testString)
{
  var trustedString = Encoder.HtmlEncode(testString);
  return Json(trustedString);
}

4. 實現具體的ajax請求,該請求會自動將密文帶到服務端,由服務端的特性驗證

$(function () {
  $("#test").click(function ()
  {
    $.z_ajax(
    {
      url: "/Home/Test",
      data: {testString:‘333333‘},
      error: function (request, textStatus, errorThrown) {
        console.log(request, textStatus, errorThrown);
      },
      success: function (response)
      {
        alert(123);
      }
    });
  })
})

 

經過以上的講解,大家應該對MVC 防止CSRF有了一定的認識。

正如上面所說,在編寫這篇隨筆的時候,參考了很多前輩的思路和結晶。在這裡就不一一列舉了,如果有什麼問題,歡迎大家隨時反饋。

以上案例使用VS2013自動產生的MVC5網站作為解析。

 

ASP.NET MVC與CSRF(跨站指令碼)攻擊

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.