JSON Hijacking все еще остается проблемой в современных браузерах?

149

Я использую Backbone.js и веб-сервер Tornado. Стандартное поведение для получения данных коллекции в Backbone - отправка в виде массива JSON.

С другой стороны, стандартное поведение Tornado не допускает использование JSON Array из-за следующей уязвимости:

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

Связанный является: http://haacked.com/archive/2009/06/25/json-hijacking.aspx

Для меня более естественно, что мне не нужно заключать JSON в объект, когда это действительно список объектов.

Мне не удалось воспроизвести эти атаки в современных браузерах (то есть в современных Chrome, Firefox, Safari и IE9). В то же время я нигде не смог подтвердить, что современные браузеры решили эти проблемы.

Чтобы убедиться, что меня не вводят в заблуждение ни какие-либо возможные плохие навыки программирования или плохие навыки поиска в Google:

Являются ли эти атаки JSON Hijacking все еще проблемой современных браузеров?

(Примечание: извините за возможный дубликат: возможно ли выполнить «захват JSON» в современном браузере? Но так как принятый ответ, похоже, не отвечает на вопрос - я подумал, что пришло время задать его снова и получить более четкие объяснения .)

Ракета человек
источник
используя eval? если это возможно, иначе Нет. Если ничего не было изменено или изменено в способе анализа ответа магистральной линии, тогда вы должны быть в безопасности
Deeptechtons
10
Вообще говоря, вы никогда не должны подходить к веб-безопасности с предположением, что кто-то собирается использовать «современный» браузер.
Лука
7
@Luke - смотрите ниже комментарий к Рейду. В общем, замечательно, но я не задаю общий вопрос безопасности. (Мои пользователи смогут проходить аутентификацию, только если они используют современный браузер.)
Rocketman
4
@ Люк, иногда нам нужно двигаться дальше и позволять нам развиваться с использованием современных шаблонов (таких как REST в данном случае: получение данных является операцией GET и не должно быть чем-то другим) без защиты от старых угроз, если теперь они кажутся применимыми только для небольшой аудитории. Таким образом, этот вопрос действительно ценен, чтобы дать возможность оценить, может ли он игнорировать эту угрозу или нет для его случая применения. В какой-то момент пользователи с очень устаревшим программным обеспечением могут столкнуться с угрозами другого типа (вредоносными программами), от которых мы все равно не сможем их защитить.
Фредерик
2
@jpaugh, где ты видишь такие предположения? Я лишь несколько предполагаю, что люди с таким устаревшим программным обеспечением в любом случае «незащищены». (Что касается оправдания стоимости моих коньков, я уже привык ставить одну треть их цены на углеродистые коньки, которые были изношены менее чем за треть времени, которое уходит на то, чтобы изнашивать мои нынешние коньки. И вообще, я думаю, что они того стоят, при условии, что вы любите на них кататься, а это мой случай.)
Frédéric

Ответы:

112

Нет, больше невозможно получить значения, переданные конструкторам []или {}в Firefox 21, Chrome 27 или IE 10. Вот небольшая тестовая страница, основанная на основных атаках, описанных в 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>

Он переопределяет window.Arrayи добавляет установщик Object.prototype.fooи проверяет инициализацию массивов и объектов с помощью коротких и длинных форм.

Спецификация ES4 , в разделе 1.5, «требует, чтобы глобальные стандартные привязки Object и Array использовались для создания новых объектов для инициализаторов объектов и массивов» и отмечает в Precedent реализации, что «Internet Explorer 6, Opera 9.20 и Safari 3 делают не уважать ни локальные, ни глобальные перепривязки Object и Array, но использовать оригинальные конструкторы Object и Array. " Это сохраняется в ES5, раздел 11.1.4 .

Аллен Уирфс-Брок объяснил, что ES5 также указывает, что инициализация объекта не должна вызывать сеттеры, поскольку она использует DefineOwnProperty. MDN: Работа с объектами отмечает, что «Начиная с JavaScript 1.8.1, сеттеры больше не вызываются при установке свойств в инициализаторах объектов и массивов». Это было решено в выпуске V8 1015 .

jpaugh
источник
28
Еще в 2009 году Брендан Айх предположил, что браузеры, не оценивающие сценарии, служат application / json ( bugzilla.mozilla.org/show_bug.cgi?id=376957#c75 ), что все еще кажется мне хорошей идеей.
2
Обратите внимание, что слепая POST CSRF все еще возможна при использовании форм, особенно с кодировкой text / plain, и должна быть побеждена с использованием токенов / одноразовых номеров.
1
Да, чтобы ПОСТ CSRF. Спасибо за всю вашу отличную информацию здесь.
Ракетчик
5
Ваше утверждение верно, когда оно относится только к простой перезаписи конструктора Array. Microsoft и Edge по-прежнему уязвимы для взлома JSON UTF-7. Протестировал это недавно (и для развлечения сегодня снова), и это все еще работает.
user857990
2
UTF-16BE также, благодаря Гарету Хейесу
угорь ghEEz