เหตุใด Google จึงเสริมขณะ (1) ตอบสนองต่อ JSON ของพวกเขา


4075

ทำไม Google เสริมwhile(1);ต่อการตอบสนอง JSON (ส่วนตัว) ของพวกเขา

ตัวอย่างเช่นต่อไปนี้เป็นการตอบสนองขณะเปิดและปิดปฏิทินในGoogle ปฏิทิน :

while (1);
[
  ['u', [
    ['smsSentFlag', 'false'],
    ['hideInvitations', 'false'],
    ['remindOnRespondedEventsOnly', 'true'],
    ['hideInvitations_remindOnRespondedEventsOnly', 'false_true'],
    ['Calendar ID stripped for privacy', 'false'],
    ['smsVerifiedFlag', 'true']
  ]]
]

ฉันจะสมมติว่านี่คือการป้องกันไม่ให้คนทำeval()มัน แต่สิ่งที่คุณต้องทำคือแทนที่มันwhileแล้วคุณจะถูกตั้งค่า ฉันจะสันนิษฐานการป้องกัน eval เพื่อให้แน่ใจว่าคนเขียนรหัสแยกปลอดภัย JSON

ฉันได้เห็นนี้ใช้ในคู่ของสถานที่อื่น ๆ ด้วย แต่มากขึ้นเพื่อให้กับ Google (จดหมายปฏิทิน, รายชื่อ, ฯลฯ ) แปลกพอGoogle Docsเริ่มต้นด้วยการ&&&START&&&แทนและ Google Contacts while(1); &&&START&&&ดูเหมือนว่าจะเริ่มต้นด้วย

เกิดอะไรขึ้นที่นี่?


45
ฉันเชื่อว่าความประทับใจแรกของคุณถูกต้อง หากคุณเริ่มมองหารหัสและพยายามที่จะตัดการสตรีมอินพุตขึ้นอยู่กับแหล่งที่มาคุณจะต้องพิจารณาอีกครั้งและดำเนินการอย่างปลอดภัย (และเนื่องจากการกระทำของ Google วิธีที่ง่ายขึ้น)
Esteban Küber

34
อาจจะเป็นคำถามที่ติดตาม: ทำไม google ย่อหน้า)]}'นี้แทนwhile(1);? คำตอบจะเหมือนกันหรือไม่
Gizmo

3
จะป้องกัน eval แต่ไม่ใช่ด้วยลูปที่ไม่สิ้นสุด
Mardoxx

9
นี้)]}'ก็อาจจะเป็นที่จะบันทึกไบต์เช่น Facebook ที่ใช้for(;;);ซึ่งจะช่วยประหยัดหนึ่งไบต์ :)
Gras ดับเบิล

3
Inorder เพื่อป้องกันการเปิดเผยข้อมูลของ json ieJSON hijacking
Ashraf.Shk786

คำตอบ:


4293

มันป้องกันการขโมย JSONซึ่งเป็นปัญหาด้านความปลอดภัย JSON ที่สำคัญซึ่งได้รับการแก้ไขอย่างเป็นทางการในเบราว์เซอร์หลักทั้งหมดตั้งแต่ปี 2011ด้วย ECMAScript 5

ตัวอย่างที่คาดหวัง: บอกว่า Google มี URL เช่นเดียวกับmail.google.com/json?action=inboxที่ส่งกลับ 50 ข้อความแรกของกล่องจดหมายของคุณในรูปแบบ JSON เว็บไซต์ที่ชั่วร้ายในโดเมนอื่นไม่สามารถร้องขอ AJAX เพื่อรับข้อมูลนี้เนื่องจากนโยบายกำเนิดเดียวกัน แต่สามารถรวม URL ผ่าน<script>แท็กได้ URL นั้นมีการเข้าชมด้วยคุกกี้ของคุณและโดยการแทนที่ตัวสร้างอาร์เรย์ทั่วโลกหรือวิธีการเข้าถึงพวกเขาสามารถมีวิธีการที่เรียกว่าเมื่อใดก็ตามที่มีการตั้งค่าแอตทริบิวต์วัตถุ (อาร์เรย์หรือแฮช) เพื่อให้พวกเขาอ่านเนื้อหา JSON

