4

eval() 또는 문자열에서 생성 된 함수를 사용하지 마십시오. 하지만 사용자가 입력 할 수있는 자바 스크립트의 하위 집합을 실행할 필요가있을 때 나는 lexer/파서와 인터프리터를 작성하는 데 많은 시간을 절약 할 수 있기 때문에 그것을 사용하도록 유혹 당한다. 기본 접근 방식은이 같은 eval()로를 통과하는 것중요한 리터럴을 "with (...) {...}"에서 샌드 박스 코드로 선언하는 것이 안전합니까?

a.toLowerCase() === 'xyz' || b == 1 || /pqr/.test(c) 

:

나는이 코드를 실행하고 싶은 말

with({a: ..., b: ..., c: ...}) { 
    ret = eval(code); 
} 

나는 code 항상 무 비판적 포함되어 있는지 확신 할 수 없다 위와 같은 코드. 이로 인해 악성 코드가 실행될 수 있습니다. 객체/메소드 with 액세스 내에서 코드를 실행하는

var obj = { 
    // list incomplete ;) 
    console: true, XMLHttpRequest: true, document: true, window: true, addEventListener: true, removeEventListener: true, parent: true, top: true, history: true, ..., 

    // actual data 
    a: ..., b: ..., c: ... 
}; 

with (obj) { 
    ... 
} 

possibe되어 있지 않은 경우 :

내가 객체를 다시 정의하는 중요한 브라우저를 통과하는 생각 같은 실제 데이터 이외의 with에 객체.

다시 정의되지 않은 다른 개체/함수를 통해 간접적으로 액세스되는 경우에도 이러한 메서드에 간접적으로 액세스 할 수 있음을 알고 있습니다. 이것들을 다시 정의한다고 가정 해 봅시다.

샌드 박스 코드에 보안 성이 있습니까 객체 및 기능이 콘텐츠 객체 인이 충분합니까?

이 경우 공격 벡터는 어떻게 남을 수 있습니까?

편집 1 :

코드는 파이어 폭스, 크롬, IE에서 실행해야합니다 (10 +), 오페라, 사파리.

+0

어디에서 실행되고 있습니까? 사용자의 브라우저에서? NodeJS에? NodeJS 또는 최신 브라우저에서는 엄격 모드가있는 IIFE를 사용하면 더 나은 행운을 얻게됩니다. –

+0

모든 사용자가 자신의 브라우저에서 자체 코드를 실행하도록하십시오. 아무것도 잘못 될 수는 없습니다. – Bergi

+0

[샌드 박스 코드를위한 가능한 해결책 (this link)] (http://stackoverflow.com/a/21700111/413180). – SilverlightFox

답변

7

아니요, 안전하지 않습니다.

var window = (function(){ return this }).call(undefined); 

Function.call는 전역 객체를 사용하기 때문에이 작동 : 아무리 당신이 with를 사용하여 코드의 실행 환경에 무엇을

, 다음과 같은 트릭을 사용하여 "진짜"전역 객체를 검색하는 데 여전히 가능 또는 null으로 명시 적으로 전달 된 경우 this의 값으로 음영 변수가 삭제 된 경우

+0

'.call()'도 필요 없습니다. 단지'(function() {return this})()'도 똑같이 할 것입니다. –

+0

'평가'중인 문자열에서'function'을 제거해도 해결되지 않습니까? –

+0

@AlexisWilke : 아니요. 잘못된 코드를 블랙리스트에 올리는 것은 결코 효과가 없습니다. 다음 단계는'var window = (1, eval) ("this");'이 될 것입니다. – Bergi

4

...

alert([1, window, document]); 
 

 
var obj = { 
 
    document: true, window: true 
 
}; 
 

 
with (obj) { 
 
    alert([2, window, document]); 
 
    
 
    delete window; 
 
    delete document; 
 
    
 
    alert([3, window, document]); //restored 
 
}

또한 당신은 document/ window 객체가 ownerDocument/ defaultView를 통해 도달 할 수있는 DOM 요소를 노출합니다.

+0

'eval'- 된 문자열에서'delete'를 제거하여 해결할 수 없습니까? –

+1

당신은'eval ("de"+ "lete document")와 같은 것들의 모든 가능성을 다루어야 할 것입니다.'eval'을 대체하면'새로운 함수'평가를 금지해야합니다 ... 그것의 제로 합 당신이 이길 수없는 게임. –

+0

그러나 변수를 '구성 불가능'으로 정의하여 '삭제'에 대해 안전하게 만들 수 있습니다. – Bergi

0

다른 원치 않는/개인 변수 (예 : 하위 함수가 상위 함수의 모든 변수에 액세스 할 수 있음)에 대한 액세스 권한을 부여하지 않으려면 전역 (정적) 함수를 사용해야합니다.

두 번째는이 같은 duskwuff 알렉스 K. 뭔가에 의해 설명 된대로 문제를 방지하기 위해 평가되는 문자열에서 몇 가지 키워드를 제거하려면 : 엄격 모드에서 작동하지 않을 수 있습니다

function exec(e) 
{ 
    e = e.replace(/new/, "new_", "g") 
     .replace(/delete/, "delete_", "g") 
     .replace(/function/, "function_", "g") 
     .replace(/throw/, "throw_", "g") 
     .replace(/this/, "this_", "g") 
     .replace(/var/, "var_", "g") 
     .replace(/eval/, "eval_", "g"); 
    obj = { ... }; 
    with(obj) 
    { 
     eval(e); 
    } 
} 

참고. 덧글에서 Bergi가 언급했듯이 obj의 변수를 보호하고 삭제할 수 없도록 만들 수 있으므로 대체 할 수 없습니다.

replace()에는 더 많은 것들이 포함될 수 있습니다. 달성하고자하는 것을 더 자세히 볼 수 있습니다. 평가 문자열이 단지 표현식 일 것으로 예상되는 경우 모든 키워드를 제거해야합니다 (truefalsenull 제외). 다른 몇 가지 기능을 제거 할 수도 있습니다. 여기에서는 eval 만 제거했습니다.

단어가 일치하면 anew이라는 단어가 new과 일치하지 않으므로 \b flag을 정규식에 사용할 수 있습니다. 이 플래그가 브라우저간에 얼마나 호환되는지 모르겠습니다.

e.replace(/\bnew\b/, "new_", "g"); 

new하지만 anew 일치합니다.

+1

문자열에 "new", "delete"등의 하위 문자열이 있으면 어떻게됩니까? –

+0

그러면 올바른 결과를 얻지 못할 것입니다. 해당 키워드가 금지되어 있다고 최종 사용자에게 항상 알릴 수 있습니다. 정규식을 고칠 수도 있습니다. –

+0

업데이트를했는데, 모든 브라우저에서'\ b'가 작동하지 않을 가능성이 있습니다. –

관련 문제