JavaScript의 샌드박싱: 깊이 있는 분석
Ethan Miller
Product Engineer · Leapcell

In JavaScript에서 샌드박스는 실행 중인 코드를 격리하여 애플리케이션 또는 시스템의 다른 부분에 불필요한 영향이나 보안 위험을 일으키지 않도록 하는 데 사용되는 보안 메커니즘입니다. 샌드박스는 외부 환경에 영향을 주지 않고 코드를 실행할 수 있는 제어된 환경을 제공하여 사용자 데이터와 시스템 보안을 보호합니다.
브라우저에서 샌드박스는 일반적으로 각 탭에 대해 브라우저에서 제공하는 격리된 환경을 나타냅니다. 이 격리를 통해 한 탭의 JavaScript 코드가 동일 출처 정책(즉, 동일한 프로토콜, 도메인 및 포트)을 따르거나 CORS(Cross-Origin Resource Sharing)를 통해 교차 출처 액세스를 명시적으로 허용하지 않는 한 다른 탭의 콘텐츠에 액세스할 수 없습니다. 웹 코드는 IPC(Inter-Process Communication) 채널을 통해 브라우저 커널 프로세스와 통신해야 하며, 통신 프로세스는 보안 검사를 거칩니다. 샌드박스 설계의 목적은 신뢰할 수 없는 코드가 특정 환경 내에서 실행되도록 허용하고 격리 영역 외부의 리소스에 대한 액세스를 제한하는 것입니다.
JavaScript에서 샌드박스의 사용 사례는 무엇입니까?
JavaScript에서 샌드박스는 일반적으로 코드의 실행 환경을 격리하고 제어하여 안전하고 제한된 환경에서 실행되도록 하고 주 환경에 대한 잠재적인 손상을 방지하는 데 사용됩니다.
- 타사 JavaScript 실행: 신뢰할 수 없는 타사 JavaScript 코드를 실행해야 하는 경우.
- 온라인 코드 편집기: 많은 온라인 코드 편집기는 사용자 제공 코드가 페이지 자체에 영향을 미치지 않도록 샌드박스에서 실행합니다.
- 웹 애플리케이션 보안: 브라우저에서 서로 다른 소스의 JavaScript를 실행할 때 샌드박스는 악성 코드가 중요한 리소스에 액세스하거나 위험한 작업을 실행하는 것을 방지하여 권한을 제한할 수 있습니다.
- 플러그인 및 타사 스크립트: 웹 애플리케이션이 타사 플러그인 또는 스크립트를 로드하고 실행해야 하는 경우 샌드박스는 액세스 권한을 제한하여 주 애플리케이션과 데이터의 보안을 보호할 수 있습니다.
- JSONP: 서버에서 JSONP 응답을 구문 분석할 때 반환된 데이터가 신뢰할 수 없는 경우 샌드박스를 사용하여 데이터를 안전하게 구문 분석하고 검색할 수 있습니다.
JSONP 통신 메커니즘
JSONP의 작동 원리는 <script>
태그에 교차 출처 제한이 없다는 사실(역사적 유물)을 기반으로 하며, 이를 통해 타사 서비스와 통신할 수 있습니다. 통신이 필요한 경우 현재 사이트의 스크립트는 다음과 같이 타사 API URL을 가리키는 <script>
요소를 만듭니다.
<script src="http://www.example.net/api?param1=1¶m2=2"></script>
데이터를 수신하기 위해 콜백 함수가 제공됩니다(함수 이름은 합의되거나 URL 매개변수를 통해 전달될 수 있음). 타사 응답은 JSON으로 래핑된 응답입니다(따라서 JSONP라는 용어는 JSON 패딩을 의미함). 예:
callback({ name: 'hax', gender: 'Male' });
이렇게 하면 브라우저가 callback
함수를 호출하고 구문 분석된 JSON 객체를 매개변수로 전달합니다. 현재 사이트의 스크립트는 callback
함수 내에서 수신된 데이터를 처리할 수 있습니다.
샌드박스를 사용하여 JSONP 데이터를 구문 분석하는 기본 접근 방식
- 격리된 iframe을 샌드박스로 생성: JSONP 요청에 격리된 실행 환경을 제공하기 위해 주 페이지에 iframe을 동적으로 만듭니다. 이 iframe은 주 페이지의 DOM에 액세스할 수 없으므로 실행 중인 코드의 영향을 제한합니다.
- iframe 내에서 JSONP 요청 시작: 생성된 iframe에
<script>
태그를 삽입하여 반환된 JSONP 스크립트가 격리된 환경 내에서 실행되도록 합니다. 이렇게 하면 반환된 스크립트에 악성 코드가 포함되어 있더라도 그 효과가 iframe 내에 제한되고 주 페이지에 영향을 미치지 않습니다. - iframe에서 데이터를 안전하게 검색: iframe 내부의 스크립트는 주 페이지의 DOM을 직접 수정할 수 없지만
postMessage
API와 같은 미리 정의된 방법을 사용하여 데이터를 주 페이지로 안전하게 전송할 수 있습니다. 주 페이지는 보안을 위해 소스를 확인하면서 이 데이터를 수신하기 위해 이벤트 리스너를 설정해야 합니다. - iframe 동작 제한 및 모니터링: 추가 보안 조치에는 iframe이 로드하고 실행할 수 있는 리소스를 제한하기 위해 **콘텐츠 보안 정책(CSP)**을 사용하는 것과 iframe 동작을 모니터링하고 제어하기 위해 다른 브라우저 보안 기능을 활용하는 것이 포함됩니다.
이러한 단계를 따르면 JSONP 응답에 신뢰할 수 없는 데이터나 코드가 포함되어 있더라도 잠재적인 위협을 효과적으로 격리하고 제어할 수 있으므로 사용자 데이터와 보안을 보호할 수 있습니다.
요약하면, 신뢰할 수 없는 JavaScript를 구문 분석하거나 실행해야 하거나 실행 중인 코드 내에서 특정 객체에 대한 액세스를 격리하거나 제한해야 하는 경우 샌드박스가 중요한 역할을 합니다.
with
+ new Function
을 사용하여 샌드박스 구현
JavaScript에서 with
문과 new Function
을 사용하여 간단한 샌드박스 환경을 만들 수 있습니다. 이 방법은 코드의 실행 범위를 제한하여 전역 변수에 액세스하거나 안전하지 않은 작업을 수행하는 것을 방지합니다.
with
블록 범위 내에서 변수 액세스는 범위 체인을 더 자세히 보기 전에 제공된 객체의 속성을 우선시합니다. 이를 통해 실행된 코드 내에서 변수 액세스를 효과적으로 모니터링할 수 있습니다.
function createSandbox(code) { // 샌드박스 내에서 전역 객체 역할을 할 빈 객체 생성 const sandbox = {}; // with 문을 사용하여 코드의 범위를 빈 객체로 설정 // new Function을 사용하여 새 함수를 만들고 코드 액세스를 샌드박스 객체로만 제한 const script = new Function('sandbox', `with(sandbox) { ${code} }`); // 함수를 실행하고 샌드박스 객체를 인수로 전달 return function () { script(sandbox); }; } // 샌드박스 환경 사용 const sandboxedScript = createSandbox('console.log("Hello from the sandbox!"); var x = 10;'); sandboxedScript(); // 출력: Hello from the sandbox! console.log(typeof x); // 출력: undefined, x는 샌드박스 내부에 정의되었고 외부에서는 액세스할 수 없기 때문입니다.
여기서 문자열 code
를 매개변수로 사용하는 createSandbox
함수를 정의합니다. 이 문자열은 샌드박스 환경에서 실행해야 하는 JavaScript 코드를 나타냅니다. 먼저 샌드박스 내에서 전역 객체 역할을 하는 빈 객체 sandbox
를 만듭니다. 그런 다음 with(sandbox)
문을 사용하여 샌드박스된 코드의 실행 환경을 이 빈 객체로 설정합니다. 즉, 모든 변수와 함수 정의는 샌드박스 내에 제한되고 전역 범위에 액세스할 수 없습니다.
new Function
생성자는 제공된 코드 문자열을 실행하는 새 함수를 만듭니다. 이를 통해 외부 환경에 액세스하거나 수정하는 것을 방지하면서 범위를 restricted하여 JavaScript를 동적으로 실행할 수 있습니다. 마지막으로, 호출될 때 샌드박스된 코드를 실행하는 클로저 함수를 반환합니다.
제한 사항 및 보안 문제
이 방법은 실행 환경을 어느 정도 격리할 수 있지만 완전히 안전하지는 않습니다. with
문과 new Function
에는 보안 위험이 있습니다. 특히 샌드박스된 코드가 Function
생성자 자체에 액세스할 수 있는 경우 샌드박스 제한을 무시하고 임의의 코드를 실행할 수 있습니다. 요컨대, new Function
+ with
는 정상적인 사용자를 막을 수 있지만 악의적인 행위에 대해서는 확실하지 않은 샌드박싱 방법입니다.
iframe
을 사용하여 샌드박스 구현
iframe
을 사용하여 샌드박스 환경을 만드는 것은 웹 개발에서 일반적인 기술입니다. 현재 페이지 내에 완전히 독립적인 HTML 페이지를 임베드할 수 있어 JavaScript 실행을 효과적으로 격리하고 스크립트가 주 페이지의 DOM 또는 JavaScript 환경에 액세스하는 것을 방지하여 보안을 강화합니다.
HTML 구조
먼저 HTML 구조를 설정해야 합니다.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Sandbox Example</title> </head> <body> <iframe id="sandbox" style="display: none"></iframe> <script src="index.js"></script> </body> </html>
JavaScript 구현
index.js
에서 iframe
의 contentWindow
속성을 조작하여 간단한 샌드박스 환경을 만들 수 있습니다. 여기서의 아이디어는 iframe
내부에 스크립트를 삽입하고 실행하여 격리된 컨텍스트 내에서 실행되도록 하는 것입니다.
// index.js function createSandbox(callback) { const iframe = document.getElementById('sandbox'); if (!iframe) { return console.error('Sandbox iframe을 찾을 수 없습니다.'); } // 코드를 실행하기 전에 iframe이 완전히 로드되었는지 확인 iframe.onload = function () { const iframeWindow = iframe.contentWindow; // 필요한 경우 샌드박스 내부에 안전한 전역 변수 또는 함수 정의 iframeWindow.safeGlobalVar = { /* 안전한 데이터 또는 메서드 */ }; // 콜백 함수를 실행하고 샌드박스의 window 객체를 전달하여 그 안에서 코드를 실행 callback(iframeWindow); }; // 깨끗한 환경을 보장하기 위해 iframe 다시 로드 iframe.src = 'about:blank'; } // 샌드박스 사용 createSandbox(function (sandboxWindow) { // 샌드박스 내부에서 코드 실행 sandboxWindow.eval('console.log("Hello from the sandbox!");'); });
iframe
샌드박싱의 제한 사항
샌드박싱에 iframe
을 사용하면 몇 가지 기본 제한 사항이 있습니다.
- 샌드박스된
iframe
내부의<script>
태그는 실행할 수 없습니다. - AJAX 요청은 허용되지 않습니다.
- 로컬 스토리지(예:
localStorage
,cookie
)에 액세스할 수 없습니다. - 새 팝업(
window.open
)을 만들 수 없습니다. - 양식을 제출할 수 없습니다.
- Flash와 같은 플러그인을 로드할 수 없습니다.
그러나 HTML5는 보안을 더욱 강화하기 위해 추가 제한 사항을 제공하는 sandbox
속성을 도입했습니다. sandbox
속성은 다음 값을 지원합니다.
allow-scripts
: 스크립트 실행을 허용합니다.allow-same-origin
: 동일한 출처의 문서와의 상호 작용을 허용합니다.allow-forms
: 양식 제출을 허용합니다.allow-popups
:window.open
으로 만든 팝업과 같은 팝업을 허용합니다.allow-top-navigation
: 최상위 프레임으로의 탐색을 허용합니다.
다음은 iframe
에서 sandbox
속성을 사용하는 예입니다.
<iframe src="sandbox.html" sandbox="allow-scripts" id="sandbox"></iframe>
주 페이지와 iframe
간의 보안 통신
postMessage
API를 사용하여 주 페이지와 샌드박스된 iframe
간에 데이터를 안전하게 교환할 수 있습니다. 먼저 주 페이지에서 다음과 같습니다.
<!DOCTYPE html> <html> <head> <title>Main Page</title> </head> <body> <iframe src="./sandbox.html" id="sandbox" style="width: 600px; height: 400px"></iframe> <script> var iframe = document.getElementById('sandbox'); // iframe이 로드될 때까지 기다립니다. iframe.onload = function () { var targetOrigin = 'http://127.0.0.1:5500/'; // iframe의 실제 출처로 바꿉니다. iframe.contentWindow.postMessage('Hello, sandbox!', targetOrigin); }; // iframe에서 온 메시지 수신 대기 window.addEventListener('message', function (event) { // 메시지 소스 확인 if (event.origin !== 'http://127.0.0.1:5500') { return; // 신뢰할 수 없는 소스의 메시지 무시 } // 수신된 메시지 처리 console.log('iframe에서 받은 메시지:', event.data); }); </script> </body> </html>
iframe
페이지(sandbox.html
)에서 메시지를 수신 대기합니다.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Sandbox</title> </head> <body> <script> window.addEventListener('message', function (event) { // 메시지 소스 확인 if (event.origin !== 'http://127.0.0.1:5500') { return; // 신뢰할 수 없는 소스의 메시지 무시 } // 수신된 메시지 처리 console.log('Received message:', event.data); // 주 페이지로 응답 다시 보내기 event.source.postMessage('Hello, main page!', event.origin); }); </script> </body> </html>
event.origin
을 확인하고 postMessage
에서 정확한 대상 출처를 지정하면 보안 통신을 보장하고 잠재적인 보안 취약점을 방지할 수 있습니다.
Web Workers를 사용하여 샌드박스 구현
Web Workers를 샌드박스로 사용하는 방법에는 작업자 내부에서 실행하려는 JavaScript 코드를 포함하는 Blob
객체를 동적으로 만드는 것이 포함됩니다. 이 방법을 사용하면 코드가 주 페이지 환경에서 격리되도록 하면서 별도의 스레드에서 임의의 JavaScript 코드를 실행할 수 있습니다. 이렇게 하면 코드를 안전하게 실행할 수 있습니다.
function workerSandbox(appCode) { var blob = new Blob([appCode]); var appWorker = new Worker(window.URL.createObjectURL(blob)); } workerSandbox('const a = 1; console.log(a);'); // 출력: 1 console.log(a); // ReferenceError: a가 정의되지 않았습니다.
이 접근 방식은 Web Workers를 활용하여 격리된 환경에서 신뢰할 수 없는 코드를 실행하여 주 페이지를 방해하지 않도록 합니다. Web Workers는 별도의 스크립트를 실행하는 동안 UI 응답성을 유지하기 때문에 계산 집약적인 작업을 처리할 때 특히 유용합니다.
요약
JavaScript 샌드박스는 코드를 실행하고 테스트할 수 있는 격리된 실행 환경으로, 주 애플리케이션의 상태 또는 데이터에 영향을 미치지 않습니다. 전역 변수 및 함수에 대한 액세스를 제한하면 샌드박스는 잠재적인 보안 위험 및 데이터 유출을 방지하면서 신뢰할 수 없는 코드를 실행하는 안전한 방법을 제공합니다. 샌드박스는 악성 스크립트 또는 예측할 수 없는 스크립트로부터 애플리케이션을 보호하는 데 필수적입니다.
샌드박스를 구현하는 다양한 방법은 다음과 같습니다.
-
with
+new Function
:- 기본 격리 제공.
- 샌드박스된 코드가
Function
생성자를 통해 이스케이프할 수 있으므로 완전히 안전하지는 않습니다.
-
iframe
샌드박싱:- 임베디드 iframe을 사용하여 별도의 실행 환경을 만듭니다.
- 보안을 강화하지만 일부 제한 사항이 있습니다(예: 제한된
localStorage
및AJAX
요청). - 보안 데이터 교환을 위해
postMessage
와 결합할 수 있습니다.
-
Web Workers:
- 별도의 스레드에서 코드를 실행합니다.
- 강력한 격리를 제공하지만 DOM에 대한 직접적인 액세스가 부족합니다.
- 신뢰할 수 없거나 계산 비용이 많이 드는 스크립트를 실행하는 데 이상적입니다.
샌드박스를 사용해야 하는 경우
샌드박스는 다음과 같은 경우에 유용합니다.
- 신뢰할 수 없는 JavaScript를 안전하게 실행하거나 구문 분석해야 하는 경우.
- 코드가 주 애플리케이션을 방해하지 않도록 실행 환경을 격리하려는 경우.
- 실행 중인 코드가 특정 객체 또는 API에 액세스하는 것을 제한해야 하는 경우.
개발자는 올바른 샌드박싱 기술을 선택하여 보안을 개선하고 주 애플리케이션에 대한 위험을 최소화하면서 스크립트의 안전한 실행을 보장할 수 있습니다.
Leapcell은 Node.js 프로젝트 호스팅을 위한 최고의 선택입니다.
Leapcell은 웹 호스팅, 비동기 작업 및 Redis를 위한 차세대 서버리스 플랫폼입니다.
다국어 지원
- Node.js, Python, Go 또는 Rust로 개발합니다.
무제한 프로젝트를 무료로 배포
- 사용량에 대해서만 지불합니다. 요청이나 요금이 없습니다.
탁월한 비용 효율성
- 유휴 요금 없이 사용한 만큼 지불합니다.
- 예: $25는 평균 응답 시간 60ms에서 694만 건의 요청을 지원합니다.
간소화된 개발자 경험
- 간편한 설정을 위한 직관적인UI
- 완전 자동화된 CI/CD 파이프라인 및 GitOps 통합.
- 실행 가능한 통찰력을 위한 실시간 지표 및 로깅.
손쉬운 확장성 및 고성능
- 높은 동시성을 쉽게 처리하기 위한 자동 확장.
- 제로 운영 오버헤드 — 구축에만 집중하십시오.
설명서에서 자세히 알아보세요!
X에서 팔로우하세요: @LeapcellHQ