Mengapa Google menambahkan sementara (1); untuk respons JSON mereka?

4078

Mengapa Google menambahkan while(1);respons JSON (pribadi) mereka?

Misalnya, inilah respons saat menghidupkan dan mematikan kalender di Google Kalender :

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

Saya akan berasumsi ini untuk mencegah orang lain melakukan eval()hal itu, tetapi yang harus Anda lakukan adalah mengganti whiledan kemudian Anda akan ditetapkan. Saya akan mengasumsikan pencegahan eval adalah untuk memastikan orang menulis kode parsing JSON yang aman.

Saya pernah melihat ini digunakan di beberapa tempat lain, tetapi lebih dari itu dengan Google (Mail, Kalender, Kontak, dll.) Anehnya, Google Documents memulai &&&START&&&, dan Google Contacts tampaknya memulai dengan while(1); &&&START&&&.

Apa yang terjadi di sini?

Jess
sumber
45
Saya percaya bahwa kesan pertama Anda benar. Jika Anda mulai mencari kode dan mencoba memangkas aliran input tergantung pada sumbernya, Anda akan mempertimbangkan kembali dan melakukannya dengan cara yang aman (dan karena tindakan Google, lebih mudah).
Esteban Küber
34
mungkin pertanyaan lanjutan: Mengapa google prepend )]}'sekarang bukan while(1);? Apakah jawabannya sama?
Gizmo
3
Akan mencegah eval, tetapi tidak dengan loop tak terbatas.
Mardoxx
9
Ini )]}'mungkin juga untuk menyimpan byte, seperti facebook yang digunakan for(;;);yang menyimpan satu byte :)
Gras Double
3
Inorder untuk mencegah pengungkapan json yaituJSON hijacking
Ashraf.Shk786

Jawaban:

4293

Ini mencegah pembajakan JSON , masalah keamanan utama JSON yang secara resmi diperbaiki di semua browser utama sejak 2011 dengan ECMAScript 5.

Contoh buatan: misalkan Google memiliki URL seperti mail.google.com/json?action=inboxyang mengembalikan 50 pesan pertama dari kotak masuk Anda dalam format JSON. Situs web jahat di domain lain tidak dapat membuat permintaan AJAX untuk mendapatkan data ini karena kebijakan asal-sama, tetapi mereka dapat memasukkan URL melalui <script>tag. URL dikunjungi dengan cookie Anda , dan dengan mengganti metode array global atau metode accessor mereka dapat memiliki metode yang dipanggil setiap kali atribut objek (array atau hash) diatur, memungkinkan mereka untuk membaca konten JSON.

The while(1);atau &&&BLAH&&&mencegah ini: permintaan AJAX di mail.google.comakan memiliki akses penuh ke konten teks, dan dapat menghapusnya. Tetapi <script>penyisipan tag secara buta mengeksekusi JavaScript tanpa pemrosesan apa pun, menghasilkan salah satu infinite loop atau kesalahan sintaksis.

Ini tidak membahas masalah pemalsuan permintaan lintas situs .

rjh
sumber
228
Mengapa permintaan untuk mendapatkan data ini tidak memerlukan token CSRF?
Jakub P.
235
Apakah for(;;);melakukan pekerjaan yang sama? Saya telah melihat ini di respons ajax facebook.
Raja Julien
183
@ JakubP. Menyimpan dan memelihara token CSRF pada skala Google membutuhkan sejumlah besar infrastruktur dan biaya.
abraham
127
@ JakubP. token anti-CSRF mengacaukan caching, dan memerlukan sejumlah sisi server evaluasi kriptografis. Pada skala Google, itu akan membutuhkan banyak CPU. Ini semacam membongkar ke klien.
bluesmoon
96
Menurut saya cara yang lebih baik adalah membiarkan server hanya mengirim JSON jika header yang benar telah ditetapkan. Anda dapat melakukannya dalam panggilan AJAX, tetapi tidak dengan tag skrip. Dengan begitu, informasi sensitif bahkan tidak pernah dikirim, dan Anda tidak harus bergantung pada keamanan sisi browser.
mcv
574

Ini mencegah pengungkapan tanggapan melalui pembajakan JSON.

Secara teori, konten respons HTTP dilindungi oleh Kebijakan Asal Sama: halaman dari satu domain tidak dapat memperoleh informasi apa pun dari halaman di domain lain (kecuali diizinkan secara eksplisit).