while(1);หรือ&&&BLAH&&&ป้องกันนี้: การร้องขอ AJAX ที่mail.google.comจะมีการเข้าถึงแบบเต็มไปยังเนื้อหาข้อความและสามารถดึงมันออกไป แต่การ<script>แทรกแท็กจะเรียกใช้ JavaScript โดยไม่ต้องดำเนินการใด ๆ ส่งผลให้เกิดการวนซ้ำไม่สิ้นสุดหรือข้อผิดพลาดทางไวยากรณ์

นี้ไม่ได้แก้ไขปัญหาของการข้ามไซต์ปลอมแปลงคำขอ


228
ทำไมคำร้องขอเพื่อรับข้อมูลนี้จึงไม่จำเป็นต้องมี CSRF-token แทน
Jakub P.

235
ทำงานfor(;;);เดียวกันหรือไม่? ฉันเคยเห็นสิ่งนี้ในการตอบสนองของ ajax ของ facebook
King Julien

183
@JakubP การจัดเก็บและบำรุงรักษาโทเค็น CSRF ในระดับของ Google ต้องมีโครงสร้างพื้นฐานและค่าใช้จ่ายจำนวนมาก
อับราฮัม

127
@JakubP anti-CSRF โทเค็นยุ่งกับการแคชและต้องใช้จำนวนของการประเมินผลการเข้ารหัสลับฝั่งเซิร์ฟเวอร์ ในระดับ Google นั้นจะต้องใช้ซีพียูจำนวนมาก การจัดเรียงนี้ offloads ไปยังลูกค้า
bluesmoon

96
ดูเหมือนว่าฉันจะมีวิธีที่ดีกว่าในการปล่อยให้เซิร์ฟเวอร์ส่ง JSON หากตั้งค่าส่วนหัวที่ถูกต้องเท่านั้น คุณสามารถทำได้ในการโทร AJAX แต่ไม่ใช่ด้วยแท็กสคริปต์ ด้วยวิธีนี้ข้อมูลที่ละเอียดอ่อนไม่เคยถูกส่งมาและคุณไม่จำเป็นต้องพึ่งพาการรักษาความปลอดภัยด้านเบราว์เซอร์
mcv

574

มันป้องกันการเปิดเผยการตอบสนองผ่าน JSON hijacking

ตามทฤษฎีแล้วเนื้อหาของการตอบกลับ HTTP ได้รับการคุ้มครองโดยนโยบายแหล่งกำเนิดเดียวกัน: หน้าจากโดเมนหนึ่งไม่สามารถรับข้อมูลส่วนใด ๆ จากหน้าในโดเมนอื่น (เว้นแต่จะได้รับอนุญาตอย่างชัดเจน)

ผู้โจมตีสามารถร้องขอหน้าเว็บในโดเมนอื่น ๆ ในนามของคุณเช่นโดยใช้<script src=...>หรือ<img>แท็ก แต่ไม่สามารถรับข้อมูลใด ๆ เกี่ยวกับผลลัพธ์ (ส่วนหัวเนื้อหา)

ดังนั้นหากคุณไปที่หน้าของผู้โจมตีมันจะไม่สามารถอ่านอีเมลของคุณจาก gmail.com

ยกเว้นว่าเมื่อใช้แท็กสคริปต์เพื่อร้องขอเนื้อหา JSON JSON จะถูกเรียกใช้เป็น Javascript ในสภาพแวดล้อมที่มีการควบคุมของผู้โจมตี หากผู้โจมตีสามารถแทนที่ Array หรือ Object Constructor หรือวิธีการอื่นที่ใช้ระหว่างการสร้างวัตถุสิ่งใดก็ตามใน JSON จะผ่านรหัสของผู้โจมตีและได้รับการเปิดเผย

โปรดทราบว่าสิ่งนี้เกิดขึ้นในเวลาที่ JSON ถูกเรียกใช้เป็น Javascript ไม่ใช่ตอนที่วิเคราะห์คำ

มีการตอบโต้หลายวิธี:

ตรวจสอบให้แน่ใจว่า JSON ไม่ดำเนินการ

