샌드박스 처리된 IFrame에서 안전하게 플레이하기

오늘날의 웹에서 풍부한 환경을 구축하는 데는 거의 불가피한 부분이 있습니다. 사용자가 실제로 제어할 수 없는 구성요소 및 콘텐츠를 삽입할 수 있습니다. 서드 파티 위젯은 참여도를 높이고 전반적인 특히 사용자 제작 콘텐츠가 사용자 제작 콘텐츠의 중요성이 더 많이 사용합니다. 둘 중 하나라도 포기하는 것은 사실상 선택사항이 아니지만 두 가지 모두 사이트에서 That BadTM가 발생할 위험을 높입니다. 각 모든 광고, 소셜 미디어 위젯 등 사용자가 삽입하면 공격 벡터를 사용합니다.

콘텐츠 보안 정책 (CSP) 위험을 완화할 수 있는 방법이 있는지 신뢰할 수 있는 스크립트 소스 및 기타 신뢰할 수 있는 있습니다. 이는 올바른 방향으로 나아가는 중요한 단계이지만, 대부분의 CSP 지시문이 제공하는 보호는 바이너리입니다. 리소스는 그렇지 않을 수도 있습니다 "나는 내가 아니고 내가 이 콘텐츠 출처를 신뢰하긴 하지만 정말 멋지다. 삽입 제발, 브라우저, 하지만 그것으로 인해 내 사이트가 중단되지 않게 해 주세요."

최소 권한

본질적으로 YouTube는 사용자에게 작업을 수행하는 데 필요한 최소한의 기능만 포함합니다. 위젯이 새 창을 표시할 필요가 없어 window.open 액세스 권한을 삭제할 수 없음 상처를 줘요. Flash가 필요하지 않다면 플러그인 지원을 끄는 것이 있습니다. Google은 최소한의 정보 보호 원칙에 따라 권한을 얻고, Google이 원하는 기능과 직접적인 관련이 없는 모든 기능을 있습니다. 그 결과, 우리는 더 이상 그 어떤 부분이건 사용되어서는 안 되는 권한을 활용하지 않도록 하는 것이 중요합니다. 그것은 애초에 해당 기능에 액세스할 수 없습니다.

iframe 요소는 이러한 솔루션의 좋은 프레임워크를 향한 첫 번째 단계입니다. iframe에서 신뢰할 수 없는 구성요소를 로드하여 분리를 측정함 로드하려는 콘텐츠 간의 간격을 나타냅니다. 프레임이 적용된 콘텐츠 페이지의 DOM이나 로컬에 저장한 데이터에 액세스할 수 없으며 페이지에서 임의의 위치에 그릴 수 있어야 합니다. 범위가 표시됩니다. 그러나 분리는 실제로 강력하지 않습니다. 포함된 페이지 성가시거나 악의적인 행위와 같은 여러 옵션인 자동재생 동영상, 플러그인, 팝업이 빙산의 일각입니다.

iframe 요소의 sandbox 속성 그것은 프레이밍된 콘텐츠에 대한 제한을 강화하는 데 필요한 것입니다. 우리는 브라우저가 특정 프레임의 콘텐츠를 낮은 권한으로 로드하도록 지시합니다. 특정 작업을 수행하는 데 필요한 일부 기능만 살펴봤습니다

확인

Twitter의 '트윗' 버튼은 더 많은 기능을 활용할 수 있는 좋은 예입니다. 샌드박스를 통해 사이트에 안전하게 삽입됩니다. Twitter를 사용하면 여러분의 콘텐츠에 버튼 클릭 다음 코드로 교체할 수 있습니다.

<iframe src="https://platform.twitter.com/widgets/tweet_button.html"
        style="border: 0; width:130px; height:20px;"></iframe>

어떤 항목을 차단할 수 있는지 알아보기 위해 정의할 수 있습니다 프레임에 로드된 HTML은 JavaScript를 가져오고, JSON으로 채워진 팝업 트윗 인터페이스 해당 인터페이스는 해당 트윗을 올바른 계정과 연결하기 위해서는 트윗 양식을 제출합니다. 거의 다 되었습니다. 프레임을 조정하기 위해 최상위 창이나 서드 파티 호스트를 탐색할 필요 없이 다른 비트의 수가 있을 수도 있습니다. 이러한 권한이 필요하지 않기 때문에 프레임의 콘텐츠를 샌드박스 처리하여 삭제해 보겠습니다.

