X-Content-Type-Options
사용법
MIME 스니핑은 브라우저가 응답의 내용을 살펴보고 응답 본문에서 발견한 패턴을 근거로 선언된 Content-Type을 무시하는 동작입니다. 잘못 구성된 서버를 위한 편의 기능으로 의도되었지만, MIME 스니핑은 보안 구멍을 엽니다. 공격자가 이미지로 위장한 파일을 업로드하면 브라우저가 그 내용을 HTML이나 JavaScript로 스니핑하여 교차 사이트 스크립팅 공격이 실행됩니다.
X-Content-Type-Options 헤더가 이 구멍을 막습니다. nosniff로 설정되면 브라우저는 Content-Type 헤더를 엄격히 따르며, 선언된 타입이 기대되는 타입과 맞지 않는 리소스의 로드를 거부합니다. 스타일 용도에서는 Content-Type이 text/css가 아니면 브라우저가 응답을 차단합니다. 스크립트 용도에서는 Content-Type이 유효한 JavaScript MIME 타입이 아니면 브라우저가 응답을 차단합니다.
이 헤더는 표준적인 보안 강화 조치로 널리 배포되어 있으며, 심층 방어를 위해 Content-Security-Policy, X-Frame-Options와 함께 사용하기를 권장합니다.
nosniff
nosniff는 정의된 유일한 값입니다. 이 디렉티브를 설정하면 브라우저가 응답을 선언된 Content-Type에서 벗어나 MIME 스니핑하는 것을 막습니다.
예시
MIME 스니핑을 비활성화한 채 JSON API 응답을 전달하는 서버로, 브라우저가 응답을 엄격히 JSON으로 취급하도록 보장합니다.
Content-Type: application/json
X-Content-Type-Options: nosniff
올바른 Content-Type과 스니핑 보호를 함께 제공하는 CSS 파일로, 브라우저가 파일을 재해석하지 못하게 막습니다.
Content-Type: text/css
X-Content-Type-Options: nosniff
문제 해결
nosniff에 의해 차단된 리소스는 선언된 Content-Type과 해당 리소스 용도에 기대되는 타입이 맞지 않는다는 MIME 타입 불일치 콘솔 오류를 냅니다.
MIME 타입 불일치로 스크립트가 차단됩니다. 브라우저가 Refused to execute script from ’…’ because its MIME type (‘text/plain’) is not executable 을 기록합니다. 이는 서버가 JavaScript 파일을 유효한 JavaScript MIME 타입(text/javascript, application/javascript)이 아닌 Content-Type으로 보낼 때 발생합니다. 서버 설정을 고치십시오. nginx에서는 http 블록에 include mime.types; 가 있는지 확인하십시오. Apache에서는 설정이나 .htaccess에 AddType text/javascript .js 가 있는지 확인하십시오.
nosniff 상태에서 잘못된 MIME 타입 때문에 CSS가 적용되지 않습니다. 콘솔에 Refused to apply style from ’…’ because its MIME type (‘text/html’) is not a supported stylesheet MIME type 이 표시됩니다. 서버가 CSS 파일을 text/css 대신 text/html이나 text/plain으로 보내고 있는 것입니다. nginx에서는 types { text/css css; } 를 추가하거나 기본 mime.types 파일을 포함시키면 불일치가 해소됩니다. Apache에서는 서버 설정에 AddType text/css .css 를 추가하십시오.
서버가 정적 파일에 잘못된 Content-Type을 보냅니다. 잘못 구성된 서버, CDN, 객체 스토리지(S3, GCS)는 정적 파일을 application/octet-stream이나 text/plain으로 제공하는 경우가 많습니다. DevTools의 Network 탭에서 요청을 선택해 응답 헤더를 살펴보며 각 리소스의 Content-Type을 확인하십시오. S3에서는 업로드 시 ContentType 메타데이터를 설정하십시오. CDN이 제공하는 애셋에서는 대부분의 CDN이 오리진의 Content-Type을 그대로 전달하므로 오리진이 올바른 타입을 반환하는지 확인하십시오.
DevTools 콘솔에서 차단된 리소스 진단하기. Console 탭을 열고 MIME 관련 오류로 필터링하십시오. 차단된 리소스 메시지마다 URL, 선언된 MIME 타입, 기대되는 타입이 들어 있습니다. Network 탭과 교차 확인하십시오. 차단된 요청을 선택하고 Headers 패널을 열어 Content-Type 응답 헤더를 점검하십시오. 해결책은 언제나 nosniff 헤더를 제거하는 것이 아니라 서버에서 Content-Type을 바로잡는 것입니다.
설정
모든 응답에 nosniff를 적용하십시오. 부담은 무시할 만한 수준이고 보호 범위는 스크립트, 스타일, 기타 하위 리소스를 아우릅니다.
nginx:
add_header X-Content-Type-Options nosniff always;
Apache:
Header always set X-Content-Type-Options nosniff
IIS (web.config):
<code class="language-xml"><customHeaders>
<add name="X-Content-Type-Options"
value="nosniff" />
</customHeaders>