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) ในเวลาเดียวกันฉันไม่สามารถยืนยันได้ทุกที่ว่าเบราว์เซอร์ที่ทันสมัยได้แก้ไขปัญหาเหล่านี้แล้ว

เพื่อให้แน่ใจว่าฉันเข้าใจผิดไม่ว่าจะเป็นทักษะการเขียนโปรแกรมที่ไม่ดีหรือทักษะ googling ที่ไม่ดี:

JSON Hijacking โจมตีเหล่านี้ยังคงมีปัญหาในเบราว์เซอร์ที่ทันสมัยหรือไม่?

(หมายเหตุ: ขออภัยในความซ้ำซ้อนที่อาจเกิดขึ้นกับ: เป็นไปได้ที่จะทำ 'JSON hijacking' ในเบราว์เซอร์สมัยใหม่หรือไม่ แต่เนื่องจากคำตอบที่ยอมรับดูเหมือนจะไม่ตอบคำถาม - ฉันคิดว่าถึงเวลาต้องถามอีกครั้ง .)


ใช้งาน eval ไหม เป็นไปได้เป็นอย่างอื่นไม่ถ้าไม่มีการเปลี่ยนแปลงหรือเปลี่ยนแปลงในวิธีการตอบสนองของกระดูกสันหลังแยกวิเคราะห์แล้วคุณควรจะปลอดภัย
Deeptechtons

10
โดยทั่วไปแล้วคุณไม่ควรเข้าใกล้ความปลอดภัยของเว็บด้วยสมมติฐานว่ามีบางคนกำลังใช้เบราว์เซอร์ "ทันสมัย"
ลุ

7
@Luke - ดูความคิดเห็นด้านล่างเพื่อเรด โดยทั่วไปจุดที่ดี - แต่ฉันไม่ถามคำถามเพื่อความปลอดภัย (ผู้ใช้ของฉันจะสามารถพิสูจน์ตัวตนได้หากพวกเขากำลังใช้เบราว์เซอร์ที่ทันสมัยในตอนแรก)
Rocketman

4
@ ลุคบางครั้งเราต้องดำเนินการต่อและอนุญาตให้เราพัฒนาด้วยรูปแบบที่ทันสมัย ​​(เช่น REST ในกรณีนี้: การรับข้อมูลเป็นการดำเนินการของ GET และไม่ควรเป็นอย่างอื่น) โดยไม่ต้องป้องกันภัยคุกคามเก่า ๆ ถึงผู้ชมกลุ่มเล็ก ดังนั้นคำถามนี้มีค่าจริง ๆ เพื่อให้คนหนึ่งประเมินว่าเขาสามารถเพิกเฉยต่อภัยคุกคามนี้หรือไม่สำหรับกรณีการสมัครของเขา ในบางจุดผู้ใช้ที่มีซอฟต์แวร์ล้าสมัยมีแนวโน้มว่าจะมีภัยคุกคามชนิดอื่น (มัลแวร์) ซึ่งเราจะไม่สามารถป้องกันได้
Frédéric

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 "ต้องใช้ทั่วโลกผูกมาตรฐานของวัตถุและอาเรย์ที่จะใช้ในการสร้างวัตถุใหม่สำหรับวัตถุและอาเรย์ initializers" และบันทึกในการดำเนินการก่อนหน้านี้ว่า "Internet Explorer 6, Opera 9.20 และ Safari 3 สิ่งที่ต้องทำ ไม่เคารพการทำวัตถุและอาร์เรย์ในระดับท้องถิ่นหรือระดับโลก แต่ใช้การสร้างวัตถุและอาร์เรย์แบบดั้งเดิม " นี้จะถูกเก็บไว้ในES5, 11.1.4

Allen Wirfs-Brock อธิบายว่า ES5 ยังระบุว่าการกำหนดค่าเริ่มต้นของวัตถุไม่ควรเรียก setters เนื่องจากใช้ DefineOwnProperty MDN: การทำงานกับวัตถุตั้งข้อสังเกตว่า "การเริ่มต้นใน JavaScript 1.8.1 จะไม่เรียกใช้ตัวตั้งค่าอีกต่อไปเมื่อตั้งค่าคุณสมบัติในวัตถุและอาร์เรย์เริ่มต้น" นี้ได้รับการแก้ไขในV8 ปัญหา 1015


28
ย้อนกลับไปในปี 2009 Brendan Eich แนะนำว่าเบราว์เซอร์ไม่ได้ประเมินสคริปต์ที่ทำหน้าที่เป็น application / json ( bugzilla.mozilla.org/show_bug.cgi?id=376957#c75 ) ซึ่งดูเหมือนว่าเป็นความคิดที่ดีสำหรับฉัน

2
โปรดทราบว่า blind POST CSRF ยังคงเป็นไปได้โดยใช้แบบฟอร์มโดยเฉพาะอย่างยิ่งกับการเข้ารหัสข้อความ / ธรรมดาและต้องพ่ายแพ้โดยใช้โทเค็น / nonces

1
ใช่กับ POST CSRF ขอบคุณสำหรับข้อมูลทั้งหมดของคุณที่นี่
Rocketman

5
คำสั่งของคุณถูกต้องเมื่ออ้างถึงเพียงเขียนทับตัวสร้าง Array Microsofts IE และ Edge ยังคงมีช่องโหว่ต่อ UTF-7 JSON Hijacking ทดสอบเมื่อเร็ว ๆ นี้ (และเพื่อความสนุกในวันนี้อีกครั้ง) และมันก็ยังใช้งานได้
user857990

2
UTF-16BE เช่นกันขอขอบคุณ Gareth Heyes, blog.portswigger.net/2016/11/json-hijacking-for-modern-web.html
eel ghEEz
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.