WebWorkers를 안전한 환경으로 만들기
Esailija 는 일반적인 yo-mama 농담만큼의 보안 구멍없이 브라우저 내에서 임의의 자바 스크립트 코드를 실행할 수있는 인터페이스를 갖기 위해 Web Workers 사용을 제안했습니다 . 세미 샌드 박스 환경 (DOM 액세스가없고 이미 브라우저 내부에 있음)에서 실행되며 사용자가 무한 루프에 넣을 수 없도록 죽일 수 있습니다.
그가 가져온 예는 다음과 같습니다. http://tuohiniemi.fi/~runeli/petka/workertest.html (콘솔 열기)
jsfiddle (Google 크롬 만 해당)
이제 이것은 좋은 해결책처럼 보입니다. 그러나 완전한 (또는 거의 다가오는) 것입니까? 명백한 누락이 있습니까?
봇에 연결되어 있기 때문에 전체 내용은 github : worker , evaluator 에서 찾을 수 있습니다.
본관:
workercode = "worker.js";
function makeWorkerExecuteSomeCode( code, callback ) {
var timeout;
code = code + "";
var worker = new Worker( workercode );
worker.addEventListener( "message", function(event) {
clearTimeout(timeout);
callback( event.data );
});
worker.postMessage({
code: code
});
timeout = window.setTimeout( function() {
callback( "Maximum execution time exceeded" );
worker.terminate();
}, 1000 );
}
makeWorkerExecuteSomeCode( '5 + 5', function(answer){
console.log( answer );
});
makeWorkerExecuteSomeCode( 'while(true);', function(answer){
console.log( answer );
});
var kertoma = 'function kertoma(n){return n === 1 ? 1 : n * kertoma(n-1)}; kertoma(15);';
makeWorkerExecuteSomeCode( kertoma, function(answer){
console.log( answer );
});
노동자:
var global = this;
/* Could possibly create some helper functions here so they are always available when executing code in chat?*/
/* Most extra functions could be possibly unsafe */
var wl = {
"self": 1,
"onmessage": 1,
"postMessage": 1,
"global": 1,
"wl": 1,
"eval": 1,
"Array": 1,
"Boolean": 1,
"Date": 1,
"Function": 1,
"Number" : 1,
"Object": 1,
"RegExp": 1,
"String": 1,
"Error": 1,
"EvalError": 1,
"RangeError": 1,
"ReferenceError": 1,
"SyntaxError": 1,
"TypeError": 1,
"URIError": 1,
"decodeURI": 1,
"decodeURIComponent": 1,
"encodeURI": 1,
"encodeURIComponent": 1,
"isFinite": 1,
"isNaN": 1,
"parseFloat": 1,
"parseInt": 1,
"Infinity": 1,
"JSON": 1,
"Math": 1,
"NaN": 1,
"undefined": 1
};
Object.getOwnPropertyNames( global ).forEach( function( prop ) {
if( !wl.hasOwnProperty( prop ) ) {
Object.defineProperty( global, prop, {
get : function() {
throw new Error( "Security Exception: cannot access "+prop);
return 1;
},
configurable : false
});
}
});
Object.getOwnPropertyNames( global.__proto__ ).forEach( function( prop ) {
if( !wl.hasOwnProperty( prop ) ) {
Object.defineProperty( global.__proto__, prop, {
get : function() {
throw new Error( "Security Exception: cannot access "+prop);
return 1;
},
configurable : false
});
}
});
onmessage = function( event ) {
"use strict";
var code = event.data.code;
var result;
try {
result = eval( '"use strict";\n'+code );
}
catch(e){
result = e.toString();
}
postMessage( "(" + typeof result + ")" + " " + result );
};
현재 코드 (아래에 나열 됨)는 현재 Stackoverflow 자바 스크립트 채팅방에서 잠시 동안 사용되었으며 지금까지 가장 어려운 문제는 Array(5000000000).join("adasdadadasd")
코드 실행기 봇을 실행할 때 일부 브라우저 탭 이 즉시 충돌하는 것이 었습니다. Monkeypatching은이 문제를 해결 한 Array.prototype.join
것으로 보이며 최대 실행 시간 인 50ms는 메모리를 잡아 먹거나 브라우저를 중단하려는 다른 시도에 대해 작동했습니다.
var global = this;
/* Could possibly create some helper functions here so they are always available when executing code in chat?*/
/* Most extra functions could be possibly unsafe */
var wl = {
"self": 1,
"onmessage": 1,
"postMessage": 1,
"global": 1,
"wl": 1,
"eval": 1,
"Array": 1,
"Boolean": 1,
"Date": 1,
"Function": 1,
"Number" : 1,
"Object": 1,
"RegExp": 1,
"String": 1,
"Error": 1,
"EvalError": 1,
"RangeError": 1,
"ReferenceError": 1,
"SyntaxError": 1,
"TypeError": 1,
"URIError": 1,
"decodeURI": 1,
"decodeURIComponent": 1,
"encodeURI": 1,
"encodeURIComponent": 1,
"isFinite": 1,
"isNaN": 1,
"parseFloat": 1,
"parseInt": 1,
"Infinity": 1,
"JSON": 1,
"Math": 1,
"NaN": 1,
"undefined": 1
};
Object.getOwnPropertyNames( global ).forEach( function( prop ) {
if( !wl.hasOwnProperty( prop ) ) {
Object.defineProperty( global, prop, {
get : function() {
throw "Security Exception: cannot access "+prop;
return 1;
},
configurable : false
});
}
});
Object.getOwnPropertyNames( global.__proto__ ).forEach( function( prop ) {
if( !wl.hasOwnProperty( prop ) ) {
Object.defineProperty( global.__proto__, prop, {
get : function() {
throw "Security Exception: cannot access "+prop;
return 1;
},
configurable : false
});
}
});
Object.defineProperty( Array.prototype, "join", {
writable: false,
configurable: false,
enumerable: false,
value: function(old){
return function(arg){
if( this.length > 500 || (arg && arg.length > 500 ) ) {
throw "Exception: too many items";
}
return old.apply( this, arguments );
};
}(Array.prototype.join)
});
(function(){
var cvalues = [];
var console = {
log: function(){
cvalues = cvalues.concat( [].slice.call( arguments ) );
}
};
function objToResult( obj ) {
var result = obj;
switch( typeof result ) {
case "string":
return '"' + result + '"';
break;
case "number":
case "boolean":
case "undefined":
case "null":
case "function":
return result + "";
break;
case "object":
if( !result ) {
return "null";
}
else if( result.constructor === Object || result.constructor === Array ) {
var type = ({}).toString.call( result );
var stringified;
try {
stringified = JSON.stringify(result);
}
catch(e) {
return ""+e;
}
return type + " " + stringified;
}
else {
return ({}).toString.call( result );
}
break;
}
}
onmessage = function( event ) {
"use strict";
var code = event.data.code;
var result;
try {
result = eval( '"use strict";\n'+code );
}
catch(e) {
postMessage( e.toString() );
return;
}
result = objToResult( result );
if( cvalues && cvalues.length ) {
result = result + cvalues.map( function( value, index ) {
return "Console log "+(index+1)+":" + objToResult(value);
}).join(" ");
}
postMessage( (""+result).substr(0,400) );
};
})();
현재 질문에 표시된 코드 (2014-11-07)는 표면 상 액세스를 허용하지 않음에도 불구하고 XMLHttpRequest
(허용 목록에 포함되지 않았기 때문에) 여전히 코드에 액세스 할 수 있도록 허용합니다.
If I put the code in the question (or the accepted answer) in a web page and worker combo and execute the following code on Chrome 38:
makeWorkerExecuteSomeCode('event.target.XMLHttpRequest', function (answer) { console.log( answer ); });
The result is:
function XMLHttpRequest() { [native code] }
However it does not work in FF. Bug in Chrome?
Another thing I found but which does not seem to lead very far down the rabit hole is reinstating console.log
. This works on FF 31 but not Chrome 38:
makeWorkerExecuteSomeCode(
'var c = self.__proto__.__proto__.__lookupGetter__("console").call(self); c.log("FOO");',
function (answer) { console.log(answer) });
This would log "FOO"
to the console without passing through the fake console.log
that the web worker provides. The code above uses self
, which can be blacklisted (by removing it from the whitelist) but this
and global
also work. I've found that attempts to blacklist global
fail on FF and Chrome: the worker dies with an error.
Note: Chrome refuses to blacklist Intl
so it has to be added to the whitelist for the code to run at all.
참고URL : https://stackoverflow.com/questions/10653809/making-webworkers-a-safe-environment
'IT박스' 카테고리의 다른 글
왜 컴파일 오류 "org / codehaus / groovy / control / CompilationFailedException"이 발생합니까? (0) | 2020.11.23 |
---|---|
Xcode 5 SpringBoard를 영구적으로 수정하는 방법은 오류로 인해 응용 프로그램을 시작하지 못했습니다 : -3 (0) | 2020.11.22 |
iOS iPad 키보드가 열리면 고정 위치가 끊어짐 (0) | 2020.11.22 |
Airflow에서 동적 워크 플로를 만드는 적절한 방법 (0) | 2020.11.22 |
* .csproj 프로젝트에서 BootstrapperPackage는 무엇을 의미합니까? (0) | 2020.11.22 |