보안 앱 개발

개발자들은 JavaScript를 사용하는 Windows 스토어 앱을 사용하여 Windows 런타임에서 사용할 수 있는 뛰어난 성능의 광범위한 API와 함께 웹 기술의 다양성과 풍부함을 결합할 수 있습니다. 이러한 앱은 기존의 기본 응용 프로그램의 모든 성능을 가지고 보안되기만 하면 됩니다. 다행히 이 플랫폼은 보안을 염두에 두고 설계되었으므로, 모범 사례를 사용했을 때 보안 앱을 쉽게 만들 수 있게 하는 여러 가지 보안 "가드레일"을 포함합니다.

일반 데이터 원본

Windows 스토어 앱은 현재 웹에 있는 광범위한 데이터 원본에 액세스할 수 있습니다. 이러한 각 데이터 원본은 개발자가 보안 처리해야 하며 악성 스크립트 또는 기타 위험한 콘텐츠가 앱을 손상시킬 수 없도록 항상 유효성을 검사해야 합니다.

백엔드 웹 서비스와 같은 신뢰할 수 있는 원본에서 가져온 데이터에서도 악성 코드를 확인하고 제거해야 합니다. 전환 시 데이터가 수정되었거나, 백엔드 서비스 자체가 손상되었을 수 있습니다. 앱 보안을 보장하고 앱 사용자를 보호하려면 앱이 네트워크에서 수신하는 모든 데이터를 확인하세요.

보안을 보장하는 첫 번째 단계는 데이터가 앱으로 흐르는 지점을 식별하는 것입니다. 다음은 잠재적으로 앱을 손상시킬 수 있는 몇 가지 일반적인 데이터 원본입니다.

다음은 신뢰할 수 없는 데이터 원본의 몇 가지 예입니다. 앱을 보안하는 첫 번째 단계는 네트워크에서 생성하는 데이터의 재고를 가져오는 것입니다.

보안 컨텍스트 및 스크립트 필터링

JavaScript를 사용하는 Windows 스토어 앱용 인프라는 개발자가 신뢰할 수 없는 데이터를 불안전하게 처리할 수 있는 일반적인 보안 문제를 피할 수 있도록 설계되었습니다. 보안을 향상시키는 데 도움을 줄 수 있는 한 가지 새로운 기능은 로컬 및 웹 컨텍스트에 대한 지원입니다. 개발자는 이러한 컨텍스트를 사용하여 처음부터 앱을 원격 JavaScript와 같은 신뢰할 수 없는 콘텐츠를 앱의 패키지에 포함된 신뢰할 수 있는 코드 및 데이터와 분리하도록 설계할 수 있습니다.

표준 프레임 격리는 웹과 로컬 컨텍스트를 분리하고 컨텍스트는 콘텐츠 생성지를 기준으로 자동으로 결정됩니다. 예를 들어, ms-appx:// 프로토콜을 통해 참조된 콘텐츠는 로컬 컨텍스트 프레임에 자동으로 로드되는 반면, iframe이 로드한 원격 웹 콘텐츠는 항상 웹 컨텍스트에서 로드됩니다. 두 컨텐스트는 다른 보안 속성과 액세스 레벨(기능별 특징 및 제한사항에 설명되어 있음)을 가집니다. 두 컨텍스트는 서로 다른 액세스 레벨을 가지는 반면, postMessage 인프라를 사용하여 편리한 프레임 간 통신을 사용할 수 있습니다.

DOM 메서드의 자동 스크립트 필터링은 안전하지 않다고 간주되는 동적 콘텐츠를 삭제하고 동적 콘텐츠를 DOM에 삽입하지 못하게 하면서, 양성 마크업을 본래 그대로 유지하도록 합니다. 콘텐츠를 기존 DOM 요소에 추가할 계획이라면 innerText 또는 outerText를 사용하여 콘텐츠를 추가하는 방법이 안전합니다.

보안 경고:  innerTextouterText를 사용하여 script 요소의 텍스트를 설정할 때는 자동 스크립트 필터링이 적용되지 않습니다.