Seorang penyerang dapat meminta halaman pada domain lain atas nama Anda, misalnya dengan menggunakan <script src=...>atau <img>tag, tetapi tidak bisa mendapatkan informasi tentang hasil (header, isi).

Jadi, jika Anda mengunjungi halaman penyerang, itu tidak dapat membaca email Anda dari gmail.com.

Kecuali bahwa ketika menggunakan tag skrip untuk meminta konten JSON, JSON dieksekusi sebagai Javascript di lingkungan yang dikontrol penyerang. Jika penyerang dapat mengganti Array atau Object constructor atau metode lain yang digunakan selama konstruksi objek, apa pun di JSON akan melewati kode penyerang, dan diungkapkan.

Perhatikan bahwa ini terjadi pada saat JSON dieksekusi sebagai Javascript, bukan pada saat diuraikan.

Ada beberapa penanggulangan:

Memastikan JSON tidak pernah dieksekusi

Dengan menempatkan while(1);pernyataan di depan data JSON, Google memastikan bahwa data JSON tidak pernah dieksekusi sebagai Javascript.

Hanya halaman yang sah yang bisa mendapatkan seluruh konten, menanggalkan while(1);, dan menguraikan sisanya sebagai JSON.

Hal-hal seperti for(;;);telah terlihat di Facebook misalnya, dengan hasil yang sama.

Memastikan JSON tidak Javascript yang valid

Demikian pula, menambahkan token yang tidak valid sebelum JSON, seperti &&&START&&&, memastikan bahwa itu tidak pernah dieksekusi.

Selalu kembalikan JSON dengan Objek di luar

Ini adalah OWASPcara yang disarankan untuk melindungi dari pembajakan JSON dan merupakan cara yang tidak terlalu mengganggu.

Mirip dengan langkah-langkah balasan sebelumnya, memastikan bahwa JSON tidak pernah dieksekusi sebagai Javascript.

Objek JSON yang valid, ketika tidak tertutup oleh apa pun, tidak valid dalam Javascript:

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

Namun ini adalah JSON yang valid:

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

Jadi, pastikan Anda selalu mengembalikan Objek di tingkat teratas dari respons, pastikan JSON tidak Javascript yang valid, sementara JSON masih valid.

Seperti dicatat oleh @hvd dalam komentar, objek kosong {}Javascript yang valid, dan mengetahui objek kosong itu sendiri dapat menjadi informasi berharga.

Perbandingan metode di atas

Cara OWASP kurang mengganggu, karena tidak memerlukan perubahan pustaka klien, dan transfer JSON yang valid. Tidak yakin apakah bug browser masa lalu atau masa depan dapat mengalahkan ini. Seperti dicatat oleh @oriadam, tidak jelas apakah data dapat bocor dalam kesalahan parse melalui penanganan kesalahan atau tidak (misalnya window.onerror).

Cara Google mengharuskan perpustakaan klien untuk mendukung de-serialisasi otomatis dan dapat dianggap lebih aman tentang bug browser.

Kedua metode ini membutuhkan perubahan sisi server untuk menghindari pengembang dari mengirimkan JSON rentan secara tidak sengaja.

Arnaud Le Blanc
sumber
23
Rekomendasi OWASP menarik karena kesederhanaannya. Adakah yang tahu alasan cara Google lebih aman?
funroll
18
Saya percaya itu tidak lebih aman dengan cara apa pun. Memberikan OWASP di sini tampaknya merupakan alasan yang cukup baik untuk +1.
30
Mungkin perlu dicatat mengapa mengembalikan objek literal gagal pada scripttag atau evalfungsinya. Kawat gigi {}dapat diartikan sebagai suatu blok kode atau objek literal, dan dengan sendirinya, JavaScript lebih memilih yang sebelumnya. Sebagai blok kode, tentu saja, tidak valid. Dengan logika ini, saya tidak dapat melihat perubahan yang dapat diperkirakan dalam perilaku browser di masa mendatang.
Manngo
16
Kode buruk tidak cukup karena penyerang juga dapat membajak script-error hander browser ( window.onerror) Saya tidak yakin apa perilaku onerrordengan kesalahan sintaks. Saya kira Google juga tidak yakin.
oriadam
12
"Objek JSON yang valid, ketika tidak tertutup oleh apa pun, tidak valid dalam Javascript:" - Kecuali untuk kasus sepele objek kosong ( {}), yang juga merupakan blok kosong yang valid. Jika mengetahui objek itu kosong itu sendiri mungkin informasi yang berharga, ini mungkin dapat dieksploitasi.
371

