2012-04-01 43 views
21

Có cách nào để đảm bảo các hình thức ASP.NET MVC 4 được bảo vệ chống lại CSRF theo mặc định?Làm thế nào để bảo vệ chống lại CSRF theo mặc định trong ASP.NET MVC 4?

Ví dụ: có cách nào để có AntiForgeryToken tự động áp dụng cho tất cả các biểu mẫu trong cả chế độ xem và hành động của bộ điều khiển?

Thông tin cơ bản về câu hỏi này: Prevent Cross-Site Request Forgery (CSRF) using ASP.NET MVC’s AntiForgeryToken() helperAnatomy of a Cross-site Request Forgery Attack.

+0

Tôi cho rằng điều này chỉ thực sự cần thiết trên các biểu mẫu cấp quyền truy cập, chẳng hạn như biểu mẫu đăng nhập hoặc biểu mẫu quản trị quyền người dùng hoặc biểu mẫu gửi thông tin nhận dạng cá nhân như số an sinh xã hội và cụm từ mật khẩu. Nhưng tôi mong được nhìn thấy câu trả lời. –

+4

Vì CSRF có thể cho phép bất kỳ ai thực hiện bất kỳ hành động nào trên ứng dụng web theo thông tin đăng nhập của bạn, có vẻ như với tôi rằng tất cả các hành động nhập hoặc sửa đổi dữ liệu phải được bảo vệ chống lại nó. Ví dụ: thêm bản ghi vào ứng dụng kế toán. –

+1

Họ sẽ, tất nhiên, cần thông tin đăng nhập của bạn trước tiên. :) –

Trả lời

22

Để thêm vào câu trả lời tuyệt vời osoviejo, những hướng dẫn dưới đây, từ gần đây của tôi blog post on CSRF, đặt công việc của mình cùng với các thông tin trong Blog của Phil trong một câu trả lời toàn diện.

ASP.NET/MVC cung cấp cơ chế cho việc này: bạn có thể thêm vào bộ sưu tập các bộ lọc trên đối tượng toàn cầu FilterProviders. Điều này cho phép bạn nhắm mục tiêu một số bộ điều khiển chứ không phải cho người khác, thêm tính năng bảo mật cần thiết.

Trước tiên, chúng tôi cần triển khai IFilterProvider. Dưới đây, bạn có thể tìm thấy lớp học Conditional Filter Provider của Phil Haack. Bắt đầu bằng cách thêm lớp này vào dự án của bạn.

public class ConditionalFilterProvider : IFilterProvider 
{ 
    private readonly 
     IEnumerable<Func<ControllerContext, ActionDescriptor, object>> _conditions; 

    public ConditionalFilterProvider(
     IEnumerable<Func<ControllerContext, ActionDescriptor, object>> conditions) 
    { 
     _conditions = conditions; 
    } 

    public IEnumerable<Filter> GetFilters(
     ControllerContext controllerContext, 
     ActionDescriptor actionDescriptor) 
    { 
     return from condition in _conditions 
       select condition(controllerContext, actionDescriptor) into filter 
       where filter != null 
       select new Filter(filter, FilterScope.Global, null); 
    } 
} 

Sau đó, thêm mã để Application_Start có thêm một mới ConditionalFilterProvider đến việc thu thập FilterProviders toàn cầu để đảm bảo rằng tất cả các phương pháp điều khiển POST sẽ yêu cầu AntiForgeryToken.

IEnumerable<Func<ControllerContext, ActionDescriptor, object>> conditions = 
    new Func<ControllerContext, ActionDescriptor, object>[] { 
    // Ensure all POST actions are automatically 
    // decorated with the ValidateAntiForgeryTokenAttribute. 

    (c, a) => string.Equals(c.HttpContext.Request.HttpMethod, "POST", 
    StringComparison.OrdinalIgnoreCase) ? 
    new ValidateAntiForgeryTokenAttribute() : null 
}; 

var provider = new ConditionalFilterProvider(conditions); 

// This line adds the filter we created above 
FilterProviders.Providers.Add(provider); 

Nếu bạn thực hiện hai đoạn mã trên, ứng dụng MVC của bạn nên yêu cầu AntiForgeryToken cho mỗi POST cho trang web. Bạn có thể thử nó trên CSRF example web site của Phil Haack - một khi được bảo vệ, cuộc tấn công CSRF sẽ ném System.Web.Mvc.HttpAntiForgeryException mà không cần phải thêm chú thích [ValidateAntiForgeryToken]. Quy tắc này đưa ra một loạt các lỗ hổng liên quan đến "lập trình viên quên".

+0

Cách tiếp cận này có hoạt động với bài đăng ajax không? – Vincent

+0

Vâng, tôi tin như vậy. –

+0

Câu hỏi này dành riêng cho MVC4 nhưng tôi có cảm giác điều này cũng có thể hoạt động trong các phiên bản cũ hơn như 3, đúng không? – evanmcdonnal

0

Một cách để làm điều đó sẽ thay đổi các mẫu T4 trong ASP.NET MVC mà tạo các biểu mẫu, để họ có chèn mã này tự động:

<% using(Html.Form("UserProfile", "SubmitUpdate")) { %> 
    <%= Html.AntiForgeryToken() %> 
    <!-- rest of form goes here --> 
<% } %> 

Và tất nhiên, bạn cần thuộc tính tương ứng trên phương pháp điều khiển:

[ValidateAntiForgeryToken] 
public ViewResult SubmitUpdate() 
{ 
    // ... etc 
} 

Thực sự không khó để trang bị thêm ứng dụng theo cách này, trừ khi nó lớn bất thường. Ứng dụng cuối cùng tôi đã viết trong MVC có lẽ sẽ đưa tôi một vài giờ để trang bị thêm.

+0

Robert, cảm ơn bạn vì mã mẫu này. Nó rất hữu dụng. Nhưng tôi đang cố gắng tìm hiểu xem có cách nào để tự động áp dụng điều này trên tất cả các biểu mẫu và tất cả các hành động của bộ điều khiển, như một tấm chăn. Ví dụ, để ngăn chặn khả năng quên thêm thuộc tính vào phương thức điều khiển. –

2

Tôi đã sử dụng FXCop để viết hai quy tắc phân tích mã yêu cầu một thuộc tính HttpMethod được áp dụng cho tất cả các hành động điều khiển và thứ hai yêu cầu bất kỳ hành động nào có thuộc tính HttpPost cũng phải có thuộc tính RequiresAntiForgeryToken.

Điều này phù hợp với chúng tôi. Các quy tắc không đặc biệt khó để viết

11

Bạn có thể sử dụng nhà cung cấp bộ lọc có điều kiện là bộ lọc ValidateAntiForgeryTokenAttribute() được áp dụng bất cứ khi nào HttpContext.Request.HttpMethod == "POST".

tôi về cơ bản theo cách tiếp cận chung described by Phil Haack, và bổ sung các điều kiện thích hợp:

// Ensure all POST actions are automatically decorated with the ValidateAntiForgeryTokenAttribute. 
(c, a) => string.Equals(c.HttpContext.Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase) ? 
new ValidateAntiForgeryTokenAttribute() : null 
+0

Điều đó nghe có vẻ giống như một cách tiếp cận tốt. Cảm ơn bạn. –

+1

Tôi đã kết hợp câu trả lời này với thông tin về ConditionalFilterProvider's từ bài đăng trên blog của Phil trong một bài viết gần đây về CSRF và ASP.NET/MVC. http://kylehodgson.com/2013/01/08/asp-netmvc-web-security-basics-csrf/ –

Các vấn đề liên quan