Adobe AIR의 HTML 보안

Adobe AIR 1.0 이상

이 항목에서는 AIR HTML 보안 아키텍처에 대해 설명하고 iframe, 프레임 및 샌드박스 브리지를 활용하여 HTML 기반 응용 프로그램을 설치하고 HTML 내용을 SWF 기반 응용 프로그램으로 안전하게 통합하는 방법에 대해 설명합니다.

런타임은 HTML 및 JavaScript에서 규칙을 적용하고 가능한 보안 취약성을 극복할 수 있는 메커니즘을 제공합니다. 응용 프로그램이 주로 JavaScript로 작성되었는지 또는 HTML 및 JavaScript 내용을 SWF 기반 응용 프로그램으로 로드할지 여부에 상관없이 동일한 규칙이 적용됩니다. 응용 프로그램 샌드박스 내용과 비 응용 프로그램 보안 샌드박스 내용의 권한은 서로 다릅니다. 내용을 iframe 또는 프레임으로 로드할 때 런타임은 프레임 또는 iframe의 내용을 응용 프로그램 보안 샌드박스의 내용과 안전하게 통신할 수 있는 안전한 샌드박스 브리지 메커니즘을 제공합니다.

AIR SDK에서는 HTML 내용을 렌더링하기 위한 세 개의 클래스를 제공합니다.

HTMLLoader 클래스는 JavaScript 코드 및 AIR API 간의 긴밀한 통합을 지원합니다.

StageWebView 클래스는 HTML 렌더링 클래스이며 호스트 AIR 응용 프로그램과 매우 제한된 상태로 통합되어 있습니다. StageWebView 클래스에서 로드한 내용은 응용 프로그램 보안 샌드박스에 배치되지 않으며 호스트 AIR 응용 프로그램에 있는 데이터에 액세스하거나 함수를 호출할 수 없습니다. 데스크톱 플랫폼에서 StageWebView 클래스는 Webkit에 기반한 내장 AIR HTML 엔진을 사용하며, 이 엔진은 HTMLLoader 클래스에서도 사용됩니다. 모바일 플랫폼에서 StageWebView 클래스는 운영 체제에서 제공하는 HTML 컨트롤을 사용합니다. 따라서 모바일 플랫폼에서 StageWebView 클래스는 시스템 웹 브라우저와 동일한 보안 고려 사항 및 취약성을 갖고 있습니다.

TextField 클래스는 HTML 텍스트의 문자열을 표시할 수 있으며, JavaScript는 실행할 수 없지만 텍스트에 링크 및 외부에서 로드된 이미지를 포함할 수 있습니다.

자세한 내용은 보안 관련 JavaScript 오류 방지를 참조하십시오.

HTML 기반 응용 프로그램 구성에 대한 개요

프레임 및 iframe은 AIR에서 HTML 내용을 구성하는 편리한 구조를 제공합니다. 프레임은 데이터 지속성 유지와 원격 내용의 안전한 작업을 위한 수단을 제공합니다.

AIR의 HTML이 해당 페이지 기반의 일반 조직을 보유하고 있으므로 HTML 환경은 HTML 내용의 맨 위 프레임이 다른 페이지로 “이동하는” 경우 완전히 새로 고쳐집니다. 브라우저에서 실행 중인 웹 응용 프로그램에 대해 수행하는 작업과 거의 마찬가지로 프레임 및 iframe을 사용하여 AIR에서 데이터 지속성을 유지할 수 있습니다. 맨 위 프레임에서 주 응용 프로그램 객체를 정의합니다. 이러한 객체는 프레임이 새 페이지로 이동하도록 허용하지 않는 한 계속 유지됩니다. 자식 프레임 또는 iframe을 사용하여 응용 프로그램의 일시적인 부분을 로드 및 표시할 수 있습니다. 프레임 이외에 또는 프레임 대신 사용할 수 있는 데이터 지속성을 유지하는 여러 방법이 있습니다. 이러한 방법에는 쿠키, 로컬 공유 객체, 로컬 파일 저장소, 암호화된 파일 저장소, 로컬 데이터베이스 저장소가 있습니다.