자동 스크립트 필터링은 예기치 못한 공격이 사용자에게 위해를 가하지 못하게 할 수 있는 멋진 "가드레일"이지만 이것으로만 앱을 보호해서는 안됩니다. 자동 스크립트 필터링이 콘텐츠를 차단할 때 사용자 경험에 영향을 줄 수 있는 오류를 발생시킵니다. 또한 데이터 작업을 하는 타사 라이브러리가 자동으로 필터링되지 않는 API를 사용하여 보안 문제를 유발할 수 있습니다. 자동 스크립트 필터링을 범용 방어벽으로 의존하지 않고 대신 코드 내에서 자동 관리를 수행하는 것이 좋은 방법입니다. 신뢰할 수 없는 데이터의 명시적 필터링을 수행하는 것은 앱을 안전하게 유지하는 가장 좋은 방법입니다.

invokeScriptAsync 및 postMessage 데이터 원본 유효성 검사

WebView(XAML) 및 x-ms-webview(HTML) 컨트롤에는 컨텍스트 간의 통신을 허용하는 iframepostMessage 메서드와 유사한 메서드가 있습니다. InvokeScriptAsync (XAML)invokeScriptAsync (HTML) 메서드는 Windows 스토어 앱에서 로컬 컨텍스트와 웹 컨텍스트 간에 데이터를 전송하는 기본 방법입니다.

postMessage 메서드는 JavaScript 앱을 사용하는 Windows 스토어 앱에서 로컬 콘텐츠와 웹 콘텐츠 간에 데이트를 전송하는 기본 방법입니다. 스크립트 요소를 사용하거나 여러 도메인을 해킹하여 매시업 앱(웹에 있는 다른 원본의 데이터를 결합하는 앱)을 만들지 않고, postMessage를 사용합니다. 개발자는 로컬 원본과 원격 원본 간에 프레임 기반 분리를 사용하여 지도나 광고와 같은 원격 콘텐츠를 포함하면서 동일한 원본 정책을 사용하여 문서 및 리소스 액세스를 계속 분리시킬 수 있습니다.

안전하게 postMessageinvokeScriptAsync 메서드를 사용하여 로컬 문서와 원격 문서 간에 메시지를 전달하려면 데이터를 사용하기 전에 postMessage 또는 invokeScriptAsync 응답의 원본을 확인합니다. 대부분의 앱은 원본 및 신뢰도가 각기 다른, 여러 원격 iframe 또는 WebView 요소를 포함하므로 이 작업이 반드시 필요합니다. 일반적으로 앱은 해당 페이지의 모든 iframe 또는 WebView 요소에서 생성된 메시지를 처리하는 각 페이지에 대해 단일 onmessage 처리기 기능을 사용합니다.

이 예제에서는 invokeScriptAsync (HTML) 메서드를 호출하는 방법을 보여 줍니다.


// The application is calling for a specific function inside of the webview
var asyncOp = webView.invokeScriptAsync(“startAnimation”, “500”);
    
asyncOp.oncomplete = function(e){
	// Even though the risk is less with the invokeScript message
	// still make sure not to use eval on the return value.
}

asyncOp.start();



이 예제에서는 InvokeScriptAsync (XAML) 메서드를 호출하는 방법을 보여 줍니다.


async void webview_DOMContentLoaded(WebView sender, WebViewDOMContentLoadedEventArgs args)
{
    var operation = await webview.InvokeScriptAsync("startAnimation", new string[] { "500" });

    if (operation == "success")
    {
        // Handle the message.
    }
} 


WebView 컨트롤의 보안을 향상시키기 위해 WebView 콘텐츠에서 window.external.notify() 함수를 사용할 수 있는 경우를 제한했습니다. 이러한 제한으로 인해 신뢰할 수 없는 콘텐츠 또는 변조된 콘텐츠는 호스트에 유효성을 검사하지 않고 실행된 메시지를 보낼 수 없습니다. 콘텐츠가 알림을 보낼 수 있으려면 다음 조건 중 하나가 true여야 합니다.

  • 페이지 원본이 NavigateToString, NavigateToStream 또는 ms-appx-web:///을 통해 로컬 시스템에서 제공됩니다.
  • 페이지 원본이 https://를 통해 제공되며 사이트 도메인 이름이 앱 패키지 매니페스트의 콘텐츠 URI 섹션에 나열됩니다.
예를 들면 다음과 같습니다.

webview.addEventListener("MSWebViewScriptNotify", handleScriptNotifyEvents);
function handleScriptNotifyEvents(e) {
        if (e.callingUri === "https://msgnotify.example.net/") {
            if(e.value === "msg1")
            {
                // Process the message.);
            }
        }
    }


이 예제는 onmessage 처리기의 두 버전을 보여 줍니다. 첫 번째는 보안되지 않고 두 번째는 보안됩니다.


