Seberapa mudah meretas JavaScript (di browser)?

37

Pertanyaan saya berkaitan dengan keamanan JavaScript.

Bayangkan sebuah sistem otentikasi tempat Anda menggunakan kerangka kerja JavaScript seperti Backbone atau AngularJS , dan Anda membutuhkan titik akhir yang aman. Itu bukan masalah, karena server selalu memiliki kata terakhir dan akan memeriksa apakah Anda berwenang untuk melakukan apa yang Anda inginkan.

Tetapi bagaimana jika Anda membutuhkan sedikit keamanan tanpa melibatkan server? Apakah itu mungkin?

Misalnya, Anda memiliki sistem perutean sisi klien dan Anda ingin rute konkret dilindungi untuk pengguna yang masuk. Jadi Anda melakukan ping ke server menanyakan apakah Anda diizinkan untuk mengunjungi rute yang dilindungi dan Anda melanjutkan. Masalahnya adalah ketika Anda melakukan ping ke server, Anda menyimpan respons dalam sebuah variabel, jadi lain kali Anda pergi ke rute pribadi, itu akan memeriksa bahwa jika Anda sudah masuk (tidak ada ping ke server), dan tergantung pada respon itu akan pergi atau tidak.

Seberapa mudah bagi pengguna untuk memodifikasi variabel itu dan mendapatkan akses?

Pengetahuan keamanan (dan JavaScript) saya tidak bagus. Tetapi jika variabel tidak dalam lingkup global dan berada di bagian pribadi dari pola modul yang hanya memiliki getter tetapi tidak setter, bahkan dalam kasus itu, dapatkah Anda meretasnya?

Jesus Rodriguez
sumber
29
Semua jawaban panjang ini. Singkatnya, untuk menjawab tajuk Anda, "sangat bisa diretas". Untuk menjawab 2 pertanyaan pertama Anda sejajar satu sama lain, "tanpa server, Anda kehilangan keamanan" && "Tidak". Untuk menjawab yang ke-3, "Sangat mudah", dan akhirnya, "Ya, dengan mudah". Ini dia. Semua pertanyaan dijawab. : P
SpYk3HH
Contoh utama, lihat posting blog saya tentang menambahkan jQuery ke halaman web mana pun. spyk3lc.blogspot.com/2013/05/... Sekarang, padawan muda, maju dan cobalah. Lihat betapa mudahnya untuk menambahkan jQuery ke situs mana pun yang belum memilikinya, lalu gunakan jquery untuk dengan mudah memanipulasi bagian mana pun dari penglihatan tanpa garis panjang javascript. Ledakan!
SpYk3HH
7
Suatu ketika, ketika mendaftar untuk nama domain, nomor telepon adalah bidang yang wajib diisi, tetapi itu hanya diberlakukan dalam javascript - bukan sisi server. Jadi, saya menonaktifkannya dengan mendefinisikan kembali suatu fungsi (menggunakan Firebug), dan voilà! Mereka tidak memiliki nomor telepon saya.
Izkata
8
manipulate any part of the sight without long lines situs vs sight
mplungjan
8
Programmer web profesional perlu melakukan hal yang benar. Silahkan. Ini memalukan lebih dari sekadar tata bahasa nazi :) plus.google.com/u/0/+MonaNomura/posts/h9ywDhfEYxT
mplungjan

Jawaban:

26

Silakan baca jawaban Joachim sebelum membaca yang ini. Ia membahas alasan umum di balik kerentanan sisi klien. Sekarang, untuk saran bagaimana Anda bisa mengatasi masalah ini ...

Skema aman untuk komunikasi klien-server tanpa harus mengautentikasi dengan server secara manual pada setiap permintaan:

Anda masih membiarkan server mengatakan yang terakhir, dan server masih harus memvalidasi semua yang dikatakan klien, tetapi itu terjadi secara transparan.

Asumsikan protokol HTTPS untuk mencegah serangan man-in-the-middle (MITMA).

  • Jabat tangan klien dengan server untuk pertama kalinya, dan server menghasilkan kunci publik untuk klien dan menyimpan kunci pribadi menggunakan skema enkripsi asimetris. Klien menyimpan kunci "publik" server di penyimpanan lokal, dienkripsi dengan kata sandi aman yang tidak Anda simpan di mana pun.

  • Klien sekarang offline. Klien ingin melakukan tindakan tepercaya. Klien memasukkan kata sandi dan mengambil kunci publik server.

  • Klien sekarang melakukan tindakan berdasarkan pengetahuannya tentang data itu, dan klien mengenkripsi setiap tindakan yang dilakukannya dengan kunci publik server untuk klien itu .

  • Ketika klien sedang online, klien mengirimkan ID kliennya dan semua tindakan yang dilakukan klien dikirim ke server dienkripsi dengan kunci publik server.

  • Server mendekripsi tindakan, dan jika mereka dalam format yang benar percaya bahwa itu berasal dari klien.