AIR의 HTML은 실행 코드와 데이터 간의 일반적인 모호한 경계를 유지하므로 AIR은 HTML 환경의 맨 위 프레임에 있는 내용을 응용 프로그램 샌드박스에 배치합니다. 페이지 load 이벤트 후 AIR은 텍스트 문자열을 실행 객체로 변환할 수 있는 eval()과 같은 모든 작업을 제한합니다. 응용 프로그램에서 원격 내용을 로드하지 않는 경우에도 이러한 제한이 적용됩니다. HTML 내용에서 이러한 제한된 작업을 실행할 수 있도록 하려면 프레임 또는 iframe을 사용하여 비 응용 프로그램 샌드박스에 내용을 배치해야 합니다. eval() 함수에 의존하는 일부 JavaScript 응용 프로그램 프레임워크를 사용할 경우 샌드박스된 자식 프레임에서 내용을 실행해야 할 수 있습니다. 응용 프로그램 샌드박스의 JavaScript에 대한 전체 제한 사항 목록은 서로 다른 샌드박스의 내용에 대한 코드 제한 사항을 참조하십시오.

AIR의 HTML이 원격의 안전하지 않을 수 있는 내용을 로드할 수 있으므로 AIR은 한 도메인의 내용이 다른 도메인의 내용과 상호 작용하지 않도록 하는 동일 원본 정책을 적용합니다. 응용 프로그램 도메인과 기타 도메인의 내용 간 상호 작용을 허용하려면 부모 프레임과 자식 프레임 간의 인터페이스로 사용할 브리지를 설정합니다.

부모와 자식 간 샌드박스 관계 설정

AIR은 sandboxRootdocumentRoot 특성을 HTML 프레임 및 iframe 요소에 추가합니다. 이러한 특성을 통해 응용 프로그램 내용을 다른 도메인에서 가져온 것처럼 다룰 수 있습니다.

특성

설명

sandboxRoot

프레임 내용을 배치할 샌드박스 및 도메인을 결정하는 데 사용할 URL입니다. file:, http: 또는 https: URL 스킴을 사용해야 합니다.

documentRoot

프레임 내용을 로드할 URL입니다. file:, app: 또는 app-storage: URL 스킴을 사용해야 합니다.

다음은 원격 샌드박스 및 www.example.com 도메인에서 실행할 응용 프로그램의 sandbox 하위 디렉토리에 설치된 내용을 매핑하는 예제입니다.

<iframe 
    src="ui.html"  
    sandboxRoot="http://www.example.com/local/"  
    documentRoot="app:/sandbox/"> 
</iframe>

다른 샌드박스 또는 도메인의 부모 프레임과 자식 프레임 간 브리지 설정

AIR은 childSandboxBridgeparentSandboxBridge 속성을 자식 프레임의 window 객체에 추가합니다. 이러한 속성을 통해 부모 프레임과 자식 프레임 간의 인터페이스로 사용할 브리지를 정의할 수 있습니다. 각 브리지는 한 방향으로 이동합니다.

childSandboxBridge - childSandboxBridge 속성을 통해 자식 프레임이 인터페이스를 부모 프레임의 내용에 표시할 수 있습니다. 인터페이스를 표시하려면 childSandbox 속성을 자식 프레임의 함수 또는 객체로 설정합니다. 그렇게 하면 부모 프레임의 내용에서 객체 또는 함수에 액세스할 수 있습니다. 다음 예제에서는 자식 프레임에서 실행하는 스크립트에서 함수 및 속성을 포함하는 객체를 해당 부모에 표시하는 방법을 보여 줍니다.

var interface = {}; 
interface.calculatePrice = function(){ 
    return .45 + 1.20; 
} 
interface.storeID = "abc" 
window.childSandboxBridge = interface;

이 자식 내용이 "child"id가 할당된 iframe에 있는 경우 프레임의 childSandboxBridge 속성을 읽어 부모 내용에서 인터페이스에 액세스할 수 있습니다.

var childInterface = document.getElementById("child").childSandboxBridge; 
air.trace(childInterface.calculatePrice()); //traces "1.65" 
air.trace(childInterface.storeID)); //traces "abc"

parentSandboxBridge - parentSandboxBridge 속성을 통해 부모 프레임은 인터페이스를 자식 프레임의 내용에 표시할 수 있습니다. 인터페이스를 표시하려면 자식 프레임의 parentSandbox 속성을 부모 프레임의 함수 또는 객체로 설정합니다. 그렇게 하면 자식 프레임의 내용에서 객체 또는 함수에 액세스할 수 있습니다. 다음 예제에서는 부모 프레임에서 실행하는 스크립트에서 save 함수를 포함하는 객체를 해당 자식에 표시하는 방법을 보여 줍니다.

var interface = {}; 
interface.save = function(text){ 
    var saveFile = air.File("app-storage:/save.txt"); 
    //write text to file 
} 
document.getElementById("child").parentSandboxBridge = interface;