โดยการวางwhile(1);คำสั่งก่อนข้อมูล JSON Google ทำให้แน่ใจว่าข้อมูล JSON ไม่เคยถูกเรียกใช้เป็น Javascript

เฉพาะหน้าเว็บที่ถูกต้องเท่านั้นที่จะได้รับเนื้อหาทั้งหมดถอดwhile(1);และแยกส่วนที่เหลือเป็น JSON

เช่นสิ่งที่for(;;);เคยเห็นที่ Facebook เช่นกับผลลัพธ์เดียวกัน

ตรวจสอบให้แน่ใจว่า JSON ไม่ใช่ Javascript ที่ถูกต้อง

ในทำนองเดียวกันการเพิ่มโทเค็นที่ไม่ถูกต้องก่อน JSON &&&START&&&จะต้องแน่ใจว่าไม่มีการดำเนินการใด ๆ

ส่งคืน JSON ด้วยวัตถุที่ด้านนอกเสมอ

วิธีนี้เป็นOWASPวิธีที่แนะนำในการป้องกันจากการจี้ JSON และเป็นการรบกวนน้อยกว่า

เช่นเดียวกับมาตรการตอบโต้ก่อนหน้านี้ตรวจสอบให้แน่ใจว่า JSON ไม่เคยดำเนินการเป็น Javascript

วัตถุ JSON ที่ถูกต้องเมื่อไม่ได้ใส่อะไรก็ไม่ถูกต้องใน Javascript:

eval('{"foo":"bar"}')
// SyntaxError: Unexpected token :

อย่างไรก็ตามนี่เป็น JSON ที่ถูกต้อง:

JSON.parse('{"foo":"bar"}')
// Object {foo: "bar"}

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

ตามที่บันทึกไว้โดย @hvd ในความคิดเห็นวัตถุที่ว่างเปล่า{}คือ Javascript ที่ถูกต้องและการรู้ว่าวัตถุนั้นว่างเปล่าอาจเป็นข้อมูลที่มีค่า

การเปรียบเทียบวิธีการข้างต้น

วิธี OWASP นั้นรบกวนน้อยกว่าเนื่องจากไม่ต้องการการเปลี่ยนแปลงไลบรารีไคลเอ็นต์และถ่ายโอน JSON ที่ถูกต้อง ไม่แน่ใจว่าข้อบกพร่องของเบราว์เซอร์ในอดีตหรือในอนาคตสามารถเอาชนะสิ่งนี้ได้หรือไม่ ดังที่บันทึกไว้โดย @oriadam มันไม่ชัดเจนว่าข้อมูลสามารถรั่วไหลในข้อผิดพลาดในการแยกวิเคราะห์ผ่านการจัดการข้อผิดพลาดหรือไม่ (เช่น window.onerror)

วิธีการของ Google ต้องการไลบรารี่ของไคลเอ็นต์เพื่อสนับสนุนการยกเลิกการทำให้เป็นอนุกรมโดยอัตโนมัติและถือว่าปลอดภัยยิ่งขึ้นเกี่ยวกับข้อบกพร่องของเบราว์เซอร์

ทั้งสองวิธีต้องการการเปลี่ยนแปลงฝั่งเซิร์ฟเวอร์เพื่อหลีกเลี่ยงนักพัฒนาจากการส่ง JSON ที่มีช่องโหว่


23
คำแนะนำ OWASP นั้นน่าสนใจเพราะความเรียบง่าย ใครรู้เหตุผลของวิธีที่ Google มีความปลอดภัยมากขึ้น?
funroll

18
ฉันเชื่อว่ามันไม่ปลอดภัยกว่า แต่อย่างใด การให้ OWASP ตรงนี้น่าจะเป็นเหตุผลที่ดีสำหรับ +1