// This message handler is not secure because it does not implement an origin check
window.addEventListener('message', function (e) { 
    div.innerHTML = window.toStaticHTML(e.data); 
}, false);

// Secure message handler, validates message domain origin 
window.addEventListener('message', function (e) {
    if (e.origin === 'http://data.contoso.com') { 
        div.innerHTML = window.toStaticHTML(e.data); 
    }
}, false);


대부분의 경우 앱은 지도 좌표를 보내는 한 두 가지 iframe 요소에서의 메시지 또는 기타 합법적인 매시업 콘텐츠는 승인하지만,광고나 답변 스트림과 같은 신뢰할 수 없는 항목에서의 다른 메시지 콘텐츠는 거부합니다. 원본으로 메시지를 필터링하는 방법은 앱의 공격 면을 줄이고 신뢰할 수 없는 데이터는 거부되도록 하는 멋진 방법입니다. 언제 onmessage 이벤트를 처리하더라도, 데이터의 원본을 확인하세요.

자동 스크립트 필터링

항상 신뢰할 수 없는 데이터 원본에서 스크립트 필터링 및 유효성 검사를 수행합니다. 데이터의 유효성을 검사하는 방법은 데이터의 용도에 따라 달라집니다. 간단한 단순 데이터를 DOM에 추가하려면 동적 요소를 무시하는 DOM API를 사용하세요. 데이터의 스크립트 또는 동적 요소는 코드로 해석되지 않고 단순 텍스트로 표시되므로, 이러한 접근방식을 사용하여 콘텐츠를 안전하게 표시할 수 있습니다. createTextNode와 같은 메서드를 사용하여 신뢰할 수 없는 데이터로 원본을 채울 수 있으며, 그런 다음 appendChild 또는 importNode를 호출하여 .문서 DOM에 추가할 수 있습니다. 콘텐츠를 기존 DOM 요소에 추가할 계획이라면 innerText 또는 outerText을 사용하여 콘텐츠를 추가하는 방법이 안전합니다.

이 예제는 안전하지 않는 방법으로 동적 콘텐츠를 추가합니다.



// Do not use this code.
// Avoid adding untrusted dynamic content
// Unsafe method 1
var myDiv = document.createElement("div");
myDiv.innerHTML = xhr.responseText 
document.body.appendChild(myDiv);

// Unsafe method 2
document.writeln(xhr.responseText);


다음 예제는 콘텐츠를 추가하는 보안 방법을 나타냅니다.



// Forcing untrusted content into static text is safe

// method 1
var myDiv = document.createElement("div");
myDiv.innerText = xhr.responseText 
document.body.appendChild(myDiv);

// method 2
var myData = document.createTextNode(xhr.responseText);
document.body.appendChild(myData);

// method3
var oDiv = document.getElementById("div1");
oDiv.outerText = xhr.responseText;



신뢰할 수 없는 데이터가 마크업을 포함할 때 window.toStaticHTML DOM 메서드를 사용하여 안전하지 않은 마크업을 필터링하면서 안전한 데이터는 본래 그대로 유지합니다.


// The untrusted data contains unsafe dynamic content
var unTrustedData = "<img src='http://www.contoso.com/logo.jpg' on-click='calltoUnsafeCode();'/>";

// Safe dynamic content can be added to the DOM without introducing errors
var safeData = window.toStaticHTML(unTrustedData);

// The content of the data is now 
// "<img src='http://www.contoso.com/logo.jpg'/>" 
// and is safe to add because it was filtered
document.write(safeData);



자동 스크립트 필터링 바이패스

동적 마크업을 삽입할 수 있는 DOM API는 자동으로 필터링되지만, eval과 같은 명시적 실행 입력은 그렇지 않습니다. eval을 사용하여 자동 필터링을 바이패스하고 안전하다고 생각하는 동적 스크립트를 실행할 수 있습니다. 다음은 시스템이 안전하지 않은 콘텐츠를 자동으로 필터링하지 않는 스크립트 실행 메서드 목록입니다.

시스템은 이러한 메서드에 자동 필터링을 제공하므로, 사용자가 직접 신뢰할 수 없는 데이터를 먼저 필터링하거나 인코딩하지 않고 이러한 데이터를 실행할 경우에는 이러한 메서드를 사용하지 마세요.

