'Thông tin nhạy cảm' nào có thể bị tiết lộ khi đặt JsonRequestBehavior thành AllowGet


112

Tôi đã gặp cùng một lỗi cũ mỗi khi tôi kiểm tra một lỗi mới URLtừ thanh địa chỉ của trình duyệt khi tôi returning Json(sử dụng cài sẵn MVC JsonResult helper):

Yêu cầu này đã bị chặn vì thông tin nhạy cảm có thể được tiết lộ cho các trang web của bên thứ ba khi thông tin này được sử dụng trong a GET request. Để cho phép GET requests, hãy đặt JsonRequestBehaviorthành AllowGet.

Thay vì cằn nhằn xác nhận và kích hoạt Fiddler để thực hiện yêu cầu đăng bài, lần này, tôi đang tự hỏi chính xác điều gì mà một GETyêu cầu cho thấy một POSTyêu cầu thì không?

Câu trả lời:


82

Giả sử trang web của bạn có GetUserphương thức web:

http://www.example.com/User/GetUser/32

trả về phản hồi JSON:

{ "Name": "John Doe" }

Nếu phương thức này chỉ chấp nhận các yêu cầu POST, thì nội dung sẽ chỉ được trả về trình duyệt nếu một yêu cầu AJAX được thực hiện http://www.example.com/User/GetUser/32bằng cách sử dụng phương thức POST. Lưu ý rằng trừ khi bạn đã triển khai CORS , trình duyệt sẽ bảo vệ dữ liệu khỏi các miền khác đưa ra yêu cầu này cho bạn.

Tuy nhiên, nếu bạn cho phép yêu cầu GET sau đó cũng như thực hiện yêu cầu AJAX tương tự như trên với GET thay vì POST, người dùng độc hại có thể đưa JSON của bạn vào ngữ cảnh trang web của chính họ bằng cách sử dụng scriptthẻ trong HTML. ví dụ trên www.evil.com:

<script src="http://www.example.com/User/GetUser/32"></script>

JavaScript này sẽ vô dụng www.evil.comvì không có cách nào đọc được đối tượng mà phương thức web của bạn trả về. Tuy nhiên, do các lỗi trong các phiên bản trình duyệt cũ (ví dụ: Firefox 3), các đối tượng nguyên mẫu JavaScript có thể được xác định lại và có thể www.evil.comđọc dữ liệu được trả về bằng phương thức của bạn. Đây được gọi là JSON Hijacking.

Xem bài đăng này để biết một số phương pháp ngăn chặn điều này. Tuy nhiên, nó không phải là một vấn đề đã biết với các phiên bản sau của các trình duyệt hiện đại (Firefox, Chrome, IE).


25
Bài đăng rất hay, nhưng nếu bạn gắn thẻ [Authorize] vào bộ điều khiển, bạn không cần lo lắng về bảo mật. Hy vọng mã sẽ trợ giúp này ai đó, Json (returnMsg, JsonRequestBehavior.AllowGet)
Dhanuka777

17
@ Dhanuka777: Rất tiếc là không đúng. Các cuộc tấn công CSRF có thể xảy ra nếu phương pháp này có tác dụng phụ (ví dụ www.example.com/User/DeleteUser/32) vì yêu cầu sẽ bao gồm các cookie cần thiết để xác thực khi chúng đến từ máy của nạn nhân. [Authorize]sẽ không cứu bạn khỏi cuộc tấn công được nêu chi tiết ở đây trong trường hợp trình duyệt rất cũ - chính người dùng đang truy cập www.evil.comnên yêu cầu www.evil.comđưa ra www.example.comsẽ chứa cookie ủy quyền.
SilverlightFox

1
Và nếu hành động có bất kỳ tác dụng phụ nào thì hành động đó không bao giờ được gọi bằng phương thức GET - quy ước là sử dụng GET chỉ để đọc dữ liệu và tất cả các hoạt động tác động phụ nên sử dụng POST, PUT, DELETE, v.v. Nói cách khác, tôi chỉ nghĩ rằng thông báo lỗi 'thông tin nhạy cảm' này gây hiểu lầm. Nếu nhà phát triển sử dụng phương thức GET theo cách mà nó nên được sử dụng thì mọi thứ đều ổn! :)
ps_ttf

1
Tôi không chắc nó tạo ra sự khác biệt gì. Bài đăng không giống như của nó được bảo vệ hoặc mã hóa nhiều hơn nhận được. Nó vẫn chỉ là văn bản thuần túy. Tôi có thể gửi yêu cầu dễ dàng như đăng thông qua bất kỳ công cụ nào và vẫn nhận lại được thông tin văn bản thuần túy. Một người dùng độc hại cũng có thể dễ dàng viết bất kỳ mã phía máy chủ nào trên trang web của chính họ để thực hiện một bài đăng.
computrius

1
@Castrohenge: Không, vì điều này yêu cầu đặt tiêu đề sẽ không được gửi cùng với yêu cầu GET cho tập lệnh src.
SilverlightFox

111

khi bạn quay lại sử dụng những thứ sau:

return this.Json("you result", JsonRequestBehavior.AllowGet);

7
Làm thế nào điều này thực sự trả lời câu hỏi của OP? Tất cả các câu trả lời này làm là nói với mọi người như thế nào để có được xung quanh ngoại trừ ..
eaglei22

2
Vâng, hãy sử dụng nó .. Nó giống như thử bắt với một con trống. ĐỪNG sử dụng kẻ này (trước khi bạn hiểu những rủi ro). -1'd
sotn

6
Thật vô trách nhiệm khi nói mọi người phớt lờ cảnh báo an ninh mà không giải thích hậu quả. -1
Eduardo Wada

58

Theo mặc định, khung ASP.NET MVC không cho phép bạn phản hồi yêu cầu GET với tải trọng JSON vì có khả năng người dùng độc hại có thể truy cập vào tải trọng thông qua một quá trình được gọi là JSON Hijacking. Bạn không muốn trả lại thông tin nhạy cảm bằng JSON trong yêu cầu GET.

Nếu bạn cần gửi JSON để phản hồi một GET và không để lộ dữ liệu nhạy cảm, bạn có thể cho phép hành vi một cách rõ ràng bằng cách truyền JsonRequestBehavior.AllowGetdưới dạng tham số thứ hai cho Json phương thức.

Nhu la

  [HttpGet] //No need to decorate, as by default it will be GET
  public JsonResult GetMyData(){  
    var myResultDataObject = buildMyData(); // build, but keep controller thin
    // delegating buildMyData to builder/Query Builder using CQRS makes easy :)
    return Json(myResultDataObject, JsonRequestBehavior.AllowGet);
  }

Đây là một bài viết thú vị của Phil Haack JSON Hijackingvề lý do tại sao không sử dụng Json với phương thức GET


2
Bài rất hay. Lý do chính đáng tại sao bạn nên sử dụng HTTPS.
pqsk

6
Tôi không nghĩ HTTPS có ích ở đây.
Sean McMillan

10

Khi chúng ta muốn trả lại một đối tượng json cho máy khách từ ứng dụng MVC, chúng ta nên chỉ định rõ ràng JsonRequestBehavior.AllowGet khi trả về một đối tượng. Do đó, tôi trả về dữ liệu json như bên dưới để khắc phục sự cố:

    return Json(yourObjectData, JsonRequestBehavior.AllowGet);

7

Bạn phải sử dụng JsonRequestBehavior.AllowGet cho Json Response như thế này:

return Json(YourObject, JsonRequestBehavior.AllowGet);

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.