30
มันอาจจะคุ้มค่าที่จะทราบว่าทำไมการส่งคืนวัตถุตามตัวอักษรจึงทำให้scriptแท็กหรือevalฟังก์ชั่นล้มเหลว เครื่องมือจัดฟัน{}สามารถตีความได้ว่าเป็นบล็อกรหัสหรือวัตถุตามตัวอักษรจาวาสคริปต์จะชอบก่อน แน่นอนว่ามันเป็นรหัสบล็อกที่ไม่ถูกต้อง ด้วยตรรกะนี้ฉันไม่สามารถเห็นการเปลี่ยนแปลงใด ๆ ที่คาดการณ์ได้ในพฤติกรรมของเบราว์เซอร์ในอนาคต
Manngo

16
รหัสที่ไม่ถูกต้องไม่เพียงพอเนื่องจากผู้โจมตีสามารถจี้ตัวจัดการสคริปต์ข้อผิดพลาดของเบราว์เซอร์ ( window.onerror) ฉันไม่แน่ใจว่าพฤติกรรมของonerrorข้อผิดพลาดทางไวยากรณ์คืออะไร ฉันเดาว่า Google ก็ไม่แน่ใจเช่นกัน
oriadam

12
"วัตถุ JSON ที่ถูกต้องเมื่อไม่มีสิ่งใดล้อมรอบไม่ถูกต้องใน Javascript:" - ยกเว้นกรณีเล็กน้อยของวัตถุว่างเปล่า ( {}) ซึ่งเป็นบล็อกว่างที่ถูกต้องเช่นกัน หากการรู้ว่าวัตถุนั้นว่างเปล่าอาจเป็นข้อมูลที่มีค่า

371

นี่คือเพื่อให้แน่ใจว่าเว็บไซต์อื่นไม่สามารถใช้กลอุบายที่น่ารังเกียจเพื่อพยายามขโมยข้อมูลของคุณ ตัวอย่างเช่นโดยการแทนที่ตัวสร้างอาร์เรย์จากนั้นรวมถึง JSON URL นี้ผ่านทาง<script>แท็กเว็บไซต์บุคคลที่สามที่เป็นอันตรายอาจขโมยข้อมูลจากการตอบสนอง JSON เมื่อวางwhile(1);จุดเริ่มต้นสคริปต์จะหยุดทำงานแทน

การร้องขอไซต์เดียวกันโดยใช้ XHR และตัวแยกวิเคราะห์ JSON แยกกันสามารถละเว้นwhile(1);คำนำหน้าได้อย่างง่ายดาย


6
ในทางเทคนิคตัวแยกวิเคราะห์ JSON "ปกติ" ควรให้ข้อผิดพลาดหากคุณมีคำนำหน้า
Matthew Crumley

12
ผู้โจมตีจะใช้<script>องค์ประกอบเก่าธรรมดาไม่ใช่ XHR
ลอเรน Gonsalves

9
@ แมทธิวแน่นอน แต่คุณสามารถลบมันออกก่อนที่จะส่งข้อมูลไปยังตัวแยกวิเคราะห์ JSON คุณไม่สามารถทำเช่นนั้นกับ<script>แท็ก
bdonlan

7
มีตัวอย่างอะไรบ้างไหม? การแทนที่ตัวสร้างอาร์เรย์จะถูกอ้างอิงอีกครั้ง แต่นั่นเป็นข้อผิดพลาดคงที่ ฉันไม่เข้าใจว่าจะเข้าถึงข้อมูลที่ได้รับผ่านแท็กสคริปต์ได้อย่างไร ฉันชอบที่จะเห็นการใช้หลอกตาซึ่งทำงานในเบราว์เซอร์ล่าสุด
Dennis G

7
@joeltine ไม่มันไม่ใช่ ดูstackoverflow.com/questions/16289894/...

111

นั่นจะทำให้เป็นการยากสำหรับบุคคลที่สามที่จะแทรกการตอบสนอง JSON ลงในเอกสาร HTML ด้วย<script>แท็ก โปรดจำไว้ว่า<script>แท็กได้รับการยกเว้นจากเดียวกันนโยบายแหล่งกำเนิดสินค้า


