Jakie „poufne informacje” mogą zostać ujawnione podczas ustawiania JsonRequestBehavior na AllowGet

112

Za każdym razem, gdy testuję nowy URLz paska adresu przeglądarki, otrzymuję ten sam stary błąd returning Json(używam wbudowanego MVC JsonResult helper):

To żądanie zostało zablokowane, ponieważ poufne informacje mogą zostać ujawnione witrynom internetowym osób trzecich, gdy jest to używane w GET request. Aby zezwolić GET requests, ustaw JsonRequestBehaviorna AllowGet.

Zamiast chrząkać w potwierdzeniu i odpalić Fiddlera, aby wykonać prośbę o wpis, tym razem zastanawiam się, co dokładnie oznacza, że GETżądanie ujawnia, a POSTnie żądanie?

A. Murray
źródło

Odpowiedzi:

82

Załóżmy, że Twoja witryna ma GetUsermetodę internetową:

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

która zwraca odpowiedź JSON:

{ "Name": "John Doe" }

Jeśli ta metoda akceptuje tylko żądania POST, zawartość zostanie zwrócona do przeglądarki tylko wtedy, gdy żądanie AJAX zostanie wysłane http://www.example.com/User/GetUser/32przy użyciu metody POST. Pamiętaj, że jeśli nie zaimplementowałeś CORS , przeglądarka będzie chronić dane z innych domen wysyłających to żądanie do Ciebie.

Jeśli jednak zezwolisz na żądania GET, a także wykonanie żądania AJAX podobnego do powyższego za pomocą GET zamiast POST, złośliwy użytkownik może dołączyć twój scriptkod JSON w kontekście własnej witryny, używając tagu w kodzie HTML. np. na www.evil.com:

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

Ten JavaScript powinien być bezużyteczny, www.evil.componieważ nie powinno być możliwości odczytania obiektu zwróconego przez twoją metodę sieciową. Jednak ze względu na błędy występujące w starszych wersjach przeglądarek (np. Firefox 3) istnieje możliwość przedefiniowania obiektów prototypowych JavaScript i umożliwienia www.evil.comodczytu danych zwróconych przez Twoją metodę. Jest to znane jako przechwytywanie JSON.

Zobacz ten post, aby zapoznać się z metodami zapobiegania temu. Nie jest to jednak znany problem z późniejszymi wersjami nowoczesnych przeglądarek (Firefox, Chrome, IE).

SilverlightFox
źródło
25
Niezły post, ale jeśli dołączysz tag [Authorize] do kontrolera, nie musisz się martwić o bezpieczeństwo. Mam nadzieję, że ten kod komuś pomoże, Json (returnMsg, JsonRequestBehavior.AllowGet)
Dhanuka777
17
@ Dhanuka777: Niestety nie prawda. Ataki CSRF mogą być możliwe, jeśli metoda ma skutki uboczne (np. www.example.com/User/DeleteUser/32), Ponieważ żądanie będzie zawierać pliki cookie niezbędne do uwierzytelnienia, ponieważ pochodzą one z komputera ofiary. [Authorize]nie uchroni Cię również przed atakiem opisanym tutaj w przypadku bardzo starej przeglądarki - to sam użytkownik odwiedza, www.evil.comwięc żądanie skierowane www.evil.comdo www.example.combędzie zawierało plik cookie autoryzacyjny.
SilverlightFox
1
A jeśli akcja ma jakieś skutki uboczne, nigdy nie powinna być wywoływana metodą GET - konwencja polega na używaniu GET tylko do odczytu danych, a wszystkie operacje powodujące efekty uboczne powinny używać POST, PUT, DELETE itp. Innymi słowy, ja pomyśl tylko, że ten komunikat o błędzie dotyczący informacji poufnych jest mylący. Jeśli programista używa metody GET w sposób, w jaki powinna być używana, wszystko jest w porządku! :)
ps_ttf
1
Nie jestem pewien, jaka to różnica. To nie tak, że poczta jest bardziej chroniona lub szyfrowana niż get. Nadal jest to zwykły tekst. Mogę wysłać prośbę tak samo łatwo, jak pocztę za pomocą dowolnego narzędzia i nadal otrzymuję te same informacje w postaci zwykłego tekstu. Szkodliwy użytkownik mógłby równie łatwo napisać dowolny kod po stronie serwera we własnej witrynie, aby również zrobić post.
computrius
1
@Castrohenge: Nie, ponieważ wymaga to ustawienia nagłówka, który nie zostanie wysłany z żądaniem GET dla skryptu src.
SilverlightFox,
111

w zwrocie użyj:

return this.Json("you result", JsonRequestBehavior.AllowGet);
OldTrain
źródło
7
Jak to właściwie odpowiada na pytanie PO? Wszystko, co robi ta odpowiedź, to powie wszystkim, jak obejść wyjątek ...
eaglei22
2
Tak, użyj tego .. To jak próba złapania z pustym zaczepem. NIE używaj tego facetów (zanim zrozumiesz ryzyko). -1'd
sotn
6
Nieodpowiedzialne jest mówienie ludziom, aby zignorowali ostrzeżenie bezpieczeństwa bez przynajmniej wyjaśnienia konsekwencji. -1
Eduardo Wada
58

Domyślnie struktura ASP.NET MVC nie pozwala odpowiadać na żądanie GET z ładunkiem JSON, ponieważ istnieje szansa, że ​​złośliwy użytkownik może uzyskać dostęp do ładunku za pośrednictwem procesu znanego jako przejęcie JSON. Nie chcesz zwracać poufnych informacji przy użyciu formatu JSON w żądaniu GET.

Jeśli musisz wysłać JSON w odpowiedzi na GET i nie ujawniasz poufnych danych, możesz jawnie zezwolić na zachowanie, przekazując JsonRequestBehavior.AllowGetjako drugi parametr do Json metody.

Jak na przykład

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

Oto interesujący artykuł Phila Haacka JSON Hijackingo tym, dlaczego nie używać Json z metodą GET

Murali Murugesan
źródło
2
Wspaniały post. Dobry powód, dla którego powinieneś używać HTTPS.
pqsk
6
Myślę, że HTTPS nie pomaga tutaj.
Sean McMillan
10

Kiedy chcemy zwrócić obiekt json do klienta z aplikacji MVC, powinniśmy jawnie określić JsonRequestBehavior.AllowGet podczas zwracania obiektu. W rezultacie zwracam dane json jak poniżej, aby rozwiązać problem:

    return Json(yourObjectData, JsonRequestBehavior.AllowGet);
Loc Huynh
źródło
7

Musisz używać JsonRequestBehavior.AllowGet dla odpowiedzi Json w następujący sposób:

return Json(YourObject, JsonRequestBehavior.AllowGet);
keivan kashani
źródło
0

return Json ("Sukces", JsonRequestBehavior.AllowGet)

Pergin Sheni
źródło