MSApp.execUnsafeLocalFunction API는 일반적으로 로컬 컨텍스트의 동적 마크업 콘텐츠에 적용되는 자동 스크립트 필터링을 바이패스하는 기능을 활성화합니다. 이것은 자동 필터링으로 지연되는 JQuery와 같은 마크업 생성 템플릿을 사용하려고 할 때 유용합니다.

eval 메서드를 사용하는 경우처럼, MSApp.execUnsafeLocalFunction을 사용하여 신뢰할 수 없는 데이터 원본을 처리할 경우 보안 문제가 초래할 수 있습니다. 템플릿 라이브러리는 내부적으로 신뢰할 수 없는 데이터를 문서에 작성할 수 있으므로, 보안 문제가 일어날 수 있습니다 데이터 원본이 의심스러울 때는 안전한 인코딩 라이브러리 또는 toStaticHTML 메서드를 사용하여 안전하지 않은 요소 및 코드에서 데이터를 제거하도록 합니다.

보안 구문 분석기 사용

JavaScript eval 메서드를 사용하여 서버측 JSON(JavaScript Object Notation) 응답에서 로컬 JavaScript 개체를 생성하는 것은 일반적이지만, 위험한 웹 개발 방법입니다. 이 예제는 eval 메서드를 선택하여 JSON 데이터를 사용합니다.


<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div id="foo"></div>
    <script type="text/javascript">
        var xhr = new XMLHttpRequest();
        xhr.open("GET", "http://contoso.com/json.js", false);
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                if (xhr.status == 200) {

			                 // DO NOT USE, UNSAFE
                    var myObject = eval('(' + xhr.responseTxt + ')');
                }
            }
        };
        xhr.send();
     </script>
</body>
</html>


공격자가 활성 도청을 사용하여 eval 메서드로 전달하는 데이터를 조작하는 경우 보안 문제가 발생할 수 있습니다. eval을 사용하는 대신, JSON.parse DOM 메서드를 사용하여 JSON 텍스트를 개체로 변환합니다. JSON.parse 메서드는 공격을 가할 수 있는 비JSON 스크립트를 거부합니다.

다음 예제는 eval 대신 JSON.parse 메서드를 사용합니다.


<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div id="foo"></div>
    <script type="text/javascript">
        var xhr = new XMLHttpRequest();
        xhr.open("GET", "http://remote-server.com/json.js", false);
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                if (xhr.status == 200) {
                    var myObject = JSON.parse(xhr.responseText);
                }
            }
        };
        xhr.send();
     </script>
</body>
</html>
</body>
</html>



중요한 데이터 보호

앱이 중요한 데이터를 적절하게 처리하는 지 확인하세요. 인터넷 연결이 제대로 작동 중인지 확인합니다. 사용자 데이터를 안전하게 유지관리하려면 중요한 데이터를 원격 서버로 돌려보내거나 전달할 때마다 SSL를 사용하세요. 보안 공격 도구를 광범위하게 사용할 수 있습니다. 악의적 의도를 가진 측이 불가피하게 SSL을 사용하지 않고 있는 앱을 공격하여 개인 데이터를 해석할 수 있도록 하려고 한다고 가정합시다.

개인정보 보호 외에 SSL은 응용 프로그램의 무결성 이점을 제공합니다. SSL은 공격자가 JSON 또는 기타 네트워크 데이터 스트림을 조작하지 못하도록 합니다. 네트워크 데이터를 Windows 런타임 API로 전달할 때 이러한 API가 사용자의 시스템에 액세스할 수 있으므로, 트래픽의 무결성을 보호하는 것이 중요합니다.

HTTPS 연결 필수

모든 원격 콘텐츠를 HTTPS(Secure Hypertext Transfer Protocol)를 통해 송신 및 수신할 수 있게 하는 것이 쉽습니다. 간단한 HTML 메타 태그를 다음과 같은 시작 페이지에 추가하면 됩니다.


<meta name="ms-https-connections-only" content="true"/>

이 메타태그를 추가하면 비HTTPS 탐색이 오류를 발생시키고 사용자가 DNS(Domain Name System) 캐시 악성 또는 ARP(Address Resolution Protocol) 캐싱 스푸핑과 같은 연결을 조작하지 못하게 합니다.

JavaScript를 사용하는 Windows 스토어 앱은 기존 PKI 인프라가 없는 개발자에 대해 응용 프로그램 패키지와 함께 묶는 개인 인증서를 지원합니다.

XDomainRequest 사용