catatan:

  • Anda tidak dapat menyimpan kata sandi klien di mana pun, jika tidak seorang penyerang akan dapat mengambil kunci dan menandatangani tindakan sebagai miliknya. Keamanan skema ini hanya bergantung pada integritas kunci yang dihasilkan server untuk klien. Klien masih perlu diautentikasi dengan server ketika meminta kunci itu.

  • Anda sebenarnya masih mengandalkan server untuk keamanan dan bukan klien. Setiap tindakan yang dilakukan klien Anda harus memvalidasi di server.

  • Dimungkinkan untuk menjalankan skrip eksternal pada pekerja web . Ingatlah bahwa setiap permintaan JSONP yang Anda miliki sekarang merupakan masalah keamanan yang jauh lebih besar. Anda harus melindungi kunci di semua biaya. Setelah Anda kehilangan itu, seorang penyerang dapat menyamar sebagai pengguna.

  • Ini memenuhi permintaan Anda bahwa 'tidak ada ping ke server' dilakukan. Seorang penyerang tidak bisa begitu saja meniru permintaan HTTP dengan data palsu jika mereka tidak tahu kuncinya.

  • Jawaban Joachim masih benar . Faktanya, Anda masih melakukan semua otentikasi di server . Satu-satunya hal yang Anda simpan di sini adalah perlunya validasi kata sandi dengan server setiap saat. Anda sekarang hanya perlu melibatkan server ketika Anda ingin melakukan, atau menarik data yang diperbarui. Yang kami lakukan di sini adalah menyimpan kunci tepercaya di sisi klien dan meminta klien untuk memvalidasinya kembali.

  • Ini adalah skema yang cukup umum untuk aplikasi satu halaman (misalnya, dengan AngularJS).

  • Saya menyebut kunci publik server "publik" karena apa artinya dalam skema seperti RSA , tetapi sebenarnya informasi sensitif dalam skema dan harus dilindungi.

  • Saya tidak akan menyimpan kata sandi di mana pun dalam memori. Saya akan membuat pengguna mengirimkan kata sandi 'offline' setiap kali dia mulai menjalankan kode offline.

  • Jangan memutar kriptografi Anda sendiri - gunakan perpustakaan yang dikenal seperti Stanford untuk otentikasi.

  • Terima nasihat ini apa adanya . Sebelum Anda memutar otentikasi semacam ini di aplikasi penting bisnis dunia nyata, berkonsultasilah dengan pakar keamanan . Ini adalah masalah serius yang menyakitkan dan mudah salah.

Sangat penting bahwa tidak ada skrip lain yang memiliki akses ke halaman. Ini berarti Anda hanya mengizinkan skrip eksternal dengan pekerja web. Anda tidak dapat mempercayai skrip eksternal lain yang mungkin memotong kata sandi Anda saat pengguna memasukkannya.

Gunakan bidang promptdan bukan bidang kata sandi sebaris jika Anda tidak sepenuhnya yakin dan tidak menunda pelaksanaannya (artinya, itu tidak boleh langsung sampai pada titik di mana acara memiliki akses ke sana tetapi hanya dalam kode sinkronisasi). Dan jangan benar-benar menyimpan kata sandi dalam variabel - sekali lagi, ini hanya berfungsi jika Anda percaya komputer pengguna tidak terganggu (meskipun itu semua berlaku untuk memvalidasi terhadap server juga).

Saya ingin menambahkan lagi bahwa kami masih tidak mempercayai klien . Anda tidak bisa mempercayai klien sendirian, dan saya pikir jawaban Joachim berhasil. Kami hanya memperoleh kemudahan karena tidak perlu melakukan ping server sebelum mulai bekerja.

Bahan terkait:

Benjamin Gruenbaum
sumber
3
"Jangan memutar crypto Anda sendiri" berlaku sama seperti protokol untuk primitif, jika tidak lebih, karena sementara orang biasanya tidak cukup bodoh untuk membuat primitif sendiri, mereka pikir mereka dapat membuat protokol yang baik-baik saja . Saya juga tidak melihat mengapa RSA diperlukan di sini. Karena Anda menggunakan HTTPS, mengapa tidak hanya menghasilkan rahasia bersama 16-32 byte dan mengharuskannya dikirim dengan permintaan di masa mendatang? Tentu saja, jika Anda melakukan ini, pastikan untuk menggunakan persamaan kesetaraan waktu-invarian pada string ...
Reid
2
+1 @ Reid Ya, saya baru saja berdiskusi tentang hal ini dengan seorang pakar tentang hal ini baru-baru ini. Saya kira-kira mendasarkan skema primitif di sini pada protokol yang saya pelajari (oleh Rabin IIRC) tetapi setidaknya sampai saya dapat menemukan spesifiknya (dan membenarkan misalnya mengapa enkripsi asimetris diperlukan dalam kasus ini). Jangan gunakan skema yang disarankan dalam jawaban ini tanpa berkonsultasi terlebih dahulu dengan pakar keamanan . Saya telah melihat pendekatan ini digunakan di beberapa tempat, tetapi dalam praktiknya itu berarti sangat sedikit, jika ada. Saya juga mengedit jawaban untuk meningkatkan itu.
Benjamin Gruenbaum
Menggunakan prompt menambah sedikit keamanan. Seorang penyerang dapat mengganti window.promptmetode untuk mencegat frase pass, atau meluncurkan prompt sendiri (mungkin dalam iframe!). Bidang kata sandi memiliki satu manfaat tambahan: karakter tidak ditampilkan.
Rob W
@RobW Tentu saja, seluruh skema ini tidak ada gunanya jika halamannya dikompromikan. Jika penyerang memiliki akses untuk menjalankan JavaScript di halaman kami kacau. Gagasan di balik prompt adalah bahwa itu memblokir tetapi Anda benar, manfaat keamanan yang diberikannya diragukan. Lihat tautan terakhir dalam daftar.
Benjamin Gruenbaum
1
Pertama-tama. Jawaban yang luar biasa, saya pikir saya tidak bisa meminta yang lain. Di sisi lain, saya ingin melakukan proyek hewan peliharaan untuk saya (dan tentu saja bagi yang ingin menggunakannya) dan mungkin ini berlebihan (atau mungkin tidak). Maksudku, aku ingin melakukan sesuatu yang serius dan aku takut aku tidak bisa menggulung auth seperti yang kau jelaskan, kurang pengetahuan. Saya pikir saya akan memutar 401 cek sederhana atau jika saya tidak memiliki permintaan, saya hanya melakukan ping server setiap kali saya mengakses rute semacam itu. Token auth juga merupakan opsi (dan mungkin hal terdekat yang terkait dengan apa yang Anda jelaskan di sini AFAIK). Terima kasih :)
Jesus Rodriguez
89

Sederhana: mekanisme keamanan apa pun yang bergantung pada klien untuk melakukan apa yang Anda suruh dapat dikompromikan ketika penyerang memiliki kendali atas klien.

Anda dapat memiliki pemeriksaan keamanan pada klien, tetapi hanya untuk secara efektif bertindak sebagai "cache" (untuk menghindari melakukan perjalanan pulang pergi yang mahal ke server jika klien sudah tahu bahwa jawabannya akan "tidak").

Jika Anda ingin menyimpan informasi dari sekelompok pengguna, pastikan bahwa klien pengguna itu tidak pernah mendapatkan informasi itu. Jika Anda mengirim "data rahasia" itu bersama dengan instruksi "tapi tolong jangan tampilkan," itu akan menjadi sepele untuk menonaktifkan kode yang memeriksa permintaan itu.

Seperti yang Anda lihat, jawaban ini tidak benar-benar menyebutkan spesifik JavaScript / Browser. Itu karena konsep ini sama, tidak peduli apa pun klien Anda. Tidak masalah apakah itu klien yang gemuk (aplikasi klien / server tradisional), aplikasi web sekolah lama, atau aplikasi satu halaman dengan JavaScript sisi klien yang luas.

Setelah data Anda meninggalkan server, Anda harus mengasumsikan bahwa penyerang memiliki akses penuh ke sana.