샌드박스는 화이트리스트를 기반으로 작동합니다. 우선 Google에서 개별 기능을 다시 사용 설정할 수 있도록 추가해야 합니다. Twitter 위젯의 경우 자바스크립트, 팝업, 양식 제출 및 twitter.com의 쿠키. 이렇게 하려면 다음과 같이 sandbox 속성을 iframe에 추가하면 됩니다. 다음 값을 사용합니다.

<iframe sandbox="allow-same-origin allow-scripts allow-popups allow-forms"
    src="https://platform.twitter.com/widgets/tweet_button.html"
    style="border: 0; width:130px; height:20px;"></iframe>

이상입니다. 필요한 모든 기능을 프레임에 제공했고 액세스할 수 없는 모든 권한에 대한 액세스를 거부하게 됩니다. sandbox 속성의 값을 통해 명시적으로 권한을 부여해야 합니다.

세밀한 기능 제어

위의 예에서 몇 가지 가능한 샌드박스 플래그를 확인했으니, 이제 속성의 내부 작동을 좀 더 자세히 살펴보겠습니다.

샌드박스 속성이 비어 있는 iframe이 있으면 프레임 문서에는 완전히 샌드박스가 적용되어 다음과 같은 제한사항이 적용됩니다.

  • 자바스크립트는 프레임 문서에서 실행되지 않습니다. 여기에는 스크립트 태그 및 인라인 이벤트 핸들러를 통해 명시적으로 로드된 JavaScript JavaScript: URL이 있습니다. 이는 noscript 태그에 포함된 콘텐츠가 사용자가 스크립트를 직접 사용 중지한 것처럼 표시됩니다.
  • 프레임 문서는 고유한 출처로 로드되므로 동일 출처 검사가 실패합니다. 고유한 출처는 다른 어떤 출처와도 일치하지 않으며 스스로도. 여러 가지 영향들도 있지만 이는 문서에 포함된 모든 출처의 쿠키 또는 기타 저장 메커니즘에 저장된 데이터에 대한 액세스 (DOM 스토리지, 색인이 생성된 DB 등)
  • 프레이밍된 문서는 window.open 또는 target="_blank").
  • 양식을 제출할 수 없습니다.
  • 플러그인이 로드되지 않습니다.
  • 프레임으로 표시된 문서는 해당 문서 자체만 탐색할 수 있으며 최상위 상위 항목은 탐색할 수 없습니다. window.top.location를 설정하면 예외가 발생하며 target="_top"는 아무런 영향을 미치지 않습니다.
  • 자동으로 실행되는 기능 (자동 초점 양식 요소, 자동재생 동영상 등)은 차단됩니다.
  • 포인터 잠금을 가져올 수 없습니다.
  • seamless 속성은 프레임된 문서에 포함된 iframes에서 무시됩니다.

상당히 엄격한 작업이며 문서가 완전히 샌드박스 처리된 iframe에 로드됩니다. 위험성이 거의 없습니다 물론, 비용도 크지 않습니다. 정적인 콘텐츠를 위한 완전한 샌드박스로 벗어날 수 있을 수도 있지만, 느슨하게 풀고 싶을 것입니다.

플러그인을 제외한 각 제한사항은 샌드박스 속성 값에 플래그를 추가하면 됩니다. 샌드박스 처리된 문서는 절대 플러그인이 샌드박스 처리되지 않은 네이티브 코드이기 때문에 플러그인 실행 가능 게임:

  • allow-forms에서는 양식 제출을 허용합니다.
  • allow-popups는 팝업을 허용합니다.
  • allow-pointer-lock는 포인터 잠금을 허용합니다.
  • allow-same-origin를 사용하면 문서의 원본을 유지할 수 있습니다. 페이지 로드됨 https://example.com/부터는 해당 출처의 데이터에 계속 액세스할 수 있습니다.
  • allow-scripts를 사용하면 JavaScript 실행을 허용하며, 자동으로 트리거됩니다 (JavaScript를 통해 구현하기 쉽기 때문).
  • allow-top-navigation를 사용하면 문서를 프레임 밖으로 나눌 수 있음 최상위 창 탐색