일반적인 브라우저와 달리, JavaScript로 작성한 Windows 스토어 앱의 로컬 스크립트 및 태그는 XMLHttpRequest를 사용할 때 웹 서비스에 대한 도메인 간 액세스를 무제한 허용했습니다. 기본적으로, XMLHttpRequest은 웹 서비스와 상호 작용하거나 JSON 데이터를 획득할 때 지정된 사이트에 대한 쿠키 인증 요청을 작성합니다. 도메인 간 요청에 쿠키를 사용할 경우 두 가지 보안 취약성이 야기됩니다.

  • 앱이 손상된 경우 공격자는 로컬 컨텍스트에 인증된 모든 사이트에 대한 쿠키에 액세스할 수 있어야 한다.
  • 비-SSL XMLHttpRequest 트래픽은 가로채기될 수 있습니다.

이러한 문제 때문에 인증된 액세스가 필요할 때만 XMLHttpRequest를 사용하고, SSL 연결에서 사용하도록 하세요. 인증된 액세스가 필요 없으면 대신 XDomainRequest을 사용합니다. XDomainRequestXMLHttpRequest와 유사한 원본 간 트래픽을 허용하지만, 쿠키 또는 참조자 헤더를 사용하지 않습니다. 이것은 도메인 간 요청의 보안 및 개인정보 보호 정책을 모두 증가시켜 전체적으로 더 안전한 앱이 되게 합니다.

탐색 도메인 제한

앱의 탐색 도메인은 앱 패키지 내부에 있는 앱 매니페시트에 의해 설정됩니다. 공격자가 사용자의 응용 프로그램 세션을 제어할 수 있는 도메인으로 리디렉션하여 피싱 공격이나 기타 유해 활동을 수행할 수 있는 가능성을 피하기 위해 가능한 탐색 도메인 목록을 제한하는 것이 중요합니다.

대형 웹 서비스의 많은 하위 도메인은 공격자가 이용할 수 있는 임의 페이지 또는 기타 콘텐츠를 호스트하는 기능을 제공하므로, 간단한 모범 사례에서는 와일드카드 사용을 피합니다. 자세한 내용은 ApplicationContentUriRules를 참조하세요.

가능한 경우 WebView 컨트롤 사용

WebView 컨트롤에는 기존 iframe보다 많은 보안 조치가 적용되어 있으므로 이 컨트롤을 이용하여 웹 콘텐츠를 호스트하면 임의 웹 콘텐츠로 인한 앱 코드 손상 가능성이 최소화됩니다. WebView는 HTML/JavaScript로 작성한 Windows 스토어 앱과 XAML로 작성한 Windows 스토어 앱에 대해 동일한 보안 기능을 제공합니다. 패키지 매니페스트에 ApplicationContentUriRules를 사용하면 개발자가 WebView 컨트롤과 호스팅 앱 간의 통신을 허용할 수 있습니다. 또한 로컬 콘텐츠와 통신하는 방법도 있습니다. 통신에 대한 자세한 내용은 Windows 8.1 WebView의 새로운 기능HTML x-ms-webview를 사용하여 앱 및 사이트 혼합을 참조하세요.

가능한 곳에서 HTML5 샌드박스 특성 사용

HTML5 iframe sandbox 특성은 iframe의 콘텐츠에 추가 제한사항을 부과합니다. JavaScript 환경을 사용하는 표준 Windows 스토어 앱이 콘텐츠 원본을 기준으로 특정 보안 보호를 제공하더라도, sandbox 특성은 추가 방어층을 제공합니다. 이 특성은 개발자가 페이지 내에서 광고나 기타 임의 콘텐츠와 같은 신뢰할 수 없는 콘텐츠를 제한하는 데 도움을 줍니다. sandbox 특성을 추가하면 콘텐츠를 다음과 같이 하지 못합니다.

  • 상위 페이지의 DOM에 액세스
  • 스크립트 실행
  • 양식 포함하기
  • 쿠키 읽기 또는 쓰기
  • 로컬 저장소 액세스
  • 로컬 SQL 데이터베이스 액세스

샌드박스 특성을 사용하여 웹 콘텐츠의 액세스를 사용자의 앱으로 제한함으로써 앱 보안을 크게 증가시킬 수 있습니다.

관련 항목

컨텍스트별 기능 및 제한 사항
가젯 검사
사이트 간 스크립팅 라이브러리 방지
postMessage
invokeScriptAsync (HTML)
InvokeScriptAsync (XAML)

 

 

표시:
© 2014 Microsoft