web-dev-qa-db-fra.com

Sandbox en toute sécurité et exécuter JavaScript soumis par l'utilisateur?

Je voudrais avoir la possibilité de laisser les utilisateurs soumettre du code JavaScript arbitraire, qui est ensuite envoyé à un serveur Node.JS et exécuté en toute sécurité avant que la sortie ne soit renvoyée à plusieurs clients (au format JSON). La fonction eval me vient à l'esprit, mais je sais que cela pose de multiples problèmes de sécurité (le code soumis par l'utilisateur pourrait accéder à l'API de fichier de Node, etc.). J'ai vu des projets comme Microsoft Web Sandbox et Google Caja qui permettent l'exécution de balises et de scripts aseptisés (pour intégrer des publicités tierces sur des sites Web), mais il semble que ce soient des outils côté client et je ne suis pas sûr s'ils le peuvent être utilisé en toute sécurité dans Node.

Existe-t-il un moyen standard de sandboxer et d'exécuter du JavaScript non approuvé dans Node, en obtenant la sortie. Est-ce une erreur d'essayer de faire cela côté serveur?

EDIT: Il n'est pas important que l'utilisateur puisse exploiter toutes les capacités de JavaScript, en fait il serait préférable de pouvoir choisir lequel Des API seraient fournies au code utilisateur.

EDIT: Je vais continuer et mettre à jour ce que j'ai trouvé. Ce module Sandcastle ( bcoe/sandcastle ) semble viser à faire ce que j'ai en tête. Je ne sais pas à quel point c'est sûr, mais comme je n'ai rien de trop important, je pense que je vais l'essayer. J'ajouterai ma propre réponse si je réussis à le faire.

43
Cory Gross

Cette réponse est obsolète car gf3 ne fournit pas de protection contre la rupture du sandbox

http://gf3.github.io/sandbox/ - il utilise require('child_process') au lieu de require('vm').

4
Ginden

Vous pouvez utiliser la prise en charge du sandbox dans nodejs avec vm.runInContext ('code js', contexte), exemple dans la documentation de l'API:

https://nodejs.org/api/vm.html#vm_vm_runinthiscontext_code_options

const util = require('util');
const vm = require('vm');

const sandbox = { globalVar: 1 };
vm.createContext(sandbox);

for (var i = 0; i < 10; ++i) {
    vm.runInContext('globalVar *= 2;', sandbox);
}
console.log(util.inspect(sandbox));

// { globalVar: 1024 }

AVERTISSEMENT: comme indiqué par "s4y", il semble être défectueux. Veuillez regarder les commentaires.

10
ton

Sous Node.js, vous pouvez créer un processus enfant en bac à sable, mais vous devez également ajouter le code avec "use strict";, sinon il est possible de casser le bac à sable avec arguments.callee.caller.

Vous ne savez pas pourquoi vous devez l'envoyer au serveur, car le code peut également être exécuté dans un travailleur Web en bac à sable.

Jetez également un œil à ma bibliothèque Jailed qui simplifie tout ce qui vient d'être mentionné pour Node.js et le navigateur Web, et offre en outre la possibilité d'exporter un ensemble de fonctions dans le bac à sable.

4
asvd

Une alternative serait d'utiliser http://github.com/patriksimek/vm2 :

$ npm install vm2

puis:

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

vm.run(`1 + 1`);  // => 2

comme mentionné dans les commentaires des autres réponses.

Je ne sais pas à quel point il est sécurisé, mais il prétend au moins qu'il exécute le code non approuvé en toute sécurité (dans son fichier README). Et je n'ai trouvé aucun problème de sécurité évident dans la mesure où les solutions suggérées dans d'autres réponses ici.

4
Hiroshi Ichikawa

Selon votre utilisation, je vous suggère également d'envisager de protéger votre bac à sable avec un environnement virtuel comme gVisor. Vous pouvez trouver quelques informations ici .

0
Pål Thingbø