Joachim Sauer
sumber
Terima kasih. Akan menyenangkan jika Anda dapat menjelaskannya sedikit lagi, pengetahuan keamanan saya tidak begitu baik dan satu-satunya bagian yang saya mengerti adalah bahwa saya salah: P. Ketika Anda berbicara tentang caching, itu hanya untuk cache ketika server mengatakan tidak? Maksud saya, jika server mengatakan ya sekali, Anda tidak bisa men-cache itu, kan?
Jesus Rodriguez
3
Saya akan seperti untuk menambahkan bahwa adalah mungkin untuk variabel akses penutupan di browser (seperti dalam pola modul Anda disebutkan), terutama dengan debugger :)
Benjamin Gruenbaum
2
@BenjaminGruenbaum: merasa bebas untuk memperluas itu menjadi jawaban yang berfokus pada sisi JS-hal. Saya hanya memberikan ikhtisar agnostik tingkat tinggi di sini. Jawaban yang berfokus pada JS itu sendiri akan menyenangkan juga!
Joachim Sauer
1
Jadi singkatnya, jika beberapa informasi / rute / apa pun yang dapat diakses tergantung pada variabel javascript, itu tidak akan aman dalam hal apa pun karena Anda dapat dengan mudah mengubah variabel itu untuk mengatakan apa yang Anda butuhkan untuk mengakses barang-barang pribadi itu.
Jesus Rodriguez
4
@ JoachimSauer Saya pikir itu akan melewatkan inti dari pertanyaan ini yang Anda paku dengan baik. Apa pun tindakan keamanan yang diambil klien, mungkin saja kompromi komunikasi . Anda dapat membuat sistem otentikasi yang sangat solid dalam JavaScript, tetapi tidak ada gunanya begitu Anda memasukkan komunikasi ke server yang diperlakukan oleh klien lain sebagai sumber kebenaran juga. Semua kode sumber dikirim ke sisi klien, penyerang pintar bisa membacanya, dan meniru permintaan HTTP ke server. Seseorang harus memperlakukan apa pun yang berasal dari klien sebagai tidak dapat dipercaya kecuali divalidasi di server.
Benjamin Gruenbaum
10

Ada pepatah di komunitas game: " Klien ada di tangan musuh". Kode apa pun yang berjalan di luar area aman seperti server rentan. Dalam skenario paling dasar, rentan untuk tidak dijalankan di tempat pertama. Keputusan klien untuk benar-benar menjalankan" kode keamanan "Anda dan pengguna dapat hanya "memilih keluar". Sementara dengan kode asli Anda memiliki setidaknya kebingungan otomatis ke dalam perakitan dan lapisan perlindungan tambahan oleh fakta bahwa penyerang harus menjadi programmer yang baik untuk memanipulasi itu, JS biasanya tidak terganggu dan sebagai teks biasa. Yang Anda butuhkan untuk melakukan serangan adalah alat primitif seperti server proxy dan editor teks. Penyerang masih membutuhkan tingkat pendidikan tertentu mengenai pemrograman, tetapi cara memodifikasi script menggunakan texteditor lebih mudah daripada memasukkan kode ke dalam executable.

tidak ada
sumber
Assembly bukanlah kebingungan, dan yang meyakini sebaliknya tidak pernah memainkan wargame
miniBill
@miniBill: Sementara penyerang yang cukup berpengalaman tidak akan mengalami masalah dengan kode rakitan, itu akan memberikan filter high-pass yang sangat dasar. (Sayangnya, ini bersifat akademis, saat menyingkirkan skrip kiddies memberikan peningkatan minimal keamanan untuk skenario OP)
Piskvor
1

Ini bukan pertanyaan tentang peretasan JavaScript. Jika saya ingin menyerang aplikasi Anda, saya akan menggunakan proxy pribadi yang memungkinkan saya untuk menangkap, memodifikasi, dan memutar ulang lalu lintas. Skema keamanan yang Anda usulkan tampaknya tidak memiliki perlindungan terhadap hal itu.

Mark E. Haase
sumber
0

Secara khusus berbicara tentang Angular:

Melindungi sisi klien rute tidak ada. Sekalipun Anda 'menyembunyikan' tombol untuk rute itu, pengguna selalu dapat mengetiknya, Angular akan mengeluh, tetapi klien dapat mengkodekannya.

Pada titik tertentu pengontrol Anda harus meminta server Anda data yang diperlukan untuk membuat tampilan, jika pengguna tidak berwenang untuk mengakses data itu, mereka tidak akan menerimanya karena Anda telah melindungi data ini di sisi server , dan aplikasi Angular Anda harus menangani 401 dengan tepat.

Jika Anda mencoba melindungi data mentah, Anda tidak dapat sisi klien, jika Anda hanya ingin pengguna tertentu hanya dapat melihat data umum dengan cara tertentu, buat data 'tampilan' pada server daripada mengirim mentah data ke klien dan memilikinya mengatur ulang (Anda harus sudah melakukan ini karena alasan kinerja).

Catatan: seharusnya tidak ada sesuatu yang sensitif yang dibangun ke tampilan templat yang diminta Angular, tapi jangan lakukan itu. Jika karena alasan gila, Anda perlu melindungi template tampilan tersebut di sisi server, sama seperti yang Anda lakukan jika Anda melakukan rendering sisi server.

Menandai
sumber