World Wide Web의 보안 정책은 동일 출처 정책에 뿌리를 두고 있습니다. 예를 들어 www.jb51.net의 코드는 www.jb51.net의 데이터에만 액세스할 수 있지만 http://www.baidu.com에 대한 액세스 권한은 없습니다. 각 원본은 네트워크의 나머지 부분과 격리되어 개발자를 위한 안전한 샌드박스를 생성합니다. 이는 이론적으로는 완벽하지만 이제 공격자들은 이 시스템을 손상시킬 수 있는 영리한 방법을 찾아냈습니다.
이는 허위 콘텐츠 및 유인 클릭을 통해 동일 출처 정책을 우회하는 XSS 크로스 사이트 스크립팅 공격입니다. 이는 큰 문제이며, 공격자가 코드 삽입에 성공하면 상당한 양의 사용자 데이터가 유출될 수 있습니다.
이제 이러한 위험을 완화하기 위한 새롭고 효과적인 보안 방어 전략인 콘텐츠 보안 정책(CSP)을 소개합니다.
소스 화이트리스트
XSS 공격의 핵심은 브라우저가 스크립트가 제3자에 의해 삽입되었는지 아니면 실제로 애플리케이션의 일부인지 구별할 수 없다는 것입니다. 예를 들어, Google 1 버튼은 https://apis.google.com/js/plusone.js에서 코드를 로드하고 실행하지만 브라우저의 그림에서는 코드가 실제로 apis.google에서 왔는지 확인할 수 없습니다. .com , 다시 apis.evil.example.com에서 가져옵니다. 브라우저는 원본에 관계없이 페이지 요청 시 임의의 코드를 다운로드하고 실행합니다.
CSP는 서버에서 제공하는 모든 콘텐츠를 맹목적으로 신뢰하는 대신 브라우저가 이러한 소스의 리소스만 실행하고 렌더링하도록 신뢰할 수 있는 소스의 화이트리스트를 생성할 수 있도록 Content-Security-Policy HTTP 헤더를 정의합니다. 공격자가 취약점을 찾아 스크립트를 주입하더라도 해당 소스가 화이트리스트에 포함되어 있지 않기 때문에 스크립트가 실행되지 않습니다.
위의 Google 1 버튼을 예로 들면, apis.google.com이 우리 자신과 마찬가지로 유효한 코드를 제공한다고 믿기 때문에 브라우저가 다음 두 가지 중 하나의 스크립트만 실행하도록 허용하는 정책을 정의할 수 있습니다. 소스.
Content-Security-Policy:script-src 'self' https://apis.google.com
아주 간단하지 않나요? script-src는 지정된 페이지에 대한 스크립트 관련 권한을 제어할 수 있습니다. 이렇게 하면 브라우저는 http://apis.google.com 및 이 페이지 자체에서만 스크립트를 다운로드하고 실행합니다.
이 전략을 정의하면 브라우저는 삽입된 코드를 감지할 때 오류를 발생시킵니다(어떤 브라우저인지 확인하세요).
콘텐츠 보안 정책은 일반적으로 사용되는 모든 리소스에 적용됩니다.
스크립트 리소스가 가장 명백한 보안 위험이지만 CSP는 페이지에서 다음과 같은 다양한 유형의 리소스 로드를 제어할 수 있는 풍부한 지침 세트도 제공합니다. 다음 유형 :
content-src: 연결 유형을 제한합니다(예: XHR, WebSockets 및 EventSource)
font-src: 웹 글꼴의 소스를 제어합니다. 예를 들어 Google의 웹 글꼴은 Font-src https://themes.googleusercontent.com을 통해 사용할 수 있습니다.
frame-src: 삽입할 수 있는 프레임의 소스를 나열합니다. 예를 들어, frame-src https://youtube.com은 YouTube 동영상 삽입만 허용합니다. .
img-src: 로드 가능한 이미지의 소스를 정의합니다.
media-src: 비디오 및 오디오 소스를 제한합니다.
object-src: Flash 및 기타 플러그인의 소스를 제한합니다.
style-src: Script-src와 유사하지만 CSS 파일에만 적용됩니다.
기본적으로 모든 설정은 아무런 제한 없이 켜져 있습니다. 여러 지시문을 세미콜론으로 구분할 수 있지만 script-src https://host1.com;script-src https://host2.com 형식에서는 두 번째 지시문이 무시됩니다. 올바른 작성 방법은 script-src https://host1.com https://host2.com 입니다.
예를 들어 콘텐츠 전송 네트워크(CDN, 예: https://cdn.example.net)에서 모든 리소스를 로드해야 하는 애플리케이션이 있고, 필요하지 않은 콘텐츠가 없다는 것을 알고 있는 경우 프레임이나 플러그인에 관계없이 전략은 다음과 같을 수 있습니다.
Content-Security-Policy:default-src https://cdn.example.net;
세부 정보
예시에서 사용하는 HTTP 헤더는 Content-Security-Policy이지만 최신 브라우저는 이미 접두사를 통해 지원을 제공합니다. Firefox는 x-Content-Security-Policy를 사용하고 WebKit은 X-WebKit-CSP를 사용합니다. 앞으로는 통일된 표준으로 점진적으로 전환될 것입니다.
각 페이지에 따라 전략을 설정할 수 있어 유연성이 뛰어납니다. 사이트의 일부 페이지에는 Google 1 버튼이 있을 수 있고 다른 페이지에는 없을 수도 있기 때문입니다.
각 지시어의 소스 목록은 매우 유연할 수 있습니다. 패턴(data:, https:)을 지정하거나 범위(example.com, 모든 원본, 패턴 및 포트와 일치)의 호스트 이름을 지정할 수 있습니다. 호스트에서) 또는 전체 URI(https://example.com:443, 특히 https 프로토콜, example.com 도메인 이름, 포트 443)를 지정합니다.
소스 목록에서 사용할 수 있는 키워드가 4개 더 있습니다.
"none": 아무것도 일치하지 않을 것으로 예상할 수 있습니다.
"self": 현재 소스와 동일하지만 하위 도메인이 없습니다.
"unsafe- inline ": 인라인 Javascript 및 CSS 허용
"unsafe-eval": eval과 같은 텍스트-JS 메커니즘 허용
이러한 키워드는 따옴표로 묶어야 합니다.
샌드박스
여기서 논의할 만한 또 다른 지시문이 있습니다. 바로 샌드박스입니다. 이는 페이지가 로드할 수 있는 리소스보다는 주로 페이지에서 수행되는 작업을 제어하는 다른 지침과 다소 일치하지 않습니다. 이 속성이 설정되면 페이지는 샌드박스 속성이 설정된 프레임처럼 동작합니다. 이는 양식 제출 방지 등 페이지에 광범위한 영향을 미칩니다. 이는 이 기사의 범위를 약간 벗어나지만 HTML5 사양의 "샌드박스 플래그 설정" 장에서 자세한 내용을 확인할 수 있습니다.
유해한 인라인 코드
CSP는 소스 화이트리스트를 기반으로 하지만 XSS 공격의 가장 큰 원인인 인라인 스크립트 삽입을 해결하지 못합니다. 공격자가 유해한 코드가 포함된 스크립트 태그(
)를 삽입할 수 있는 경우 브라우저에는 이 태그를 구별할 수 있는 좋은 메커니즘이 없습니다. CSP는 인라인 스크립트를 완전히 비활성화해야만 이 문제를 해결할 수 있습니다. 이 금지 사항에는 스크립트에 포함된 스크립트 태그뿐만 아니라 인라인 이벤트 핸들러 및 javascrpt: URL도 포함됩니다. script 태그의 내용을 외부 파일에 넣고 javascript: 및
을 적절한 addEventListener 메소드로 바꿔야 합니다. 예를 들어
Am I amazing?
형식을
나 정말 대단해?
// amazing.js
function doAmazingThings() {
Alert('YOU AM AMAZING!');
}
문서. addEventListener('DOMContentReady', function () {
document.getElementById('amazing')
.addEventListener('click', doAmazingThings);
});
CSP 사용 여부에 관계없이 위의 코드는 실제로 더 큰 장점을 가지고 있습니다. 인라인 JavaScript는 구조와 동작을 완전히 혼합하므로 그렇게 해서는 안 됩니다. 또한 외부 리소스는 브라우저에서 캐시하기 쉽고, 개발자가 이해하기 쉽고, 컴파일 및 압축하기가 더 쉽습니다. 외부 코드를 사용하면 더 나은 코드를 작성할 수 있습니다.
인라인 스타일은 동일한 방식으로 처리해야 하며, 스타일 속성과 스타일 태그를 모두 외부 스타일 시트로 추출해야 합니다. 이는 모든 종류의 마법같은 데이터 유출을 방지합니다.
인라인 스크립트와 스타일이 있어야 하는 경우 script-src 또는 style-src 속성에 'unsafe-inline 값'을 설정할 수 있습니다. 하지만 이렇게 하지 마세요. 인라인 스크립트를 비활성화하는 것은 CSP가 제공하는 최고의 보안 보장입니다. 인라인 스타일을 비활성화하면 애플리케이션이 더욱 안전하고 강력해집니다. 절충안이지만 그만한 가치가 있습니다.
평가
공격자가 스크립트를 직접 삽입할 수 없더라도 애플리케이션이 삽입된 텍스트를 실행 가능한 스크립트로 변환하고 자체적으로 실행하도록 속일 수 있습니다. eval() , newFunction() , setTimeout([string], ...) 및 setInterval([string], ...)은 모두 이러한 위험의 벡터가 될 수 있습니다. 이 위험에 대한 CSP의 전략은 이러한 벡터를 완전히 차단하는 것입니다.
이는 애플리케이션 구축 방식에 몇 가지 영향을 미칩니다.
eval에 의존하는 대신 내장된 JSON.parse를 통해 JSON을 구문 분석합니다. IE8 이후의 브라우저는 완전히 안전한 로컬 JSON 작업을 지원합니다.
문자열 대신 인라인 함수를 사용하여 setTimeout 및 setInterval을 호출하는 방식을 다시 작성하세요. 예:
setTimeout("document.querySelector('a').style.display = 'none';", 10);
다음과 같이 다시 작성할 수 있습니다.
setTimeout(function () { document. querySelector ('a').style.display = 'none' }, 10);
런타임 시 인라인 템플릿 피하기: 많은 템플릿 라이브러리는 템플릿 생성 속도를 높이기 위해 new Function()을 사용합니다. 이는 동적 프로그램에는 적합하지만 악성 텍스트에는 위험합니다.
보고서
서버 측에서 신뢰할 수 없는 리소스를 차단하는 CSP의 기능은 사용자에게 좋지만, 악성 스크립트 삽입을 식별하고 수정할 수 있도록 서버로 전송되는 다양한 알림을 받는 것도 좋습니다. 이를 위해, report-uri 지시문을 통해 JSON 형식의 차단 보고서를 특정 주소로 보내도록 브라우저에 지시할 수 있습니다. <script>sendMyDataToEvilDotCom();</script>콘텐츠 보안 정책: default-src 'self' ...;보고서는 다음과 같습니다:
{
"csp-report": {
"document-uri": "http://example.org/page.html",
"referrer " : "http://evil.example.com/",
"blocked-uri": "http://evil.example.com/evil.js",
"violated-directive": " 스크립트 -src 'self' https://apis.google.com",
"original-policy": "script-src 'self' https://apis.google.com http:// 예 .org/my_amazing_csp_report_parser"
}
}
여기에 포함된 정보는 차단이 발생한 페이지(document-uri), 해당 페이지의 리퍼러, 페이지 정책(blocked-uri), 위반-지시문 및 페이지의 모든 콘텐츠 보안 정책(original-policy)을 위반하는 리소스입니다.
실제 사용
CSP는 이제 Chrome 16 및 Firefox 4에서 사용할 수 있으며 IE10에서는 지원이 제한될 것으로 예상됩니다. Safari는 아직 이를 지원하지 않지만 WebKit의 야간 빌드를 사용할 수 있으므로 Safari가 다음 반복에서 이를 지원할 것으로 기대합니다.
몇 가지 일반적인 사용 사례를 살펴보겠습니다.
실제 사례 1: 소셜 미디어 위젯
Google 1 버튼에는 https://apis.google.com의 스크립트가 포함되어 있으며 plusone용 https:// iframe에서 삽입됩니다. .google.com. Google 1 버튼을 사용하려면 전략에 이러한 소스가 포함되어야 합니다. 가장 간단한 전략은 script-src https://apis.google.com입니다. 또한 Google에서 제공하는 JS 스니펫이 외부 JS 파일에 저장되어 있는지 확인해야 합니다.
Facebook의 좋아요 버튼을 구현하는 솔루션은 다양합니다. 사이트의 나머지 부분과 잘 분리되어 있으므로 iframe 버전을 계속 사용하는 것이 좋습니다. 이를 위해서는 Frame-src https://facebook.com 지시문을 사용해야 합니다. 기본적으로 Facebook에서 제공하는 iframe 코드는 상대 경로 //facebook.com을 사용하므로 이 코드를 https://facebook.com으로 변경하세요. 필요한 경우 HTTP를 사용할 수 없습니다.
Twitter의 트윗 버튼은 둘 다 https://platform.twitter.com에서 제공되는 스크립트와 프레임에 의존합니다(Twitter는 기본적으로 상대 URL을 제공하므로 복사할 때 HTTPS를 지정하도록 코드를 편집하세요).
다른 플랫폼에도 비슷한 상황이 있으므로 비슷하게 해결할 수 있습니다. default-src를 없음으로 설정한 다음 콘솔을 확인하여 위젯이 제대로 작동하는지 확인하는 데 필요한 리소스가 무엇인지 확인하는 것이 좋습니다.
여러 위젯을 사용하는 것은 매우 간단합니다. 모든 전략 지침을 병합하고 동일한 지침에 대한 설정을 함께 유지하는 것을 기억하세요. 위의 세 가지 위젯을 사용하려는 경우 전략은 다음과 같습니다.
script-src https://apis.google.com https://platform.twitter.com https:// plusone; .google.com https://facebook.com https://platform.twitter.com
실제 사례 2: 방어
은행 웹사이트를 방문하여 필요한 리소스만 로드되었는지 확인하고 싶다고 가정해 보겠습니다. 이 경우 모든 콘텐츠를 차단하는 기본 권한(default-src 'none')을 설정하고 처음부터 정책을 구축하는 것부터 시작하세요.
예를 들어 은행 웹사이트는 https://cdn.mybank.net에서 CDN의 이미지, 스타일, 스크립트를 로드하고 XHR을 통해 https://api.mybank.com/에 연결하여 다양한 데이터를 가져와야 합니다. . 또한 프레임을 사용해야 하지만 프레임은 타사 로컬 페이지에서 제공되지 않습니다. 웹사이트에는 플래시, 글꼴 및 기타 콘텐츠가 없습니다. 이 경우 보낼 수 있는 가장 엄격한 CSP 헤더는 다음과 같습니다.
Content-Security-Policy: default-src 'none'; script-src https://cdn.mybank.net https:// cdn; .mybank.net; img-src https://cdn.mybank.net; connect-src https://api.mybank.com; frame-src 'self'
실제 사례 3: SSL만 사용
결혼 반지 포럼 관리자는 모든 리소스가 안전한 방식으로 로드되기를 원하지만 실제로 너무 많은 코드를 작성하고 싶지는 않습니다. 많은 수의 타사 포럼 인라인 스크립트 및 스타일을 다시 작성하는 것은 그의 능력을 넘어서는 일입니다. 따라서 다음 정책이 매우 유용할 것입니다:
Content-Security-Policy: default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'
-src는 https를 지정하며 스크립트와 스타일은 자동으로 상속되지 않습니다. 각 지시문은 기본 리소스 유형을 완전히 재정의합니다.
미래
W3C의 웹 애플리케이션 보안 워킹 그룹은 콘텐츠 보안 정책 사양의 세부 사항을 공식화하고 있습니다. 버전 1.0이 곧 최종 개정 단계에 접어들고 있으며 이 문서에서 설명하는 내용과 매우 가깝습니다. public-webappsec@ 메일링 그룹에서는 버전 1.1에 대해 논의하고 있으며 브라우저 제조업체도 CSP 구현을 통합하고 개선하기 위해 열심히 노력하고 있습니다.
CSP 1.1에는 아트보드에 별도로 나열할 가치가 있는 몇 가지 흥미로운 기능이 있습니다.
메타 태그를 통해 정책 추가: CSP를 설정하는 기본 방법은 HTTP 헤더를 사용하는 것입니다. 이는 매우 유용하지만 태그나 스크립트를 통해 설정하는 것이 더 간단합니다. , 그러나 현재로서는 아직 확정되지 않았습니다. WebKit에서는 메타 요소를 통해 권한을 설정하는 기능을 구현했으므로 이제 Chrome에서 다음 설정을 시도해 볼 수 있습니다. 문서 헤더에
런타임에 스크립트를 통해 전략을 추가할 수도 있습니다.
DOM API: CSP의 다음 버전에 이 기능이 추가되면 Javascript를 통해 페이지의 현재 보안 정책을 쿼리하고 상황에 따라 조정할 수 있습니다. 예를 들어 eval()을 사용할 수 있는 경우 코드 구현이 약간 다를 수 있습니다. 이는 JS 프레임워크 작성자에게 매우 유용하며 API 사양은 현재 매우 불확실하므로 초안 사양의 스크립팅 인터페이스 장에서 최신 반복을 찾을 수 있습니다.
새로운 지시문: script-nonce를 포함한 많은 새로운 지시문이 논의되고 있습니다. 명시적으로 지정된 스크립트 요소만 인라인 스크립트를 사용할 수 있습니다. 이는 플러그인 유형을 제한합니다. 양식은 제출만 허용합니다. 특정 소스.
이러한 향후 기능에 대한 토론에 관심이 있다면 메일링 리스트 아카이브를 읽거나 메일링 리스트에 가입할 수 있습니다.
이 기사의 번역 출처: http://www.html5rocks.com/en/tutorials/security/content-security-policy/
출처: Jiang Yujie 블로그