Vm2: Tidak kebal terhadap while(1){}

Dibuat pada 2 Jan 2019  ·  19Komentar  ·  Sumber: patriksimek/vm2

Kode berikut tidak akan habis waktu.

const {VM} = require('vm2');
new VM({timeout:1}).run(`
        function main(){
        while(1){}
    }
    new Proxy({}, {
        getPrototypeOf(t){
            global.main();
        }
    })`);
bug confirmed help wanted

Semua 19 komentar

Kemungkinan tidak ada solusi yang baik untuk ini. NodeJS adalah proses tunggal. perlindungan while(1){} memerlukan multi-proses agar pemeriksa tidak diblokir oleh while(1){}. Mungkin jika kita bisa menghidupkan kembali proyek SpiderNode.......

Ini disebabkan oleh pengujian Decontextify.value untuk prototipe objek tamu dengan instanceOf . Modul Node.js vm tentu saja kebal terhadap ini. Tambalan orang miskin mungkin ke backdoor Proxy sehingga kami dapat mendeteksi objek Proxy apa pun dari kotak pasir, tetapi pendekatan yang ideal adalah dengan tidak pernah mempercayai objek dan fungsi apa pun darinya dan memasukkan contextify.js ke dalam kotak pasir, menggunakan nilai primitif untuk berkomunikasi dan menangani referensi objek tamu.

Hanya untuk dilihat orang, tanpa browser menggunakan proses anak dan penyampaian pesan untuk berbicara dengan anak yang menjalankan kode yang tidak tepercaya. Ini sedikit tugas penyiapan, tetapi setelah selesai, Anda akan kebal terhadap serangan while(1){} . Sumbernya ada di sini .

Inti dari proyek ini tampaknya tidak menelurkan keseluruhan yang terpisah
proses OS. Kalau tidak, ada banyak solusi yang tersedia yang banyak
lebih aman.

Jika tidak, ada banyak solusi yang tersedia yang jauh lebih aman.

Yang mana? Saya tidak yakin ada alternatif yang lebih baik untuk VM2 di NodeJS, setidaknya tidak yang pernah saya lihat

Pengelola perpustakaan ini menunjuk ke alternatif ini dalam edisi #80:

https://github.com/laverdet/isolated-vm

Saya sendiri belum mencobanya.

Saya hanya menjalankan kode yang tidak dipercaya dalam proses anak. Tidak dapat mengambil risiko menjalankannya di instance V8 utama terutama ketika Anda tahu itu utas tunggal.

Masalah memanggil mesin V8 secara langsung adalah kurangnya modul impor. Dalam kasus saya, saya perlu mengimpor modul permintaan untuk mengizinkan operasi HTTP. Itu juga harus asinkron.

Saya menemukan vm2 + child_process kombinasi yang baik.

Hei,

saya dan @harelmo telah membuat perpustakaan di atas vm2 yang kebal terhadap while(1) {} .

Mirip dengan apa yang disebutkan tian-ma, tetapi kami menggunakan utas pekerja node.js alih-alih proses anak.

lihat di sini: https://www.npmjs.com/package/isolated-runtime dan beri tahu kami pendapat Anda :)

Solusi lain adalah dengan menonaktifkan Proxy di dalam kotak pasir, bukan?

const vm = new VM({
    sandbox: {
        Proxy: undefined
    },
    timeout: 100
});

Menggunakan Promise juga memungkinkan untuk menulis kode yang tidak pernah habis:

"use strict";
const {VM} = require('vm2');
const untrusted = '(' + function(){
    Promise.resolve().then(a=>{
        while(1){}
    });
}+')()';
try{
    console.log(new VM({timeout:10}).run(untrusted));
}catch(x){
    console.log(x);
}

Masalah di sini adalah .then akan mengantri fungsi yang akan dipanggil nanti dalam antrean microtask.
Untuk memperbaikinya, kita perlu menulis Promise.then & fungsi terkait kita sendiri atau menonaktifkan Promise.

Juga ini berfungsi:

const {VM} = require('vm2');

const script = '(' + function() {
    (async function x(){
        await {then: y=>y()};
        while(1){}
    })();
}+')()';

new VM({timeout:10}).run(script);

Jadi mengesampingkan Janji saja tidak akan berhasil.
Tidak tahu bagaimana cara memperbaikinya.

Sementara ini tetap terbuka, kami harus menambahkan klarifikasi ke README untuk memperingatkan pengguna potensial. Kerentanan ini memungkinkan seseorang untuk keluar dari kotak pasir dan dengan demikian mengalahkan tujuan perpustakaan.

Readme telah diperbarui https://github.com/patriksimek/vm2/commit/77f5265ab53b87864a312156ee62b1082787e9b0#diff -04c6e90faac2675aa89e2176d2eec7d8. Dan saya tidak tahu bagaimana ini dapat digunakan untuk keluar dari kotak pasir, Anda hanya dapat keluar dari kerangka waktu yang dimaksudkan untuk menjalankan skrip.

Mungkin ini harus menjadi masalahnya sendiri, tetapi mengapa NodeVM tidak mendukung "batas waktu"?

@crowder karena di NodeVM setTimeout, setInterval & setImmediate ada, akan mudah untuk menghindari batas waktu. Mungkin ada alasan lain juga, tapi saya tidak bekerja dengan NodeVM, hanya VM.

@XmiliaH tidak akan menerapkan batas waktu mencegah setidaknya dari loop tak terbatas yang tidak diinginkan?
Kombinasi while(true) + setTimeout yang berbahaya masih akan menjadi masalah tetapi loop tak terbatas sederhana yang tidak disengaja yang dilakukan secara tidak sengaja dapat ditangani dengan mendukung batas waktu

Kekhawatiran saya adalah bahwa NodeVM memungkinkan untuk meminta modul yang mungkin menjadi modul Host dan waktu habis saat mereka mengubah keadaan global mungkin buruk. Juga NodeVM mengembalikan modul dan pengguna kemungkinan besar akan memanggil fungsi yang diekspos oleh modul, namun batas waktu hanya akan berlaku untuk pemuatan modul dan bukan panggilan fungsi.
Jika Anda ingin memanggil fungsi dengan batas waktu, Anda bisa mengimplementasikannya sendiri seperti

function doWithTimeout(fn, timeout) {
    let ctx = CACHE.timeoutContext;
    let script = CACHE.timeoutScript;
    if (!ctx) {
        CACHE.timeoutContext = ctx = vm.createContext();
        CACHE.timeoutScript = script = new vm.Script('fn()', {
            filename: 'timeout_bridge.js',
            displayErrors: false
        });
    }
    ctx.fn = fn;
    try {
        return script.runInContext(ctx, {
            displayErrors: false,
            timeout
        });
    } finally {
        ctx.fn = null;
    }
}

Poin bagus @XmiliaH dan terima kasih untuk contohnya
Saya melihat contoh Anda menggunakan paket vm dan bukan vm2
Akan menyenangkan untuk dapat menggunakan vm2 dan masih dapat kehabisan waktu

@szydan Kode yang saya posting digunakan oleh VM2 untuk timeout VM. Jika NodeVM memiliki batas waktu juga, itu akan menggunakan fungsi yang sama.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat