Czy przejęcie JSON nadal stanowi problem w nowoczesnych przeglądarkach?

149

Używam Backbone.js i serwera WWW Tornado. Standardowym zachowaniem podczas odbierania danych kolekcji w Backbone jest wysyłanie jako tablica JSON.

Z drugiej strony standardowym zachowaniem Tornado jest uniemożliwienie korzystania z tablic JSON ze względu na następującą lukę:

http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx

Powiązany to: http://haacked.com/archive/2009/06/25/json-hijacking.aspx

Wydaje mi się bardziej naturalne, że nie muszę zawijać mojego kodu JSON w obiekcie, gdy tak naprawdę jest to lista obiektów.

Nie byłem w stanie odtworzyć tych ataków w nowoczesnych przeglądarkach (tj. Aktualnej przeglądarce Chrome, Firefox, Safari i IE9). Jednocześnie nigdzie nie byłem w stanie potwierdzić, że nowoczesne przeglądarki rozwiązały te problemy.

Aby upewnić się, że nie wprowadzają mnie w błąd żadne możliwe słabe umiejętności programowania ani słabe umiejętności googlowania:

Czy ataki typu JSON Hijacking nadal stanowią problem w nowoczesnych przeglądarkach?

(Uwaga: przepraszam za możliwy duplikat: Czy można zrobić `` przechwytywanie JSON '' w nowoczesnej przeglądarce? Ale ponieważ zaakceptowana odpowiedź nie wydaje się odpowiadać na pytanie - pomyślałem, że nadszedł czas, aby zadać to ponownie i uzyskać jaśniejsze wyjaśnienia .)

Człowiek rakieta
źródło
używając eval? to możliwe w inny sposób Nie. Jeśli nic nie zostało zmienione lub zmienione w sposobie, w jaki szkielet analizuje odpowiedź, to powinieneś być bezpieczny
Deeptechtons
10
Ogólnie rzecz biorąc, nigdy nie należy podchodzić do bezpieczeństwa w sieci z założeniem, że ktoś będzie używał „nowoczesnej” przeglądarki.
Łukasz
7
@Luke - Zobacz poniżej komentarz do Reida. Ogólnie rzecz biorąc, świetna uwaga - ale nie zadaję ogólnego pytania zabezpieczającego. (Moi użytkownicy będą mogli się uwierzytelnić tylko wtedy, gdy używają nowoczesnej przeglądarki.)
Rocketman
4
@Luke, czasami musimy iść dalej i pozwolić nam rozwijać się z nowoczesnymi wzorcami (takimi jak REST w tym przypadku: pozyskiwanie danych jest operacją GET i nie powinno być czymś innym) bez ochrony przed starymi zagrożeniami, jeśli teraz wydają się obowiązywać tylko małej publiczności. Więc to pytanie jest naprawdę cenne, aby umożliwić ocenę, czy można zignorować tę groźbę, czy nie w swoim przypadku. W pewnym momencie użytkownik z bardzo przestarzałym oprogramowaniem może mieć inne rodzaje zagrożeń (złośliwe oprogramowanie), przed którymi i tak nie będziemy w stanie ich ochronić.
Frédéric
2
@jpaugh, gdzie widzisz takie założenia? Zakładam tylko trochę, że ci ludzie z tak przestarzałym oprogramowaniem i tak są „niechronieni”. (Jeśli chodzi o uzasadnienie kosztu moich rolek, przyzwyczaiłem się już do umieszczania jednej trzeciej ich ceny w rolkach szybkich z włókna węglowego, które zużyły się w mniej niż jedną trzecią czasu, w którym zużywa się moje obecne rolki. myślę, że są tego warte, pod warunkiem, że lubisz jeździć na nich, co jest moim przypadkiem.)
Frédéric

Odpowiedzi:

112

Nie, nie jest już możliwe przechwytywanie wartości przekazywanych do konstruktorów []lub {}w przeglądarkach Firefox 21, Chrome 27 lub IE 10. Oto mała strona testowa oparta na głównych atakach opisanych na http://www.thespanner.co.uk / 2011/05/30 / json-hijacking / :

( http://jsfiddle.net/ph3Uv/2/ )

var capture = function() {
    var ta = document.querySelector('textarea')
	ta.innerHTML = '';
	ta.appendChild(document.createTextNode("Captured: "+JSON.stringify(arguments)));
	return arguments;
}
var original = Array;

var toggle = document.body.querySelector('input[type="checkbox"]');
var toggleCapture = function() {
    var isOn = toggle.checked;
    window.Array = isOn ? capture : original;
    if (isOn) {
        Object.defineProperty(Object.prototype, 'foo', {set: capture});    
    } else {
        delete Object.prototype.foo;
    }
};
toggle.addEventListener('click', toggleCapture);
toggleCapture();

[].forEach.call(document.body.querySelectorAll('input[type="button"]'), function(el) {
    el.addEventListener('click', function() {
        document.querySelector('textarea').innerHTML = 'Safe.';
        eval(this.value);
    });
});
<div><label><input type="checkbox" checked="checked"> Capture</label></div>
<div><input type="button" value="[1, 2]" /> <input type="button" value="Array(1, 2);" /> <input type="button" value="{foo: 'bar'}" /> <input type="button" value="({}).foo = 'bar';" /></div>
<div><textarea></textarea></div>

Zastępuje window.Arrayi dodaje metodę ustawiającą Object.prototype.foooraz testuje inicjalizację tablic i obiektów za pomocą krótkich i długich formularzy.

Specyfikacja ES4 , w sekcji 1.5, „wymaga użycia globalnych, standardowych powiązań Object i Array do konstruowania nowych obiektów dla inicjatorów obiektów i tablic” oraz uwagi w poprzedniej implementacji, że „Internet Explorer 6, Opera 9.20 i Safari 3 wymagają nie respektuje ani lokalnych, ani globalnych ponownych wiązań Object i Array, ale używa oryginalnych konstruktorów Object i Array. ” Zostało to zachowane w ES5, sekcja 11.1.4 .

Allen Wirfs-Brock wyjaśnił, że ES5 określa również, że inicjalizacja obiektu nie powinna wyzwalać seterów, ponieważ używa DefineOwnProperty. MDN: Working with Objects zauważa, że ​​„Począwszy od JavaScript 1.8.1, metody ustawiające nie są już wywoływane podczas ustawiania właściwości w inicjatorach obiektów i tablic”. Ten problem został rozwiązany w numerze 1015 V8 .

jpaugh
źródło
28
W 2009 roku Brendan Eich zasugerował, że przeglądarki nie oceniają skryptów służących jako application / json ( bugzilla.mozilla.org/show_bug.cgi?id=376957#c75 ), co nadal wydaje mi się dobrym pomysłem.
2
Zauważ, że ślepe CSRF POST jest nadal możliwe przy użyciu formularzy, szczególnie z kodowaniem tekstowym / zwykłym, i musi zostać pokonane za pomocą tokenów / wartości nonce.
1
Tak, do POST CSRF. Dzięki za wszystkie świetne informacje tutaj.
Rocketman
5
Twoje stwierdzenie jest poprawne, gdy odnosi się tylko do prostego nadpisania konstruktora Array. Jednak Microsofty IE i Edge są nadal podatne na przechwytywanie JSON UTF-7. Przetestowałem go niedawno (i dzisiaj znowu dla zabawy) i nadal działa.
user857990
2
UTF-16BE również, dzięki Garethowi Heyesowi
eel ghEEz