'Informasi sensitif' apa yang dapat diungkapkan saat menyetel JsonRequestBehavior ke AllowGet

112

Saya mendapatkan kesalahan lama yang sama setiap kali saya menguji yang baru URLdari bilah alamat browser saya saat saya returning Json(menggunakan bawaan MVC JsonResult helper):

Permintaan ini telah diblokir karena informasi sensitif dapat diungkapkan ke situs web pihak ketiga jika ini digunakan di GET request. Untuk mengizinkan GET requests, setel JsonRequestBehaviorke AllowGet.

Daripada mendengus dalam pengakuan dan menjalankan Fiddler untuk melakukan permintaan posting, kali ini, saya bertanya-tanya apa sebenarnya GETpermintaan yang mengekspos POSTpermintaan itu tidak?

A. Murray
sumber

Jawaban:

82

Katakanlah situs web Anda memiliki GetUsermetode web:

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

yang mengembalikan respons JSON:

{ "Name": "John Doe" }

Jika metode ini hanya menerima permintaan POST, maka konten hanya akan dikembalikan ke browser jika permintaan AJAX dibuat untuk http://www.example.com/User/GetUser/32menggunakan metode POST. Perhatikan bahwa kecuali Anda telah menerapkan CORS , browser akan melindungi data dari domain lain yang membuat permintaan ini kepada Anda.

Namun, jika Anda mengizinkan permintaan GET dan juga membuat permintaan AJAX yang serupa dengan yang di atas dengan GET, bukan POST, pengguna yang berniat jahat dapat menyertakan JSON Anda dalam konteks situs mereka sendiri dengan menggunakan scripttag di HTML. misalnya pada www.evil.com:

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

JavaScript ini seharusnya tidak berguna www.evil.comkarena seharusnya tidak ada cara membaca objek yang dikembalikan oleh metode web Anda. Namun, karena bug di versi lama browser (mis. Firefox 3), objek prototipe JavaScript dapat didefinisikan ulang dan memungkinkan untuk www.evil.commembaca data Anda yang dikembalikan oleh metode Anda. Ini dikenal sebagai JSON Hijacking.

Lihat posting ini untuk beberapa metode mencegah ini. Namun, ini bukan masalah yang diketahui dengan versi browser modern yang lebih baru (Firefox, Chrome, IE).

SilverlightFox
sumber
25
Posting yang bagus, tetapi jika Anda menyertakan tag [Otorisasi] ke pengontrol, Anda tidak perlu khawatir tentang keamanan. Semoga kode ini akan membantu seseorang, Json (returnMsg, JsonRequestBehavior.AllowGet)
Dhanuka777
17
@ Dhanuka777: Sayangnya tidak benar. Serangan CSRF dapat dimungkinkan jika metode tersebut memiliki efek samping (misalnya www.example.com/User/DeleteUser/32) karena permintaan akan menyertakan cookie yang diperlukan untuk otentikasi karena berasal dari mesin korban. [Authorize]tidak akan menyelamatkan Anda dari serangan yang dirinci di sini dalam kasus browser yang sangat lama juga - pengguna itu sendiri yang mengunjungi www.evil.comsehingga permintaan yang www.evil.comdibuat untuk www.example.comakan berisi cookie otorisasi.
SilverlightFox
1
Dan jika tindakan tersebut memiliki efek samping, tindakan tersebut tidak boleh dipanggil menggunakan metode GET - ketentuannya adalah menggunakan GET hanya untuk membaca data dan semua operasi efek samping harus menggunakan POST, PUT, DELETE, dll. Dengan kata lain, saya anggap saja pesan kesalahan 'informasi sensitif' ini menyesatkan. Jika pengembang menggunakan metode GET sebagaimana mestinya, maka semuanya baik-baik saja! :)
ps_ttf
1
Saya tidak yakin apa bedanya. Ini tidak seperti posting yang lebih terlindungi atau dienkripsi daripada get. Ini masih teks biasa. Saya dapat mengirim permintaan semudah mengirim melalui alat apa pun dan masih mendapatkan kembali informasi teks biasa yang sama. Seorang pengguna jahat dapat dengan mudah menulis kode sisi server apa pun di situs mereka sendiri untuk melakukan posting juga.
computrius
1
@Castrohenge: Tidak, karena ini memerlukan pengaturan header yang tidak akan dikirim dengan permintaan GET untuk script src.
SilverlightFox
111

dalam pengembalian Anda gunakan yang berikut ini:

return this.Json("you result", JsonRequestBehavior.AllowGet);
OldTrain
sumber
7
Bagaimana ini sebenarnya menjawab pertanyaan OP? Semua jawaban ini tidak memberitahu semua orang bagaimana menyiasati pengecualian ..
eaglei22
2
Ya, gunakan .. Ini seperti mencoba menangkap dengan tangkapan kosong. JANGAN gunakan orang ini (sebelum Anda memahami risikonya). -1'd
sotn
6
Tidak bertanggung jawab memberi tahu orang-orang untuk mengabaikan peringatan keamanan tanpa setidaknya menjelaskan konsekuensinya. -1
Eduardo Wada
58

Secara default, kerangka kerja ASP.NET MVC tidak memungkinkan Anda untuk menanggapi permintaan GET dengan muatan JSON karena ada kemungkinan pengguna jahat dapat memperoleh akses ke muatan melalui proses yang dikenal sebagai JSON Hijacking. Anda tidak ingin mengembalikan informasi sensitif menggunakan JSON dalam permintaan GET.

Jika Anda perlu mengirim JSON sebagai respons terhadap GET, dan tidak mengekspos data sensitif, Anda dapat secara eksplisit mengizinkan perilaku dengan meneruskan JsonRequestBehavior.AllowGetsebagai parameter kedua ke Json metode.

Seperti

  [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);
  }

Berikut adalah artikel menarik dari Phil Haack JSON Hijackingtentang mengapa tidak menggunakan Json dengan metode GET

Murali Murugesan
sumber
2
Pos yang bagus. Alasan bagus mengapa Anda harus menggunakan HTTPS.
pqsk
6
Saya rasa HTTPS tidak membantu di sini.
Sean McMillan
10

Ketika kita ingin mengembalikan objek json ke klien dari aplikasi MVC, kita harus secara eksplisit menentukan JsonRequestBehavior.AllowGet saat mengembalikan objek. Akibatnya, saya mengembalikan data json seperti di bawah ini untuk mengatasi masalah tersebut:

    return Json(yourObjectData, JsonRequestBehavior.AllowGet);
Loc Huynh
sumber
7

Anda harus menggunakan JsonRequestBehavior.AllowGet untuk Json Response seperti ini:

return Json(YourObject, JsonRequestBehavior.AllowGet);
keivan kashani
sumber
0

return Json ("Success", JsonRequestBehavior.AllowGet)

Pergin Sheni
sumber