이러한 점을 염두에 두고, 우리는 왜 이러한 결정을 내렸는지 정확히 평가할 수 있습니다. 위의 Twitter 예제에 있는 샌드박스 플래그 세트:

  • allow-scripts가 필요합니다. 프레임에 로드된 페이지가 사용자 상호작용을 처리하는 JavaScript입니다.
  • 새 창에서 트윗 양식이 팝업으로 표시되므로 allow-popups가 필요합니다. 창
  • 트윗 양식을 제출할 수 있어야 하므로 allow-forms가 필요합니다.
  • twitter.com의 쿠키가 필요하지 않으므로 allow-same-origin가 필요합니다. 액세스할 수 없고 사용자가 로그인하여 양식을 게시할 수 없었습니다.

한 가지 중요한 점은 프레임에 적용된 샌드박스 플래그도 적용할 수 없습니다. 이것은 양식만 존재하더라도 프레임의 샌드박스에 allow-forms를 추가합니다. 프레임이 팝업되는 창에서

sandbox 속성을 적용하면 위젯은 권한만 가져옵니다. 필요한 기능을 제공하며 플러그인, 상단 탐색, 포인터 잠금 등의 기능은 님이 차단되었습니다. 악영향 없이 위젯을 삽입하는 위험을 줄였습니다. 이는 모두에게 이익이 됩니다.

권한 분리

신뢰할 수 없는 코드를 실행하기 위해 서드 파티 콘텐츠를 샌드박싱하여 꽤 명백히 유익합니다 그렇다면 어떻게 해야 할까요? 스스로를 믿으시죠? 그렇다면 왜 샌드박스에 대해 걱정할까요?

이 질문을 돌려보겠습니다. 코드에 플러그인이 필요하지 않다면 왜 액세스할 수 있나요? 기껏해야 한 번도 사용하지 않는 특권이긴 하지만, 최악의 경우에는 잠재적인 벡터가 포함됩니다. 모든 사람의 코드는 사실상 모든 애플리케이션이 한 가지 방식으로 악용에 취약합니다. 또는 다른 형태일 수 있습니다. 자체 코드를 샌드박싱하면 공격자가 장애가 발생하면 애플리케이션에 대한 전체 액세스 권한이 애플리케이션 출처 그들은 응용 프로그램이 할 수있는 작업만 할 수 있습니다 있습니다. 여전히 나쁘지만 그렇게 나쁘지는 않습니다.

애플리케이션을 여러 영역으로 분할하면 위험을 더욱 줄일 수 있습니다. 가능한 최소한의 권한으로 각 조각을 샌드박싱하는 등의 작업을 수행할 수 있습니다. 이 기법은 네이티브 코드에서 매우 일반적입니다. 예를 들어 Chrome이 자체적으로 로컬 하드 드라이브에 액세스할 수 있는 높은 권한의 브라우저 프로세스로 네트워크 연결을 만들 수 있으며, 높은 권한의 렌더러 프로세스를 파싱하는 어려운 작업을 대신 수행할 수 있습니다. 렌더러는 터치하지 않아도 됨 브라우저에서는 컴퓨터에 필요한 모든 정보를 페이지를 렌더링해야 합니다. 영리한 해커가 렌더러를 손상시키는 방법을 찾아낸다 해도 렌더러가 자체적으로 많은 관심을 할 수 없기 때문입니다. 높은 권한의 액세스는 모두 브라우저의 프로세스를 통해 라우팅되어야 합니다. 공격자들은 시스템의 다양한 부분에서 몇 개의 허점을 찾아야 합니다. 피해를 입힐 수 있기 때문에 전복에 성공할 위험이 크게 줄어듭니다.

eval()을(를) 안전하게 샌드박스 처리 중

샌드박스를 사용하면 postMessage API 이 모델의 성공 여부를 웹에 적용하는 것은 매우 간단합니다. 조각 애플리케이션은 샌드박스 처리된 iframe에 상주할 수 있고 상위 문서는 중개인이 보내는 메시지를 게시하고 확인할 수 있습니다 이러한 종류의 구조는 앱이 가능한 최소한의 손상을 입히도록 합니다. 또한 한 번에 여러 작업을 해야 하는 명확한 통합 지점을 만들 수 있으므로 작업이 필요한 위치를 정확히 알 수 있습니다. 입력과 출력의 유효성을 검사할 때 주의하세요. 한 가지 예를 통해 그것이 어떻게 작동하는지 볼 수 있습니다.

