브라우저에서 실행되는 자바스크립트 샌드박스가 가능합니까?
HTML 페이지에서 실행되는 자바스크립트 코드에 보통 사용 가능한 기능에 접근하지 못하도록 브라우저에서 실행되는 자바스크립트를 샌드박스할 수 있는지 궁금합니다.
를 들어,에게 자바스크립트 API를 하여 "가 할 때 할 수 가 않았으면. API 를하여 "" , 를 합니다.window물건. 나 수 요?제가 할 수 있을까요?
가장 가 , 를 하는 것을 alert할 수 몇 은 다음과 같습니다 제가 생각할 수 있는 몇 가지 접근 방법은 다음과 같습니다.
-
window.alert세계적으로 페이지에서인 다른 핸들러의 것)가 페이지에서 실행 중인 다른 코드(즉, 이벤트 핸들러의 사용자가 작성하지 않은 것) 를 사용할 수 있기 때문에 이 접근 방식이 유효하지 않을 것으로 생각합니다를 사용하고 수 에 이 접근 하지 않을alert. - 처리할 서버에 이벤트 핸들러 코드를 보냅니다.이벤트 핸들러를 페이지의 컨텍스트에서 실행해야 하므로 처리할 코드를 서버로 전송하는 것이 올바른 방법인지 잘 모르겠습니다.
서버가 사용자가 정의한 기능을 처리한 다음 클라이언트에서 실행할 콜백을 생성하는 솔루션이 효과적일까요?그 방법이 효과가 있다 하더라도 이 문제를 해결할 더 나은 방법이 있습니까?
Google Caja는 "신뢰할 수 없는 타사 HTML 및 JavaScript를 페이지에 인라인으로 배치하고 여전히 안전하게 유지할 수 있도록 해주는" 소스-소스 간 번역기입니다.
Douglas Crockford의 ADsafe를 보십시오.
ADsafe를 사용하면 웹 페이지에 게스트 코드(예: 타사 스크립트 광고 또는 위젯)를 안전하게 넣을 수 있습니다.ADsafe는 게스트 코드가 가치 있는 상호 작용을 수행할 수 있도록 하는 동시에 악의적이거나 우발적인 손상이나 침입을 방지할 수 있을 정도로 강력한 JavaScript의 하위 집합을 정의합니다.ADsafe 서브셋은 JSlint와 같은 도구를 통해 기계적으로 확인할 수 있으므로 안전을 위해 게스트 코드를 검토하기 위해 사람이 검사할 필요가 없습니다.또한 ADsafe 서브셋은 우수한 코딩 방식을 적용하여 게스트 코드가 올바르게 실행될 가능성을 높입니다.
은 ADsafe 를를 를 볼 수 .template.html그리고.template.js프로젝트의 GitHub 저장소에 있는 파일들.
웹 워커를 이용하여 평가된 코드를 샌드박스하는 jsandbox라는 샌드박스 라이브러리를 만들었습니다.또한 샌드박스화된 코드 데이터를 명시적으로 제공하는 입력 방법을 가지고 있습니다.
다음은 API의 예입니다.
jsandbox
.eval({
code : "x=1;Math.round(Math.pow(input, ++x))",
input : 36.565010597564445,
callback: function(n) {
console.log("number: ", n); // number: 1337
}
}).eval({
code : "][];.]\\ (*# ($(! ~",
onerror: function(ex) {
console.log("syntax error: ", ex); // syntax error: [error object]
}
}).eval({
code : '"foo"+input',
input : "bar",
callback: function(str) {
console.log("string: ", str); // string: foobar
}
}).eval({
code : "({q:1, w:2})",
callback: function(obj) {
console.log("object: ", obj); // object: object q=1 w=2
}
}).eval({
code : "[1, 2, 3].concat(input)",
input : [4, 5, 6],
callback: function(arr) {
console.log("array: ", arr); // array: [1, 2, 3, 4, 5, 6]
}
}).eval({
code : "function x(z){this.y=z;};new x(input)",
input : 4,
callback: function(x) {
console.log("new x: ", x); // new x: object y=4
}
});
RyanOHARA의 웹 워커 샌드박스 코드를 단일 파일로 개선한 버전(추가 파일 없음)eval.js파일이 필요합니다).
function safeEval(untrustedCode)
{
return new Promise(function (resolve, reject)
{
var blobURL = URL.createObjectURL(new Blob([
"(",
function ()
{
var _postMessage = postMessage;
var _addEventListener = addEventListener;
(function (obj)
{
"use strict";
var current = obj;
var keepProperties =
[
// Required
'Object', 'Function', 'Infinity', 'NaN', 'undefined', 'caches', 'TEMPORARY', 'PERSISTENT',
// Optional, but trivial to get back
'Array', 'Boolean', 'Number', 'String', 'Symbol',
// Optional
'Map', 'Math', 'Set',
];
do
{
Object.getOwnPropertyNames(current).forEach(function (name)
{
if (keepProperties.indexOf(name) === -1)
{
delete current[name];
}
});
current = Object.getPrototypeOf(current);
}
while (current !== Object.prototype)
;
})(this);
_addEventListener("message", function (e)
{
var f = new Function("", "return (" + e.data + "\n);");
_postMessage(f());
});
}.toString(),
")()"],
{type: "application/javascript"}));
var worker = new Worker(blobURL);
URL.revokeObjectURL(blobURL);
worker.onmessage = function (evt)
{
worker.terminate();
resolve(evt.data);
};
worker.onerror = function (evt)
{
reject(new Error(evt.message));
};
worker.postMessage(untrustedCode);
setTimeout(function ()
{
worker.terminate();
reject(new Error('The worker timed out.'));
}, 1000);
});
}
테스트:
https://jsfiddle.net/kp0cq6yw/
var promise = safeEval("1+2+3");
promise.then(function (result) {
alert(result);
});
출력해야 합니다.6(Chrome 및 Firefox에서 테스트됨).
다른 응답에서 언급된 바와 같이, (서버 측에 코드를 보내지 않고) 샌드박스된 iframe에 코드를 가두고 메시지와 통신하는 것만으로도 충분합니다.
질문에 설명된 것처럼 신뢰할 수 없는 코드에 API를 제공할 필요가 있기 때문에 제가 만든 작은 라이브러리를 살펴볼 것을 제안합니다. 신뢰할 수 없는 코드가 실행되는 샌드박스에 특정 함수 집합을 바로 내보낼 수 있는 기회가 있습니다.사용자가 제출한 코드를 샌드박스에서 실행하는 데모도 있습니다.
http://asvd.github.io/jailed/demos/web/console/
저는 js.js가 여기서 언급할 가치가 있다고 생각합니다.자바스크립트로 작성된 자바스크립트 인터프리터입니다.
네이티브 자바스크립트보다 약 200배 느리지만, 특성상 완벽한 샌드박스 환경입니다.또 다른 단점은 크기가 약 600KB로 데스크톱의 경우에는 허용될 수 있지만 모바일 장치의 경우에는 허용되지 않습니다.
모든 브라우저 공급업체와 HTML5 사양은 iframe을 샌드박스할 수 있도록 실제 sandbox 속성을 위해 노력하고 있지만 여전히 iframe의 세분화로 제한되어 있습니다.
일반적으로 임의의 사용자가 제공하는 자바스크립트가 정지문제로 전락하면서 어느 정도의 정규표현 등도 안전하게 위생할 수 없습니다 :-/
추한 방법이지만, 아마 당신에게 이 방법이 효과가 있을 겁니다.
나는 모든 글로벌을 가져다가 샌드박스 범위에서 재정의했고, 익명 기능을 사용하여 글로벌 객체를 얻을 수 없도록 strict mode를 추가했습니다.
function construct(constructor, args) {
function F() {
return constructor.apply(this, args);
}
F.prototype = constructor.prototype;
return new F();
}
// Sanboxer
function sandboxcode(string, inject) {
"use strict";
var globals = [];
for (var i in window) {
// <--REMOVE THIS CONDITION
if (i != "console")
// REMOVE THIS CONDITION -->
globals.push(i);
}
globals.push('"use strict";\n'+string);
return construct(Function, globals).apply(inject ? inject : {});
}
sandboxcode('console.log( this, window, top , self, parent, this["jQuery"], (function(){return this;}()));');
// => Object {} undefined undefined undefined undefined undefined undefined
console.log("return of this", sandboxcode('return this;', {window:"sanboxed code"}));
// => Object {window: "sanboxed code"}
https://gist.github.com/alejandrolechuga/9381781
독립적인 자바스크립트 인터프리터는 내장된 브라우저 구현의 케이지 버전보다 강력한 샌드박스를 제공할 가능성이 더 높습니다.
라이언은 이미 js.js를 언급했지만, 더 최신 프로젝트는 JS-Interpreter입니다.이 문서에서는 다양한 기능을 인터프리터에 노출하는 방법을 다루지만, 그 범위는 매우 제한적입니다.
2019년 현재, vm2는 Node.js에서 JavaScript를 실행하는 데 가장 인기 있고 정기적으로 업데이트되는 솔루션으로 보입니다.저는 프론트엔드 솔루션에 대해 잘 모릅니다.
NISP를 사용하면 샌드박스된 평가를 수행할 수 있습니다.
당신이 쓰는 표현이 정확히 자바스크립트 코드는 아니지만, 대신에 당신은 S표현을 쓸 것입니다.이것은 광범위한 프로그래밍을 요구하지 않는 간단한 DSL에 이상적입니다.
실행할 코드가 있다고 가정합니다.
var sCode = "alert(document)";이제 샌드박스에서 실행할 경우를 가정해 보겠습니다.
new Function("window", "with(window){" + sCode + "}")({});"샌드박스"에서 "경고" 기능을 사용할 수 없기 때문에 실행 시 이 두 줄은 실패합니다.
이제 사용자의 기능을 사용하여 창 개체의 멤버를 노출하려고 합니다.
new Function("window", "with(window){" + sCode + "}")({ 'alert':function(sString){document.title = sString} });
물론 견적서를 추가해서 다른 광택을 낼 수도 있지만, 그 생각은 분명하다고 생각합니다.
이 사용자 자바스크립트 코드는 어디에서 오는 것입니까?
사용자가 페이지에 코드를 삽입한 다음 브라우저에서 코드를 호출하는 경우(그리스 몽키 참조) 할 수 있는 일은 많지 않습니다.그냥 브라우저가 하는 일입니다.
그러나 스크립트를 데이터베이스에 저장한 후 검색하여 평가()하면 스크립트를 실행하기 전에 정리할 수 있습니다.
모든 창을 제거하는 코드의 예.그리고 문서.참조:
eval(
unsafeUserScript
.replace(/\/\/.+\n|\/\*.*\*\/, '') // Clear all comments
.replace(/\s(window|document)\s*[\;\)\.]/, '') // Removes window. Or window; or window)
)
이를 통해 다음이 실행(테스트되지 않음)되지 않도록 합니다.
window.location = 'http://example.com';
var w = window;
안전하지 않은 사용자 스크립트에 적용해야 하는 많은 제한 사항이 있습니다.유감스럽게도 자바스크립트에 사용할 수 있는 '샌드박스 컨테이너'가 없습니다.
저는 사용자들이 제 사이트를 위해 애플릿을 만들 수 있도록 단순화된 자바스크립트 샌드박스를 만들고 있습니다.DOM 액세스를 허용하는 문제(parentNode에서는 보안을 유지할 수 없음 =/)에 직면해 있지만, 제 접근 방식은 일부 유용한/harmless 멤버로 창 개체를 재정의한 다음 이 재정의된 창을 기본 범위로 사용자 코드를 ()하는 것이었습니다.
내 '핵심' 코드는 이렇게 돼요(나는 그것을 완전히 보여주지 않습니다 ;)
function Sandbox(parent){
this.scope = {
window: {
alert: function(str){
alert("Overriden Alert: " + str);
},
prompt: function(message, defaultValue){
return prompt("Overriden Prompt:" + message, defaultValue);
},
document: null,
.
.
.
.
}
};
this.execute = function(codestring){
// Here some code sanitizing, please
with (this.scope) {
with (window) {
eval(codestring);
}
}
};
}
그래서 샌드박스를 인스턴스화하고 실행() 기능을 사용하여 코드를 실행할 수 있습니다.또한 eval'd 코드 내의 모든 새로운 선언 변수는 궁극적으로 execute() 범위에 바인딩되므로 이름이 충돌하거나 기존 코드를 엉망으로 만들지 않습니다.
글로벌 개체는 여전히 액세스할 수 있지만 샌드박스 코드를 알 수 없는 개체는 샌드박스::scope 개체에서 프록시로 정의해야 합니다.
수 있습니다. 그러면 는 . 그러면 다음과 같습니다.undefined 시시:
(function (alert) {
alert ("uh oh!"); // User code
}) ();
물론 영리한 공격자는 자바스크립트 DOM을 검사하고 창에 대한 참조가 포함된 무시되지 않는 객체를 찾음으로써 이 문제를 해결할 수 있습니다.
또 다른 아이디어는 JSlint와 같은 도구를 사용하여 사용자의 코드를 스캔하는 것입니다.미리 설정된 변수가 없는지(또는 원하는 변수만) 확인한 다음 글로벌이 설정되거나 액세스되는 경우 사용자의 스크립트가 사용되지 않도록 합니다.다시 말해서, 사용자가 리터럴을 사용하여 구성할 수 있는 객체는 샌드박스를 탈출하기 위해 접근할 수 있는 윈도우 객체에 대한 암시적 참조를 가질 수 있습니다.
언급URL : https://stackoverflow.com/questions/195149/is-it-possible-to-sandbox-javascript-running-in-the-browser
'programing' 카테고리의 다른 글
| A2부터 무한대까지 지정(NO VBA) (0) | 2023.09.26 |
|---|---|
| long-poll jQuery.ajax()는 전화가 잠든 후 다시 전화하지 못합니까? (0) | 2023.09.26 |
| AngularJS에서 $timeout을 사용하여 매개 변수로 함수를 실행하는 방법은? (0) | 2023.09.26 |
| 자바스크립트를 이용하여 다음 / 이전 요소를 얻으시겠습니까? (0) | 2023.09.26 |
| WooCommerce 관리자 주문 목록의 특정 메타 필드별로 주문 필터링 (0) | 2023.09.26 |