21
นี่เป็นคำตอบเพียงครึ่งเดียว หากไม่ใช่เพราะกลวิธีในการเอาชนะObjectและคอนArrayสตรัคเตอร์ให้เรียกใช้การตอบสนอง JSON ที่ถูกต้องราวกับว่าเป็น JavaScript จะไม่มีอันตรายใด ๆ ทั้งสิ้นในทุกสถานการณ์ ใช่การwhile(1);ป้องกันไม่ให้การตอบสนองถูกเรียกใช้เป็น JavaScript หากกำหนดเป้าหมายด้วย<script>แท็ก แต่คำตอบของคุณไม่ได้อธิบายว่าทำไมจึงจำเป็น
Mark Amery

แต่มันจะป้องกัน iframe ได้อย่างไร
Ravinder Payal

แท็กสคริปต์ไม่ได้รับการยกเว้นจากนโยบายต้นกำเนิดเดียวกัน คุณช่วยเคลียร์ให้ฉันได้ไหม
Suraj Jain

82

หมายเหตุ : ตั้งแต่ปี 2562 ช่องโหว่เก่า ๆ ที่นำไปสู่มาตรการป้องกันที่กล่าวถึงในคำถามนี้ไม่ได้เป็นปัญหาในเบราว์เซอร์สมัยใหม่อีกต่อไป ฉันจะปล่อยให้คำตอบด้านล่างเป็นความอยากรู้อยากเห็นทางประวัติศาสตร์ แต่จริงๆหัวข้อทั้งหมดมีการเปลี่ยนแปลงอย่างรุนแรงตั้งแต่ปี 2010 (!!) เมื่อถูกถาม


มันป้องกันไม่ให้ถูกใช้เป็นเป้าหมายของ<script>แท็กอย่างง่าย (มันไม่ได้ป้องกันมัน แต่ก็ทำให้มันไม่เป็นที่พอใจ) ด้วยเหตุนี้คนร้ายจึงไม่สามารถใส่แท็กสคริปต์นั้นในเว็บไซต์ของตนเองและพึ่งพาเซสชันที่ใช้งานอยู่เพื่อให้สามารถดึงเนื้อหาของคุณได้

แก้ไข - บันทึกความคิดเห็น (และคำตอบอื่น ๆ ) ปัญหาเกี่ยวข้องกับสิ่งอำนวยความสะดวกในตัวที่ถูกโค่นล้มโดยเฉพาะObjectและตัวArrayสร้าง สิ่งเหล่านี้สามารถเปลี่ยนแปลงได้เช่น JSON ที่ไม่เป็นอันตรายเมื่อวิเคราะห์คำสามารถเรียกใช้รหัสผู้โจมตีได้


17
นี่เป็นคำตอบเพียงครึ่งเดียว หากไม่ใช่เพราะกลวิธีในการเอาชนะObjectและคอนArrayสตรัคเตอร์ให้เรียกใช้การตอบสนอง JSON ที่ถูกต้องราวกับว่าเป็น JavaScript จะไม่มีอันตรายใด ๆ ทั้งสิ้นในทุกสถานการณ์ ใช่การwhile(1);ป้องกันไม่ให้การตอบสนองถูกเรียกใช้เป็น JavaScript หากกำหนดเป้าหมายด้วย<script>แท็ก แต่คำตอบของคุณไม่ได้อธิบายว่าทำไมจึงจำเป็น
Mark Amery

11

เนื่องจาก<script>แท็กได้รับการยกเว้นจากนโยบายแหล่งกำเนิดเดียวกันซึ่งเป็นสิ่งจำเป็นด้านความปลอดภัยในโลกเว็บwhile(1)เมื่อมีการเพิ่มลงในการตอบสนองของ JSON จะช่วยป้องกันการใช้ในทางที่ผิดใน<script>แท็ก


0

หลังจากมีการพิสูจน์ตัวตนแล้วการป้องกันการจี้ JSON สามารถมีหลายรูปแบบ Google ผนวกในขณะที่ (1)ลงในข้อมูล JSON ของพวกเขาดังนั้นหากสคริปต์ที่เป็นอันตรายใด ๆ ประเมินว่าสคริปต์ที่เป็นอันตรายเข้าสู่วงไม่สิ้นสุด

ข้อมูลอ้างอิง: ตำราการทดสอบความปลอดภัยของเว็บ: เทคนิคระบบเพื่อค้นหาปัญหาอย่างรวดเร็ว

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.