Le détournement JSON est-il toujours un problème dans les navigateurs modernes?

149

J'utilise Backbone.js et le serveur Web Tornado. Le comportement standard pour recevoir des données de collection dans Backbone consiste à envoyer en tant que tableau JSON.

D'autre part, le comportement standard de Tornado est de ne pas autoriser JSON Array en raison de la vulnérabilité suivante:

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

Un lien connexe est: http://haacked.com/archive/2009/06/25/json-hijacking.aspx

Il me semble plus naturel de ne pas avoir à envelopper mon JSON dans un objet alors qu'il s'agit vraiment d'une liste d'objets.

Je n'ai pas pu reproduire ces attaques dans les navigateurs modernes (c'est-à-dire Chrome, Firefox, Safari et IE9 actuels). Dans le même temps, je n'ai pu confirmer nulle part que les navigateurs modernes avaient résolu ces problèmes.

Pour m'assurer que je ne suis trompé ni par d'éventuelles faibles compétences en programmation ni par de mauvaises compétences en recherche sur Google:

Ces attaques de détournement JSON sont-elles toujours un problème aujourd'hui dans les navigateurs modernes?

(Remarque: Désolé pour le doublon possible à: Est-il possible de faire un `` détournement JSON '' sur un navigateur moderne? Mais comme la réponse acceptée ne semble pas répondre à la question - j'ai pensé qu'il était temps de la poser à nouveau et d'obtenir des explications plus claires .)

Rocketman
la source
en utilisant eval? alors possible sinon Non. Si rien n'a été altéré ou changé dans la manière dont la colonne vertébrale analyse la réponse, vous devriez être en sécurité
Deeptechtons
10
De manière générale, vous ne devez jamais aborder la sécurité Web en supposant que quelqu'un utilisera un navigateur «moderne».
Luc
7
@Luke - Voir ci-dessous le commentaire à Reid. Excellent point en général - mais je ne pose pas de question de sécurité générale. (Mes utilisateurs ne pourront s'authentifier que s'ils utilisent un navigateur moderne en premier lieu.)
Rocketman
4
@Luke, parfois nous devons passer à autre chose et nous permettre de développer avec des modèles modernes (comme REST dans ce cas: l'obtention de données est une opération GET et ne devrait pas être autre chose) sans se protéger contre les anciennes menaces si elles semblent maintenant s'appliquer uniquement à un petit public. Cette question est donc vraiment précieuse, pour permettre d'évaluer s'il peut ignorer cette menace ou non pour son cas d'application. À un moment donné, les utilisateurs avec des logiciels très obsolètes sont très susceptibles d'avoir d'autres types de menaces (logiciels malveillants) contre lesquels nous ne pourrons de toute façon pas les protéger.
Frédéric
2
@jpaugh, où voyez-vous de telles hypothèses? Je suppose seulement un peu que ces personnes avec des logiciels obsolètes sont de toute façon «non protégés». (Pour justifier le coût de mes patins, j'avais déjà l'habitude de mettre un tiers de leur prix dans des patins de vitesse en carbone qui s'usaient en moins d'un tiers du temps qu'il me fallait pour user mes patins actuels. Et de toute façon, je pense qu'ils en valent la peine, à condition que tu aimes les chevaucher, ce qui est mon cas.)
Frédéric

Réponses:

112

Non, il n'est plus possible de capturer les valeurs transmises aux constructeurs []ou {}dans Firefox 21, Chrome 27 ou IE 10. Voici une petite page de test, basée sur les principales attaques décrites dans http://www.thespanner.co.uk / 2011/05/30 / json-détournement / :

( 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>

Il remplace window.Arrayet ajoute un setter àObject.prototype.foo et teste l'initialisation des tableaux et des objets via les formes courtes et longues.

La spécification ES4 , dans la section 1.5, "exige que les liaisons standard globales d'Objet et Array soient utilisées pour construire de nouveaux objets pour les initialiseurs d'objets et de tableaux" et note dans Précédente d'implémentation que "Internet Explorer 6, Opera 9.20 et Safari 3 font ne respecte pas les reliaisons locales ou globales d'Object et de Array, mais utilise les constructeurs Object et Array d'origine. " Ceci est conservé dans ES5, section 11.1.4 .

Allen Wirfs-Brock a expliqué que ES5 spécifie également que l'initialisation d'objet ne doit pas déclencher les setters, car elle utilise DefineOwnProperty. MDN: Working with Objects note que «À partir de JavaScript 1.8.1, les setters ne sont plus appelés lors de la définition des propriétés dans les initialiseurs d'objets et de tableaux». Ce problème a été abordé dans le numéro 1015 du V8 .

jpaugh
la source
28
En 2009, Brendan Eich a suggéré que les navigateurs n'évaluent pas les scripts utilisés comme application / json ( bugzilla.mozilla.org/show_bug.cgi?id=376957#c75 ), ce qui me semble toujours une bonne idée.
2
Notez que le POST CSRF aveugle est toujours possible en utilisant des formulaires, en particulier avec le codage texte / brut, et doit être vaincu en utilisant des jetons / nonces.
1
Oui au POST CSRF. Merci pour toutes vos bonnes informations ici.
Rocketman
5
Votre déclaration est correcte lorsqu'elle se réfère uniquement à l'écrasement du constructeur Array. Cependant, Microsoft IE et Edge sont toujours vulnérables au piratage JSON UTF-7. Je l'ai testé récemment (et pour le plaisir aujourd'hui encore), et cela fonctionne toujours.
user857990
2
UTF-16BE également, merci à Gareth Heyes, blog.portswigger.net/2016/11/json-hijacking-for-modern-web.html
eel ghEEz