이 인터페이스를 사용하면 자식 프레임의 내용이 save.txt라는 파일에 텍스트를 저장할 수 있습니다. 그러나 파일 시스템에 대한 어떠한 액세스 권한도 없습니다. 일반적으로 응용 프로그램 내용은 가능한 가장 좁은 인터페이스를 다른 샌드박스에 표시해야 합니다. 자식 내용은 다음과 같이 save 함수를 호출할 수 있습니다.

var textToSave = "A string."; 
window.parentSandboxBridge.save(textToSave);

자식 내용이 parentSandboxBridge 객체의 속성을 설정하려는 경우 런타임에서 SecurityError 예외가 발생합니다. 부모 내용이 childSandboxBridge 객체의 속성을 설정하려는 경우 런타임에서 SecurityError 예외가 발생합니다.

서로 다른 샌드박스의 내용에 대한 코드 제한 사항

이 항목의 소개 부분인 Adobe AIR의 HTML 보안에서 설명한 대로 런타임은 규칙을 적용하고 HTML 및 JavaScript에서의 가능한 보안 취약성을 극복할 수 있는 메커니즘을 제공합니다. 이 항목에서는 그러한 제한 사항을 보여 줍니다. 코드가 이러한 제한된 API를 호출하려고 하면 런타임에서 "응용 프로그램 보안 샌드박스에서의 JavaScript 코드에 대한 Adobe AIR 런타임 보안 위반” 메시지의 오류가 발생합니다.

자세한 내용은 보안 관련 JavaScript 오류 방지를 참조하십시오.

JavaScript eval() 함수 및 유사 기술 사용에 대한 제한 사항

응용 프로그램 보안 샌드박스의 HTML 내용의 경우 코드를 로드한 후(body 요소의 onload 이벤트를 전달하고 onload 핸들러 함수가 실행을 완료한 후) 문자열을 실행 코드로 동적으로 변환할 수 있는 API를 사용할 때 제한 사항이 있습니다. 이는 응용 프로그램이 잠재적으로 안전하지 않은 네트워크 도메인과 같은 비 응용 프로그램 소스의 코드를 실수로 삽입 및 실행하지 않도록 하는 것입니다.

예를 들어 응용 프로그램에서 DOM 요소의 innerHTML 속성에 쓸 원격 소스의 문자열 데이터를 사용하는 경우 문자열에 안전하지 않은 작업을 수행할 수 있는 실행(JavaScript) 코드가 포함될 수 있습니다. 그러나 내용을 로드하는 동안 원격 문자열을 DOM에 삽입할 위험은 없습니다.

하나의 제한 사항은 JavaScript eval() 함수를 사용하는 경우에 해당됩니다. 응용 프로그램 샌드박스의 코드가 로드되고 onload 이벤트 핸들러가 처리된 후에는 eval() 함수를 제한적인 방법으로만 사용할 수 있습니다. 다음 규칙은 응용 프로그램 보안 샌드박스에서 코드가 로드된 이후eval() 함수를 사용할 때 적용됩니다.

  • 리터럴을 포함하는 식이 허용됩니다. 예를 들면 다음과 같습니다.

    eval("null"); 
    eval("3 + .14"); 
    eval("'foo'");
  • 다음과 같이 객체 리터럴이 허용됩니다.

    { prop1: val1, prop2: val2 }
  • 다음과 같이 객체 리터럴 setter/getter가 금지됩니다.

    { get prop1() { ... }, set prop1(v) { ... } }
  • 다음과 같이 배열 리터럴이 허용됩니다.

    [ val1, val2, val3 ]
  • 다음과 같이 속성 읽기를 포함하는 식이 금지됩니다.

    a.b.c
  • 함수 호출이 금지됩니다.

  • 함수 정의가 금지됩니다.

  • 속성 설정이 금지됩니다.

  • 함수 리터럴이 금지됩니다.

그러나 코드를 로드하는 동안, onload 이벤트 이전 및 onload 이벤트 핸들러 함수를 실행하는 동안 이러한 제한 사항이 응용 프로그램 보안 샌드박스의 내용에 적용되지 않습니다.

예를 들어 코드를 로드한 후 다음 코드를 실행하면 런타임에서 예외가 발생합니다.

eval("alert(44)"); 
eval("myFunction(44)"); 
eval("NativeApplication.applicationID");