Evalbox는 흥미로운 애플리케이션입니다. 는 문자열을 가져와 JavaScript로 평가합니다. 와, 그렇죠? 무엇을 여러분은 이 오랜 세월을 기다렸어요. 꽤 위험합니다 물론 임의의 JavaScript 실행을 허용하면 출처가 제공해야 하는 모든 데이터를 확보할 수 있습니다. Google은 Kubernetes 클러스터의 Bad ThingsTM는 코드가 샌드박스 내에서 실행되게 하거나 훨씬 더 안전해집니다. 먼저 프레임의 내용부터 시작합니다.

<!-- frame.html -->
<!DOCTYPE html>
<html>
    <head>
    <title>Evalbox's Frame</title>
    <script>
        window.addEventListener('message', function (e) {
        var mainWindow = e.source;
        var result = '';
        try {
            result = eval(e.data);
        } catch (e) {
            result = 'eval() threw an exception.';
        }
        mainWindow.postMessage(result, event.origin);
        });
    </script>
    </head>
</html>

프레임 안에는 메시지를 수신 대기하는 최소한의 문서가 있습니다. window 객체의 message 이벤트에 연결하여 상위 요소로부터 회수할 수 있습니다. 상위 요소가 iframe 콘텐츠에서 postMessage를 실행할 때마다 이 이벤트는 상위가 원하는 문자열에 액세스할 수 있게 해 줍니다. 실행할 수 있습니다

핸들러에서 상위 요소인 이벤트의 source 속성을 가져옵니다. 창 이 데이터로 작업한 결과를 완료되었습니다. 그런 다음 주어진 데이터를 eval() 이 호출은 차단된 작업이므로 try 블록에 래핑되었습니다. 샌드박스 처리된 iframe 내에서 DOM 예외를 자주 생성합니다. 우리가 잡을 것입니다 대신 친절한 오류 메시지를 신고해 주세요. 마지막으로 상위 창으로 돌아갑니다. 매우 간단합니다.

상위 요소도 마찬가지로 복잡하지 않습니다. textarea로 작은 UI를 만듭니다. 실행용 button이며, frame.html iframe를 샌드박스 처리하여 스크립트 실행만 허용:

<textarea id='code'></textarea>
<button id='safe'>eval() in a sandboxed frame.</button>
<iframe sandbox='allow-scripts'
        id='sandboxed'
        src='frame.html'></iframe>

이제 실행을 위해 항목을 연결해 보겠습니다. 먼저, 우리는 디코더의 응답을 듣고 iframealert()를 사용자에게 제공합니다. 실제 애플리케이션은 덜 성가신 일을 할 것입니다.

window.addEventListener('message',
    function (e) {
        // Sandboxed iframes which lack the 'allow-same-origin'
        // header have "null" rather than a valid origin. This means you still
        // have to be careful about accepting data via the messaging API you
        // create. Check that source, and validate those inputs!
        var frame = document.getElementById('sandboxed');
        if (e.origin === "null" &amp;&amp; e.source === frame.contentWindow)
        alert('Result: ' + e.data);
    });

다음으로, button를 클릭하도록 이벤트 핸들러를 연결합니다. 사용자가 textarea의 현재 콘텐츠를 가져와 실행할 프레임:

function evaluate() {
    var frame = document.getElementById('sandboxed');
    var code = document.getElementById('code').value;
    // Note that we're sending the message to "*", rather than some specific
    // origin. Sandboxed iframes which lack the 'allow-same-origin' header
    // don't have an origin which you can target: you'll have to send to any
    // origin, which might alow some esoteric attacks. Validate your output!
    frame.contentWindow.postMessage(code, '*');
}

document.getElementById('safe').addEventListener('click', evaluate);

