Saya bertanya-tanya apakah mungkin untuk menjalankan JavaScript di browser untuk mencegah akses ke fitur yang biasanya tersedia untuk kode JavaScript yang berjalan di halaman HTML.
Sebagai contoh, katakanlah saya ingin memberikan API JavaScript untuk pengguna akhir agar mereka menentukan penangan acara yang akan dijalankan ketika "peristiwa menarik" terjadi, tetapi saya tidak ingin pengguna tersebut mengakses properti dan fungsi window
objek. Apakah saya dapat melakukan ini?
Dalam kasus paling sederhana, katakanlah saya ingin mencegah panggilan pengguna alert
. Beberapa pendekatan yang dapat saya pikirkan adalah:
- Definisikan ulang
window.alert
secara global. Saya tidak berpikir ini akan menjadi pendekatan yang valid karena kode lain yang berjalan di halaman (yaitu hal-hal yang tidak ditulis oleh pengguna dalam event handler mereka) mungkin ingin digunakanalert
. - Kirim kode event handler ke server untuk diproses. Saya tidak yakin bahwa mengirim kode ke server untuk diproses adalah pendekatan yang tepat karena penangan acara harus berjalan dalam konteks halaman.
Mungkin solusi di mana server memproses fungsi yang ditentukan pengguna dan kemudian menghasilkan panggilan balik yang akan dijalankan pada klien akan bekerja? Bahkan jika pendekatan itu berhasil, adakah cara yang lebih baik untuk menyelesaikan masalah ini?
sumber
while (1) {}
--- itu hanya hang. Demikian jugaa=[]; while (1) { a=[a,a]; }
.Lihatlah Douglas Crockford's ADsafe :
Anda dapat melihat contoh cara menggunakan ADsafe dengan melihat
template.html
dantemplate.js
file dalam repositori GitHub proyek .sumber
this
, yang sepenuhnya tidak dapat diterima. Anda tidak dapat menulis javascript yang baik tanpa menggunakanthis
.this
. Tidak sulit untuk menghindari parameter dengan nama buruk.this
, ada cara yang setara dan setarathis
untuk melakukannya (itu hanya parameter, setelah semua).Saya membuat perpustakaan sandboxing yang disebut jsandbox yang menggunakan pekerja web untuk sandbox kode dievaluasi. Ini juga memiliki metode input untuk secara eksplisit memberikan data kode sandbox yang tidak bisa didapatkan.
Berikut ini adalah contoh dari API:
sumber
Saya pikir js.js layak disebutkan di sini. Ini adalah penerjemah JavaScript yang ditulis dalam JavaScript.
Itu sekitar 200 kali lebih lambat dari JS asli, tetapi sifatnya membuatnya menjadi lingkungan kotak pasir yang sempurna. Kelemahan lain adalah ukurannya - hampir 600 kb, yang mungkin dapat diterima untuk desktop dalam beberapa kasus, tetapi tidak untuk perangkat seluler.
sumber
Seperti disebutkan dalam respons lain, cukup mem-jailed kode di iframe kotak pasir (tanpa mengirimnya ke sisi server) dan berkomunikasi dengan pesan. Saya akan menyarankan untuk melihat perpustakaan kecil yang saya buat sebagian besar karena kebutuhan untuk menyediakan beberapa API untuk kode yang tidak dipercaya, seperti yang dijelaskan dalam pertanyaan: ada peluang untuk mengekspor set fungsi tertentu langsung ke kotak pasir di mana kode yang tidak dipercaya berjalan. Dan ada juga demo yang mengeksekusi kode yang dikirimkan oleh pengguna di kotak pasir:
http://asvd.github.io/jailed/demos/web/console/
sumber
Semua vendor browser dan spesifikasi HTML5 sedang bekerja menuju properti kotak pasir yang sebenarnya untuk memungkinkan iframe kotak pasir - tetapi itu masih terbatas pada rincian granularitas iframe.
Secara umum, tidak ada derajat ekspresi reguler, dll. Dapat dengan aman membersihkan pengguna sewenang-wenang yang disediakan JavaScript karena merosot ke masalah penghentian: - /
sumber
Versi yang ditingkatkan dari kode sandbox pekerja web @ RyanOHara, dalam satu file (tidak
eval.js
diperlukan file tambahan ).Menguji:
https://jsfiddle.net/kp0cq6yw/
Seharusnya keluaran
6
(diuji di Chrome dan Firefox).sumber
Cara yang jelek tapi mungkin ini bekerja untuk Anda, saya mengambil semua global dan mendefinisikannya kembali di ruang pasir, juga saya menambahkan mode ketat sehingga mereka tidak bisa mendapatkan objek global menggunakan fungsi anonim.
https://gist.github.com/alejandrolechuga/9381781
sumber
window
kembali dari itu.sandboxcode('console.log((0,eval)("this"))')
function sbx(s,p) {e = eval; eval = function(t){console.log("GOT GOOD")}; sandboxcode(s,p); eval =e}
(_=>_).constructor('return this')()
Interpreter Javascript independen lebih mungkin menghasilkan kotak pasir yang kuat daripada versi yang dikurung dari implementasi browser bawaan. Ryan sudah menyebutkan js.js , tetapi proyek yang lebih mutakhir adalah JS-Interpreter . The docs mencakup bagaimana untuk mengekspos berbagai fungsi untuk interpreter, tetapi ruang lingkup dinyatakan sangat terbatas.
sumber
Pada 2019, vm2 sepertinya solusi yang paling populer dan paling sering diperbarui untuk masalah ini.
sumber
Dengan NISP Anda akan dapat melakukan evaluasi kotak pasir. Meskipun ekspresi yang Anda tulis bukanlah JS, namun Anda akan menulis ekspresi-s. Ideal untuk DSL sederhana yang tidak membutuhkan pemrograman yang luas.
sumber
1) Misalkan Anda memiliki kode untuk dieksekusi:
Sekarang, misalkan Anda ingin menjalankannya di kotak pasir:
Dua baris ini ketika dieksekusi akan gagal, karena fungsi "peringatan" tidak tersedia dari "kotak pasir"
2) Dan sekarang Anda ingin mengekspos anggota objek jendela dengan fungsionalitas Anda:
Memang Anda bisa menambahkan tanda kutip yang keluar dan membuat pemolesan lainnya, tapi saya rasa idenya jelas.
sumber
Dari mana asal pengguna JavaScript ini?
Tidak banyak yang dapat Anda lakukan tentang pengguna memasukkan kode ke halaman Anda dan kemudian memanggilnya dari browser mereka (lihat Greasemonkey, http://www.greasespot.net/ ). Itu hanya sesuatu yang dilakukan browser.
Namun, jika Anda menyimpan skrip dalam database, lalu mengambilnya dan eval (), maka Anda dapat membersihkan skrip sebelum dijalankan.
Contoh kode yang menghapus semua jendela. dan mendokumentasikan. referensi:
Ini mencoba untuk mencegah eksekusi berikut (tidak diuji):
Ada banyak batasan yang harus Anda terapkan pada skrip pengguna yang tidak aman. Sayangnya, tidak ada 'wadah kotak pasir' yang tersedia untuk JavaScript.
sumber
Saya telah mengerjakan kotak pasir js sederhana untuk membiarkan pengguna membuat applet untuk situs saya. Walaupun saya masih menghadapi beberapa tantangan dengan mengizinkan akses DOM (parentNode tidak akan membiarkan saya menjaga semuanya tetap aman = /), pendekatan saya hanya untuk mendefinisikan ulang objek jendela dengan beberapa anggota yang berguna / tidak berbahaya, dan kemudian mengevaluasi () pengguna kode dengan jendela yang didefinisikan ulang ini sebagai ruang lingkup default.
Kode "inti" saya seperti ini ... (Saya tidak menunjukkannya sepenuhnya;)
Jadi, saya dapat membuat instance Sandbox dan menggunakan executnya () untuk menjalankan kode. Juga, semua variabel yang dideklarasikan baru dalam kode yang dievalisasi pada akhirnya akan terikat pada lingkup execut (), sehingga tidak akan ada nama yang berbenturan atau mengacaukan kode yang ada.
Meskipun objek global masih dapat diakses, objek yang seharusnya tidak diketahui oleh kode sandboxed harus didefinisikan sebagai proksi dalam objek Sandbox :: scope.
Semoga ini berhasil untuk Anda.
sumber
Anda bisa membungkus kode pengguna dalam fungsi yang mendefinisikan ulang objek terlarang sebagai parameter - ini akan
undefined
ketika dipanggil:Tentu saja, penyerang yang pandai dapat menyiasatinya dengan memeriksa DOM Javascript dan menemukan objek yang tidak ditimpa yang berisi referensi ke jendela.
Gagasan lain adalah memindai kode pengguna menggunakan alat seperti jslint . Pastikan itu diatur untuk tidak memiliki variabel yang telah ditetapkan (atau: hanya variabel yang Anda inginkan), dan kemudian jika ada global ditetapkan atau diakses jangan biarkan skrip pengguna digunakan. Sekali lagi, mungkin rentan untuk berjalan DOM - objek yang dapat dibangun pengguna menggunakan literal mungkin memiliki referensi implisit ke objek jendela yang dapat diakses untuk keluar dari kotak pasir.
sumber