eval() 함수를 호출할 때 생성된 코드와 같이 동적으로 생성된 코드는 응용 프로그램 샌드박스 내에 허용되는 경우 보안 위험을 유발할 수 있습니다. 예를 들어 응용 프로그램에서 네트워크 도메인에서 로드한 문자열을 실수로 실행하고 해당 문자열이 악의적인 코드를 포함할 수 있습니다. 예를 들어 이 코드가 사용자 컴퓨터의 파일을 삭제하거나 변경하는 코드일 수 있습니다. 또는 로컬 파일의 내용을 신뢰할 수 없는 네트워크 도메인으로 다시 보고하는 코드일 수 있습니다.

동적 코드를 생성하는 방법은 다음과 같습니다.

  • eval() 함수를 호출합니다.

  • innerHTML 속성 또는 DOM 함수를 사용하여 응용 프로그램 디렉토리 외부에 있는 스크립트를 로드하는 script 태그를 삽입합니다.

  • innerHTML 속성 또는 DOM 함수를 사용하여 src 특성을 통해 스크립트를 로드하지 않고 인라인 코드를 포함하는 script 태그를 삽입합니다.

  • script 태그에 대한 src 특성을 설정하여 응용 프로그램 디렉토리 외부에 있는 JavaScript 파일을 로드합니다.

  • href="javascript:alert('Test')"의 경우처럼 javascript URL 스킴을 사용합니다.

  • setInterval() 또는 setTimout() 함수를 사용합니다. 여기서 첫 번째 매개 변수(함수를 비동기적으로 실행하도록 정의)는 함수 이름이 아닌 평가할 문자열입니다(setTimeout('x = 4', 1000)과 유사).

  • document.write() 또는 document.writeln()을 호출합니다.

응용 프로그램 보안 샌드박스의 코드는 내용을 로드하는 동안 이러한 메서드만 사용할 수 있습니다.

이러한 제한 사항은 JSON 객체 리터럴과 함께 eval()을 사용하지 않도록 지정하지 않습니다. 이를 통해 응용 프로그램 내용을 JSON JavaScript 라이브러리에서 사용할 수 있습니다. 그러나 오버로드된 JSON 코드(이벤트 핸들러 사용)를 사용하는 데 제한을 받습니다.

다른 Ajax 프레임워크 및 JavaScript 코드 라이브러리의 경우 프레임워크 또는 라이브러리의 코드가 동적으로 생성된 코드에 대한 이러한 제한 사항 내에서 작동하는지 확인합니다. 그렇게 작동하지 않는 경우 비 응용 프로그램 보안 샌드박스에서 프레임워크 또는 라이브러리를 사용하는 내용을 포함합니다. 자세한 내용은 AIR 내부의 JavaScript에 대한 제한응용 프로그램 내용과 비 응용 프로그램 내용 간 스크립팅을 참조하십시오. Adobe에서는 http://www.adobe.com/products/air/develop/ajax/features/에서 응용 프로그램 보안 샌드박스를 지원하는 것으로 알려진 Ajax 프레임워크 목록을 유지합니다.

응용 프로그램 보안 샌드박스의 내용과 달리 비 응용 프로그램 보안 샌드박스의 JavaScript 내용은 eval() 함수를 호출하여 동적으로 생성된 코드를 언제든지 실행할 수 있습니다.

AIR API 액세스에 대한 제한 사항(비 응용 프로그램 샌드박스의 경우)

비 응용 프로그램 샌드박스의 JavaScript 코드에서는 window.runtime 객체에 액세스할 수 없으며 그러므로 이 코드에서 AIR API를 실행할 수 없습니다. 비 응용 프로그램 보안 샌드박스의 내용이 다음 코드를 호출하는 경우 응용 프로그램에서 TypeError 예외가 발생합니다.

try { 
    window.runtime.flash.system.NativeApplication.nativeApplication.exit(); 
}  
catch (e)  
{ 
    alert(e); 
}

비 응용 프로그램 샌드박스의 내용이 window.runtime 객체를 인식하지 않아 해당 객체를 정의되지 않은 값으로 식별하기 때문에 예외 유형은 TypeError(정의되지 않은 값)입니다.

스크립트 브리지를 사용하여 비 응용 프로그램 샌드박스의 내용에 런타임 기능을 표시할 수 있습니다. 자세한 내용은 응용 프로그램 내용과 비 응용 프로그램 내용 간 스크립팅을 참조하십시오.

XMLHttpRequest 호출 사용에 대한 제한 사항

응용 프로그램 보안 샌드박스의 HTML 내용은 동기 XMLHttpRequest 메서드를 사용하여 onLoad 이벤트 동안 HTML 내용이 로드될 때 응용 프로그램 샌드박스 외부에서 데이터를 로드할 수 없습니다.

