web-dev-qa-db-ja.com

JSONハイジャックは、最新のブラウザーではまだ問題ですか?

Backbone.jsとTornado Webサーバーを使用しています。 Backboneでコレクションデータを受信するための標準的な動作は、JSON配列として送信することです。

一方、Tornadoの標準的な動作では、次の脆弱性のためJSON配列を許可しません。

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がオブジェクトのリストである場合、JSONをオブジェクトにラップする必要がない方が自然です。

最新のブラウザ(つまり、現在のChrome、Firefox、Safari、およびIE9)でこれらの攻撃を再現できませんでした。同時に、最新のブラウザがこれらの問題に対処したことをどこにも確認できませんでした。

貧弱なプログラミングスキルや貧弱なグーグルスキルによって誤解されないようにするには:

これらのJSONハイジャック攻撃は、今日のブラウザでも今日の問題ですか?

(注:重複する可能性があるため申し訳ありません: 最新のブラウザで「JSONハイジャック」を行うことは可能ですか? もう一度、より明確な説明を入手してください。)

141
Rocketman

いいえ、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で、「オブジェクトと配列の初期化子の新しいオブジェクトを構築するために使用されるオブジェクトと配列のグローバルな標準バインディングが必要です」と「Internet Explorer 6 Opera 9.20、およびSafari 3は、ObjectおよびArrayのローカルまたはグローバルの再バインドを尊重しませんが、元のObjectおよびArrayコンストラクターを使用します。これは ES5、セクション11.1.4 で保持されます。

Allen Wirfs-Brockの説明 ES5では、DefineOwnPropertyを使用しているため、オブジェクトの初期化がセッターをトリガーしないように指定していることもあります。 MDN:オブジェクトの操作 「JavaScript 1.8.1以降では、オブジェクトおよび配列の初期化子でプロパティを設定するときにセッターが呼び出されなくなりました。」これは V8 issue 1015 で対処されました。

107
user69173