Ini untuk memastikan beberapa situs lain tidak dapat melakukan trik jahat untuk mencoba mencuri data Anda. Misalnya, dengan mengganti konstruktor array , lalu memasukkan URL JSON ini melalui <script>tag, situs pihak ketiga jahat dapat mencuri data dari respons JSON. Dengan meletakkan a while(1);di awal, skrip akan menggantung.

Permintaan situs yang sama menggunakan XHR dan parser JSON yang terpisah, di sisi lain, dapat dengan mudah mengabaikan while(1);awalan.

omong kosong
sumber
6
Secara teknis, parser JSON "normal" akan memberikan kesalahan jika Anda memiliki awalan.
Matthew Crumley
12
Penyerang hanya akan menggunakan <script>elemen tua biasa , bukan XHR.
Laurence Gonsalves
9
@ Matius, tentu, tapi Anda bisa menghapusnya sebelum meneruskan data ke parser JSON. Anda tidak dapat melakukannya dengan <script>tag
bdonlan
7
Apakah ada contohnya? Mengganti konstruktor array direferensikan lagi, tapi itu bug lama diperbaiki. Saya tidak mengerti bagaimana orang akan memiliki akses ke data yang diterima melalui tag skrip. Saya ingin melihat implementasi tiruan yang berfungsi di browser terbaru.
Dennis G
7
@ Joeltine, tidak, bukan itu. Lihat stackoverflow.com/questions/16289894/… .
111

Itu akan menyulitkan pihak ketiga untuk memasukkan respons JSON ke dalam dokumen HTML dengan <script>tag. Ingat bahwa <script>tag dibebaskan dari Kebijakan Same Origin .

Daniel Vassallo
sumber
21
Ini hanya setengah jawaban. Jika bukan karena trik menimpa Objectdan Arraykonstruktor, menjalankan respons JSON yang valid seolah-olah JavaScript akan benar-benar tidak berbahaya dalam semua keadaan. Ya, while(1);mencegah respons dieksekusi sebagai JavaScript jika ditargetkan oleh <script>tag, tetapi jawaban Anda tidak menjelaskan mengapa itu perlu.
Mark Amery
tapi bagaimana itu akan mencegah iframe
Ravinder Payal
Tag skrip tidak pernah dibebaskan dari kebijakan asal yang sama. Bisakah Anda membersihkannya untuk saya?
Suraj Jain
82

Catatan : pada 2019, banyak kerentanan lama yang mengarah ke tindakan pencegahan yang dibahas dalam pertanyaan ini tidak lagi menjadi masalah di browser modern. Saya akan meninggalkan jawaban di bawah ini sebagai keingintahuan historis, tetapi sebenarnya seluruh topik telah berubah secara radikal sejak 2010 (!!) ketika ditanya.


Ini mencegahnya digunakan sebagai target <script>tag sederhana . (Yah, itu tidak mencegahnya, tetapi membuatnya tidak menyenangkan.) Dengan begitu orang jahat tidak bisa hanya menaruh tag skrip itu di situs mereka sendiri dan mengandalkan sesi aktif untuk memungkinkannya mengambil konten Anda.

sunting - perhatikan komentar (dan jawaban lainnya). Masalahnya berkaitan dengan fasilitas built-in subvert, khususnya Objectdan Arraykonstruktor. Itu dapat diubah sedemikian rupa sehingga JSON yang tidak berbahaya, ketika diuraikan, dapat memicu kode penyerang.

Runcing
sumber
17
Ini hanya setengah jawaban. Jika bukan karena trik menimpa Objectdan Arraykonstruktor, menjalankan respons JSON yang valid seolah-olah JavaScript akan benar-benar tidak berbahaya dalam semua keadaan. Ya, while(1);mencegah respons dieksekusi sebagai JavaScript jika ditargetkan oleh <script>tag, tetapi jawaban Anda tidak menjelaskan mengapa itu perlu.
Mark Amery
11

Karena <script>tag dikecualikan dari Kebijakan Asal yang Sama yang merupakan kebutuhan keamanan di dunia web, while(1)ketika ditambahkan ke respons JSON mencegah penyalahgunaan di <script>tag.

Krishna Ganeriwal
sumber