정말 쉽죠? 아주 간단한 평가 API를 만들었고, 이제 쿠키와 같은 민감한 정보에 액세스할 수 없는 사용자 환경을 또는 DOM 스토리지를 사용합니다 마찬가지로 평가된 코드는 플러그인을 로드하거나 새 창을 표시하거나 기타 성가시거나 악의적인 활동을 차단할 수 있습니다.

모놀리식 애플리케이션을 단일 목적 구성요소로 작동합니다 각각 간단한 메시징 API로 래핑할 수 있으며 사용할 수 있습니다. 권한이 높은 상위 창은 컨트롤러와 디스패처를 통해 각각 고유한 IP 주소를 가진 특정 모듈로 메시지를 가능한 한 적은 수의 권한으로서 작업을 수행하고, 결과를 듣고, 각 모듈에 필요한 정보만 잘 제공되도록 합니다.

하지만 프레임이 있는 콘텐츠를 다룰 때는 매우 주의해야 합니다. 데이터를 가져올 수 있습니다 만약 https://example.com/가 샌드박스로 동일한 출처의 다른 페이지를 프레이밍합니다. allow-same-originallow-scripts 플래그를 모두 포함하는 경우 프레이밍된 페이지가 상위 페이지에 도달할 수 있으며 샌드박스 속성을 제거하여 있습니다.

샌드박스에서 플레이하기

샌드박스는 현재 다양한 브라우저(Firefox 17 이상, IE10 이상 및 작성 시점의 Chrome (caniuse는 최신 지원 표 참조). sandbox 적용 속성을 iframes 사용하면 해당 사용자에게 특정 권한을 콘텐츠 게시에 필요한 권한 있어야 합니다. 이를 통해 공정 사용으로 인해 발생할 수 있는 위험을 제3자 콘텐츠의 포함과 관련된 문제라고 할 수 있으며, Content Security는 정책을 참조하세요.

게다가 샌드박스는 지능적인 사람이 악용하는 위험 요소를 줄이는 공격자가 여러분의 코드에 있는 허점을 악용할 수 있습니다. 인코더-디코더 아키텍처를 샌드박스 서비스로 모놀리식 애플리케이션을 통합하고 각 서비스는 자체 완비된 기능의 작은 덩어리로 인해, 공격자들은 특정 프레임만 손상하도록 컨트롤러 역할을 할 것입니다. 그건 작업을 더욱 까다롭게 만들 수 있습니다. 특히 컨트롤러가 지원 범위 내입니다 해당 코드를 감사하는 데 보안 관련 노력을 기울일 수 있습니다. 나머지는 브라우저에 도움을 요청하세요.

그렇다고 해서 샌드박싱이 인프라의 문제점에 대한 완전한 해결책이라는 것은 아닙니다. 인터넷 보안의 핵심입니다. 이 솔루션은 심층 방어를 제공하며, 제어 기능을 모든 것을 지원하는 데 아직 브라우저 지원에 의존할 수는 관리(사용자 클라이언트를 제어하는 경우(엔터프라이즈 환경) (예: 만세!) 언젠가는 언젠가는... 하지만 지금은 샌드박스가 그 것이 특정 방어 수단에 대한 완전한 방어는 아니며, 전적으로 의존할 수 있습니다. 레이어는 여전히 훌륭합니다. 이 있습니다

추가 자료

  • 'HTML5 애플리케이션의 권한 분리' 작은 틀의 설계를 통해 작동하는 흥미로운 보고서입니다. 3개의 기존 HTML5 앱에 적용합니다.

  • 2개의 다른 새 iframe과 결합하면 샌드박스가 훨씬 더 유연해집니다. 속성: srcdoc, 및 seamless. 전자를 사용하면 해당 프레임에 대한 오버헤드 없이 프레임에 콘텐츠를 채울 수 HTTP 요청이 있어야 하며, HTTP 요청은 프레임된 콘텐츠에 스타일이 흐르도록 합니다. 현재 둘 다 브라우저 지원이 상당히 비효율적입니다 (Chrome 및 WebKit 합니다. 앞으로 흥미로운 조합이 될 것입니다. 다음과 같이 할 수 있습니다. 예를 들어 다음 코드를 통해 기사에 샌드박스 주석을 추가할 수 있습니다.

        <iframe sandbox seamless
                srcdoc="<p>This is a user's comment!
                           It can't execute script!
                           Hooray for safety!</p>"></iframe>