기본적으로 비 응용 프로그램 보안 샌드박스의 HTML 내용은 JavaScript XMLHttpRequest 객체를 사용하여 요청을 호출하는 도메인 이외의 다른 도메인에서 데이터를 로드할 수 없습니다. frame 또는 iframe 태그에 allowcrosscomainxhr 특성이 포함될 수 있습니다. 이 특성을 null이 아닌 값으로 설정하면 프레임 또는 iframe의 내용이 Javascript XMLHttpRequest 객체를 사용하여 요청을 호출하는 코드의 도메인 이외의 다른 도메인에서 데이터를 로드할 수 있습니다.

<iframe id="UI" 
    src="http://example.com/ui.html" 
    sandboxRoot="http://example.com/" 
    allowcrossDomainxhr="true" 
    documentRoot="app:/"> 
</iframe>

자세한 내용은 다른 도메인의 내용 간 스크립팅을 참조하십시오.

CSS, 프레임, iframe 및 img 요소 로드에 대한 제한 사항(비 응용 프로그램 샌드박스 내용의 경우)

원격(네트워크) 보안 샌드박스의 HTML 내용은 원격 샌드박스(네트워크 URL)에서 CSS, frame, iframeimg 내용을 로드할 수만 있습니다.

local-with-filesystem, local-with-networking 또는 local-trusted 샌드박스의 HTML 내용은 응용 프로그램 또는 네트워크 샌드박스가 아닌 로컬 샌드박스에서 CSS, frame, iframe 및 img 내용을 로드할 수만 있습니다.

JavaScript window.open() 메서드 호출에 대한 제한 사항

JavaScript window.open() 메서드에 대한 호출을 통해 생성된 윈도우에 비 응용 프로그램 보안 샌드박스의 내용이 표시되는 경우 윈도우 제목은 주(시작) 윈도우 제목으로 시작하고 뒤에 콜론이 나옵니다. 코드를 사용하여 윈도우 제목의 해당 부분을 화면 밖으로 이동할 수 없습니다.

비 응용 프로그램 보안 샌드박스의 내용은 사용자 마우스 또는 키보드 상호 작용에 의해 트리거된 이벤트에 응답하여 JavaScript window.open() 메서드만 성공적으로 호출할 수 있습니다. 따라서 비 응용 프로그램 내용이 피싱 공격 등 위장하여 사용될 수 있는 윈도우를 만들 수 없습니다. 또한 마우스 또는 키보드 이벤트에 대한 이벤트 핸들러는 setTimeout() 함수 호출 등의 작업을 통해 window.open() 메서드가 지연 후 실행되도록 설정할 수 없습니다.

원격(네트워크) 샌드박스의 내용은 window.open() 메서드를 사용하여 원격 네트워크 샌드박스의 내용을 열 수만 있습니다. window.open() 메서드를 사용하여 응용 프로그램 또는 로컬 샌드박스의 내용을 열 수 없습니다.

local-with-filesystem, local-with-networking 또는 local-trusted 샌드박스(보안 샌드박스 참조)의 내용은 window.open() 메서드를 사용하여 로컬 샌드박스의 내용을 열 수만 있습니다. window.open()을 사용하여 응용 프로그램 또는 원격 샌드박스의 내용을 열 수 없습니다.

제한된 코드 호출 시 오류

이러한 보안 제한으로 인해 샌드박스에서의 사용이 제한되는 코드를 호출하면 런타임에서 JavaScript 오류: "응용 프로그램 보안 샌드박스에서의 JavaScript 코드에 대한 Adobe AIR 런타임 보안 위반"을 전달합니다.

자세한 내용은 보안 관련 JavaScript 오류 방지를 참조하십시오.

문자열에서 HTML 내용을 로드할 때의 샌드박스 보호

HTMLLoader 클래스의 loadString() 메서드를 사용하면 런타임에 HTML 내용을 만들 수 있습니다. 그러나 안전하지 않은 인터넷 소스에서 데이터를 로드할 경우 HTML 내용으로 사용하는 데이터가 손상될 수 있습니다. 따라서 loadString() 메서드를 사용하여 만들어진 HTML은 기본적으로 응용 프로그램 샌드박스에 배치되지 않으며 AIR API에 액세스할 수 없습니다. 그러나 HTMLLoader 객체의 placeLoadStringContentInApplicationSandbox 속성을 true로 설정하면 loadString() 메서드를 사용하여 만든 HTML을 응용 프로그램 샌드박스에 배치할 수 있습니다. 자세한 내용은 문자열에서 HTML 내용 로드를 참조하십시오.