1. 소개
웹의 사이트와 애플리케이션은 단일 출처의 리소스만으로 구성되는 일이 드물다. 예를 들어, 작성자는 매우 다양한 서비스와 콘텐츠 전송 네트워크에서 스크립트와 스타일을 가져오며, 전달된 표현이 실제로 자신이 로드할 것으로 기대한 것이라고 신뢰해야 한다. 공격자가 사용자를 속여 적대적 서버에서 콘텐츠를 다운로드하게 할 수 있다면 (DNS [RFC1035] 포이즈닝 또는 그 밖의 유사한 수단을 통해), 작성자는 대응할 방법이 없다. 마찬가지로, 콘텐츠 전송 네트워크(CDN) 서버의 파일을 교체할 수 있는 공격자는 임의의 콘텐츠를 삽입할 수 있다.
보안 채널을 통해 리소스를 전달하면 이러한 위험의 일부를 완화할 수 있다. TLS [TLS], HSTS [RFC6797], 그리고 고정된 공개 키 [RFC7469]를 사용하면, 사용자 에이전트는 자신이 통신한다고 믿는 서버와 실제로 통신하고 있다고 상당히 확신할 수 있다. 그러나 이러한 메커니즘은 서버만 인증할 뿐, 콘텐츠는 인증하지 않는다. 서버에 접근할 수 있는 공격자(또는 관리자)는 아무런 제약 없이 콘텐츠를 조작할 수 있다. 이상적으로는 작성자가 서버의 키만 고정할 수 있는 것이 아니라 콘텐츠도 고정하여, 리소스의 정확한 표현, 그리고 오직 그 표현만이 로드되고 실행되도록 보장할 수 있어야 한다.
이 문서는 그러한 검증 방식을 지정하며, 작성자가 로드하기를 기대하는
리소스 표현의 암호학적 해시를 포함하는 integrity 속성으로
두 HTML 요소를 확장한다. 예를 들어, 작성자는 어떤 프레임워크를 자기 출처에
호스팅하는 대신 공유 서버에서 로드하고자 할 수 있다.
https://example.com/example-framework.js의 기대되는 SHA-384 해시가
Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7라고 지정하면,
사용자 에이전트는 그 URL에서 로드한 데이터가 그 안에 포함된 JavaScript를 실행하기 전에
기대한 해시와 일치하는지 검증할 수 있다. 이
무결성 검증은 공격자가 악성 콘텐츠로 대체할 수 있는 위험을 크게 줄인다.
이 예시는 다음과 같이 해시를 script 요소에 추가하여
사용자 에이전트에 전달할 수 있다:
< script src = "https://example.com/example-framework.js" integrity = "sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7" crossorigin = "anonymous" ></ script >
물론 스크립트만이 무결성 검증의 이점을 얻을 수 있는 응답 유형은 아니다.
여기서 지정하는 방식은 link에도 적용되며,
이 명세의 향후 버전은 이 적용 범위를 확대할 가능성이 높다.
1.1. 목표
-
제3자 서비스가 손상되었다고 해서 그 스크립트를 포함하는 모든 사이트가 자동으로 손상되어서는 안 된다. 콘텐츠 작성자는 로드하는 콘텐츠에 대한 기대값을 지정할 수 있는 메커니즘을 갖게 되며, 예를 들어 특정 URL을 가지고 있는 아무 스크립트가 아니라 특정한 스크립트를 로드할 수 있게 된다.
-
검증 메커니즘은 유효하지 않은 응답이 수신되었음을 작성자에게 알려 주는 오류 보고 기능을 가져야 한다.
1.2. 사용 사례/예시
1.2.1. 리소스 무결성
-
작성자는 전 세계에 분산된 사용자의 성능을 향상하기 위해 콘텐츠 전송 네트워크를 사용하고자 한다. 그러나 CDN의 서버가 작성자가 전달하기를 기대한 코드 만을 전달하도록 보장하는 것이 중요하다. CDN 손상(또는 예기치 않은 악의적 동작)이 해당 사이트를 바람직하지 않은 방식으로 변경할 위험을 완화하기 위해, 다음 무결성 메타데이터를 페이지에 포함된
link요소에 추가한다: -
작성자는 제3자 분석 서비스에서 제공하는 JavaScript를 포함하고자 한다. 신중하게 검토된 코드만 실행되도록 보장하기 위해 작성자는 해당 스크립트에 대한 무결성 메타데이터를 생성하고, 이를
script요소에 추가한다: -
사용자 에이전트는 높은 권한의 HTML 컨텍스트(예: 브라우저의 새 탭 페이지)에서 실행되는 JavaScript 코드가 표시되기 전에 조작되지 않았음을 보장하고자 한다. 무결성 메타데이터는 변경된 JavaScript가 이러한 페이지의 높은 권한 컨텍스트에서 실행될 위험을 완화한다.
2. 핵심 개념과 용어
이 절은 문서 전체에서 사용되는 여러 용어를 정의한다.
digest라는 용어는 임의의 데이터 블록에 암호학적 해시 함수를 실행한 결과를 base64로 인코딩한 것을 가리킨다.
origin 및 same origin 용어는 HTML에서 정의된다. [HTML]
base64 encoding은 RFC 4648의 4절에서 정의된다. [RFC4648]
SHA-256, SHA-384, 그리고 SHA-512는 NIST가 정의한 SHA-2 암호학적 해시 함수 집합의 일부이다. [SHA2]
valid
SRI hash algorithm token set은 순서 있는 집합
« "sha256", "sha384", "sha512" »이다(각각 SHA-256,
SHA-384, 그리고 SHA-512에 대응한다). 이 집합의 순서는
의미가 있으며, 더 강한 알고리즘이 집합의 뒤쪽에 나타난다. 추가 정보는
§ 3.2.2 우선순위 및 § 3.3.3 set에서 가장 강한
메타데이터 가져오기를 참조하라.
문자열은 그 ASCII 소문자가 valid SRI hash algorithm token set에 포함되어 있다면 valid SRI hash algorithm token이다.
2.1. 문법 개념
이 문서에서 사용하는 Augmented Backus-Naur Form (ABNF) 표기법은 RFC5234에 지정되어 있다. [ABNF]
부록 B.1은 [ABNF]의 VCHAR(출력 문자) 및 WSP (공백) 규칙을 정의한다.
Content Security Policy는 base64-value 및
hash-algorithm 규칙을 정의한다. [CSP]
3. 프레임워크
여기서 지정하는 무결성 검증 메커니즘은 본질적으로 리소스에 대해 충분히 강한 암호학적 digest를 생성하고, 그 digest를 사용자 에이전트에 전달하여 응답 검증에 사용할 수 있게 하는 과정이다.
3.1. 무결성 메타데이터
응답의 무결성을 검증하려면, 사용자 에이전트는 request의 일부로 무결성 메타데이터를 필요로 한다. 이 메타데이터는 다음 정보 조각으로 구성된다:
-
암호학적 해시 함수("alg")
-
digest ("val")
-
옵션("opt")
응답의 무결성을 검증하려면 해시 함수와 digest가 반드시 제공되어야 한다.
참고: 현재는 정의된 옵션이 없다. 그러나 명세의 향후 버전에서는 MIME 유형 [MIME-TYPES]과 같은 옵션을 정의할 수 있다.
이 메타데이터는 Content
Security Policy Level 2 명세의 4.2절에 있는 hash-source(작은따옴표 제외)와
동일한 형식으로 인코딩되어야 한다.
예를 들어, 문자열 alert('Hello, world.');만 포함하는 스크립트 리소스가 주어졌을 때,
작성자는 해시 함수로 SHA-384를 선택할 수 있다.
H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO는 그 결과로 나오는
base64 인코딩된 digest이다. 이는
다음과 같이 인코딩할 수 있다:
echo -n"alert('Hello, world.');" | openssl dgst -sha384 -binary| openssl base64 -A
3.2. 암호학적 해시 함수
적합한 사용자 에이전트는 요청의 무결성 메타데이터 일부로 사용할 SHA-256, SHA-384, 그리고 SHA-512 암호학적 해시 함수를 반드시 지원해야 하며, 이 문서의 향후 반복에서 정의되는 추가 해시 함수를 지원할 수 있다.
참고: 이 문서에서 지원되는 알고리즘은 (현재로서는!) 두 번째 원상 공격과 충돌 공격에 저항한다고 여겨진다. 지원 알고리즘 집합에 대한 향후 추가/제거는 유사한 기준을 적용하는 것이 바람직하다. § 5.2 해시 충돌 공격을 참조하라.
3.2.1. 민첩성
미래의 암호학적 발견에 대응할 수 있는 민첩성을 제공하기 위해, 여러 무결성 메타데이터 집합을 하나의 리소스에 연결할 수 있다. 예를 들어 이전 절에서 설명한 리소스는 다음 두 해시 표현 중 어느 하나로 설명될 수 있다:
sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO sha512-Q2bFTOhEALkN8hOms2FKTDLy7eugP2zFZ1T8LCvX42Fp3WoNr3bjZSAHeOsHrbV1Fu9/A0EzCinRE7Af1ofPrw==
작성자는 예를 들어 둘 다 지정하도록 선택할 수 있다:
< script src = "hello_world.js" integrity = "sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO sha512-Q2bFTOhEALkN8hOms2FKTDLy7eugP2zFZ1T8LCvX42Fp3WoNr3bjZSAHeOsHrbV1Fu9/A0EzCinRE7Af1ofPrw==" crossorigin = "anonymous" ></ script >
이 경우 사용자 에이전트는 목록에서 가장 강한 해시 함수를 선택하고, 아래 § 3.3.2 메타데이터 구문 분석 및 § 3.3.3 set에서 가장 강한 메타데이터 가져오기 알고리즘에 설명된 대로 그 메타데이터를 사용하여 응답을 검증한다.
해시 함수가 안전하지 않다고 판단되면, 사용자 에이전트는 안전하지 않은 해시 함수를 사용한 무결성 검증 지원을 폐기 예정으로 표시하고 결국 제거해야 한다. 사용자 에이전트는 폐기 예정 함수에 기반한 digest를 사용하여 응답의 유효성을 검사할 수 있다.
작성자가 오래된 사용자 에이전트에 발목 잡히지 않고 더 강한 해시 함수로 전환할 수 있도록, 지원되지 않는 해시 함수를 사용한 검증은 무결성 값이 제공되지 않은 것처럼 동작한다 (아래 § 3.3.4 bytes가 metadataList와 일치하는가? 알고리즘 참조). 작성자는 강한 해시 함수를 사용하고, 더 강한 해시 함수를 사용할 수 있게 되는 즉시 그 함수로 마이그레이션을 시작하는 것이 권장된다.
3.2.2. 우선순위
해시 알고리즘의 우선순위는 valid SRI hash algorithm token set에서 각 토큰의 순서로 지정된다. 그 집합에서 더 앞에 나타나는 알고리즘은 더 뒤에 나타나는 알고리즘보다 약하다.
현재 지정된 바에 따르면, SHA-256은 SHA-384보다 약하고, 이는 다시 SHA-512보다 약하다. 현재 이 명세는 다른 해시 알고리즘을 지원하지 않는다.
3.3. 응답 검증 알고리즘
3.3.1. algorithm을 bytes에 적용
-
result를 algorithm을 bytes에 적용한 결과로 둔다.
-
result를 base64 encoding한 결과를 반환한다.
3.3.2. 메타데이터 구문 분석
문자열 metadata가 주어져 메타데이터를 구문 분석하라는 요청을 받으면 다음 단계를 실행한다:
참고: 이 알고리즘은 사용자 에이전트가 이해하는 해시 함수를 가진 해시 표현들의 집합을 반환한다.
-
result를 빈 집합으로 둔다.
-
metadata를 공백 기준으로 분할하여 반환된 각 item에 대해:
-
expression-and-options를 item을 U+003F (?) 기준으로 분할한 결과로 둔다.
-
algorithm-expression을 expression-and-options[0]으로 둔다.
-
base64-value를 빈 문자열로 둔다.
-
algorithm-and-value를 algorithm-expression을 U+002D (-) 기준으로 분할한 결과로 둔다.
-
algorithm을 algorithm-and-value[0]으로 둔다.
-
algorithm이 valid SRI hash algorithm token이 아니면 continue한다.
-
algorithm-and-value[1]이 존재하면, base64-value를 algorithm-and-value[1]로 설정한다.
-
metadata를 순서 있는 맵 «["alg" → algorithm, "val" → base64-value]»로 둔다.
참고: 정의된
options가 없기 때문에(§ 3.1 무결성 메타데이터 참조), metadata에는 이에 대응하는 항목이 설정되지 않는다. 향후 버전에서options가 정의되면, expression-and-options[1]을options로 활용할 수 있다. -
metadata를 result에 추가한다.
-
-
result를 반환한다.
3.3.3. set에서 가장 강한 메타데이터 가져오기
-
result를 빈 집합으로, strongest를 null로 둔다.
-
set의 각 item에 대해:
-
Assert: item["
alg"]는 valid SRI hash algorithm token이다. -
result가 빈 집합이면:
-
currentAlgorithm을 strongest["
alg"]로 두고, currentAlgorithmIndex를 valid SRI hash algorithm token set에서 currentAlgorithm의 인덱스로 둔다. -
newAlgorithm을 item["
alg"]로 두고, newAlgorithmIndex를 valid SRI hash algorithm token set에서 newAlgorithm의 인덱스로 둔다. -
newAlgorithmIndex가 currentAlgorithmIndex보다 작으면, continue한다.
-
그렇지 않고 newAlgorithmIndex가 currentAlgorithmIndex보다 크면:
-
strongest를 item으로 설정한다.
-
result를 « item »로 설정한다.
-
-
그렇지 않으면 newAlgorithmIndex와 currentAlgorithmIndex는 같은 값이다. item을 result에 추가한다.
-
-
result를 반환한다.
3.3.4. bytes가 metadataList와 일치하는가?
-
parsedMetadata를 metadataList를 구문 분석한 결과로 둔다.
-
parsedMetadata가 빈 집합이면 비어 있음,
true를 반환한다. -
metadata를 parsedMetadata에서 가장 강한 메타데이터를 가져온 결과로 둔다.
-
metadata의 각 item에 대해:
-
algorithm을 item["alg"]로 둔다.
-
expectedValue를 item["val"]로 둔다.
-
actualValue를 algorithm을 bytes에 적용한 결과로 둔다.
-
actualValue가 expectedValue와 대소문자를 구분하여 일치하면,
true를 반환한다.
-
-
false를 반환한다.
이 알고리즘은 사용자 에이전트가 여러 개의 유효한 강한 해시 함수를 허용할 수 있게 한다.
예를 들어 개발자는 다음과 같은 script 요소를 작성할 수 있다:
< script src = "https://example.com/example-framework.js" integrity = "sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7 sha384-+/M6kredJcxdsqkczBUjMLvqyHb1K/JThDXWsBVxMEeZHEaMKEOEct339VItX1zB" crossorigin = "anonymous" ></ script >
이는 사용자 에이전트가 서로 다른 두 콘텐츠 페이로드를 허용할 수 있게 하며, 그중 하나는 첫 번째 SHA-384 해시 값과 일치하고 다른 하나는 두 번째 SHA-384 해시 값과 일치한다.
참고: 사용자 에이전트는 사용자 기본 설정, bookmarklet, 사용자 에이전트에 대한 제3자 추가 기능 및 기타 유사한 메커니즘을 통해 사용자가 이 알고리즘의 결과를 수정할 수 있도록 허용할 수 있다. 예를 들어 HTTPS Everywhere와 같은 확장이 생성한 리디렉션은, 리소스의 HTTPS 버전이 HTTP 버전과 다르더라도 올바르게 로드되고 실행될 수 있다.
참고: Subresource Integrity는 CORS를 필요로 하며, CORS 없이 사용하려고 시도하는 것은 논리적 오류이다. 사용자 에이전트는 이 실패를 설명하기 위해 개발자 콘솔에 경고 메시지를 보고하는 것이 권장된다. [Fetch]
3.4. HTML 문서 하위 리소스의 검증
여러 HTML 요소는 문서에 삽입되거나 그 컨텍스트에서 실행될 리소스에 대한 요청을
발생시킨다. 이러한 요소 중 일부에 대한 무결성 메타데이터를 지원하기 위해,
link 및 script 요소의 콘텐츠 속성 목록에 새로운
integrity 속성이 추가된다. [HTML]
참고: 이 명세의 향후 개정판은
가능한 모든 하위 리소스, 즉 a, audio, embed,
iframe, img,
link, object, script, source, track, 및
video 요소에 대한 무결성 지원을 포함할 가능성이 높다.
3.5. integrity 속성
integrity 속성은 요소의 무결성 메타데이터를 나타낸다.
이 속성의 값은 빈 문자열이거나, 다음 ABNF 문법으로 설명되는 하나 이상의
유효한 메타데이터여야 한다:
integrity-metadata = *WSP hash-with-options *(1*WSP hash-with-options ) *WSP / *WSP
hash-with-options = hash-expression *("?" option-expression)
option-expression = *VCHAR
hash-expression = hash-algorithm "-" base64-value
option-expression은 각 hash-expression별로 연결되며,
바로 앞에 있는 hash-expression에만 적용된다.
사용자 에이전트가 향후 옵션과 완전한 전방 호환성을 유지하려면,
사용자 에이전트는 인식하지 못한 모든 option-expression을 무시해야 한다.
참고: option-expression은 구문에서
예약되어 있지만, 정의된 옵션은 없다는 점에 유의하라. 명세의 향후 버전에서
옵션에 대해 더 구체적인 구문을 정의할 가능성이 높으므로, 여기서는 가능한 한
넓게 정의한다.
3.6.
integrity 링크 처리 옵션
무결성 메타데이터는
요소의 integrity 속성에 적용되는 것과 동일한
integrity-metadata 문법을 사용하여
지정해야 하는 integrity 링크 매개변수로,
`link`
HTTP 응답 헤더에도 지정할 수 있다. 예:
Link: </style.css>; rel=preload; as=style; crossorigin="anonymous"; integrity="sha256-[digest goes here]"
3.7. 무결성 위반 처리
사용자 에이전트는 무결성 검사에 실패한 응답을 렌더링하거나 실행하는 것을 거부하고, 대신 Fetch에 정의된 network error를 반환한다 [Fetch].
참고: 무결성 검사 실패 시 error
이벤트가 발생한다. 표준 fallback 리소스(예: CDN에서 제공되지 않는 리소스, 아마도 보조적이고
신뢰할 수 있지만 더 느린 출처의 리소스)를 제공하려는 개발자는 이 error 이벤트를
포착하고 실패한 리소스를 다른 리소스로 교체하는 적절한 핸들러를 제공할 수 있다.
3.8. Integrity-Policy
Integrity-Policy 및 Integrity-Policy-Report-Only HTTP 헤더는 문서가
특정 destinations의 모든 하위 리소스를 로드할 때
무결성 메타데이터 요구사항에 관한 정책을 시행할 수 있게 한다.
헤더의 값은 Dictionary [RFC9651]이며, 각 member-value는 inner list 형태의 tokens이다.
source는 문자열이다. 가능한
유일한 값은 "inline"이다.
destination은 destination type이다. 가능한 값은
"script"와 "style"이다.
integrity policy는 다음을 포함하는 struct이다:
-
sources, 초깃값이 빈 source들의 목록.
-
blocked destinations, 초깃값이 빈 destination들의 목록.
-
endpoints, 초깃값이 빈 문자열들의 list.
header list headers와 header name headerName가 주어진 상태에서 무결성 정책을 처리할 때에는 다음을 수행한다:
-
integrityPolicy를 새 integrity policy로 둔다.
-
dictionary를 headers에서 headerName과 "
dictionary"가 주어졌을 때 structured field value를 가져온 결과로 둔다. -
dictionary["
sources"]가 존재하지 않거나 그 값이 "inline"을 포함하면, "inline"을 integrityPolicy의 sources에 추가한다. -
dictionary["
blocked-destinations"]가 존재하면:-
그 값이 "
script"를 포함하면, "script"를 integrityPolicy의 blocked destinations에 추가한다. -
그 값이 "
style"을 포함하면, "style"을 integrityPolicy의 blocked destinations에 추가한다.
-
-
dictionary["
endpoints"]가 존재하면:-
integrityPolicy의 endpoints를 dictionary['endpoints']로 설정한다.
-
-
integrityPolicy를 반환한다.
Integrity-Policy: blocked-destinations=(script), endpoints=(integrity-endpoint)차단은 "
integrity-endpoint" 보고 엔드포인트에도 보고를 트리거한다
(관련 Reporting-Endpoints 헤더로 정의됨).
개발자는 "integrity-violation"에 대해 ReportingObserver를 등록하여
JavaScript 기반
보고를 받을 수도 있다.
3.8.1. Integrity-Policy 헤더 구문 분석
Response response와 policy container container가 주어졌을 때 Integrity-Policy 헤더를 구문 분석하려면 다음을 수행한다:-
headers를 response의 header list로 둔다.
-
headers가
integrity-policy를 포함하면, 해당 header value로 무결성 정책 처리를 실행한 결과를 container의 integrity policy로 설정한다. -
headers가
integrity-policy-report-only를 포함하면, 해당 header value로 무결성 정책 처리를 실행한 결과를 container의 report only integrity policy로 설정한다.
3.8.2. 요청이 Integrity Policy에 의해 차단되어야 하는가
request request가 주어졌을 때, 요청이 무결성 정책에 의해 차단되어야 하는지를 결정하려면 다음을 수행한다:-
policyContainer를 request의 policy container로 둔다.
-
parsedMetadata를 request의 integrity metadata로 parse metadata를 호출한 결과로 둔다.
-
parsedMetadata가 빈 집합이 아니고 request의 mode가 "
cors" 또는 "same-origin"이면, "Allowed"를 반환한다. -
policy를 policyContainer의 integrity policy로 둔다.
-
reportPolicy를 policyContainer의 report only integrity policy로 둔다.
-
policy와 reportPolicy가 모두 빈 integrity policy이면, "Allowed"를 반환한다.
-
global을 request의 client의 global object로 둔다.
-
global이
Window도 아니고WorkerGlobalScope도 아니면, "Allowed"를 반환한다. -
block을 불리언으로 두고, 초깃값을 false로 한다.
-
reportBlock을 불리언으로 두고, 초깃값을 false로 한다.
-
policy의 sources가 "
inline"을 포함하고 policy의 blocked destinations가 request의 destination을 포함하면, block을 true로 설정한다. -
reportPolicy의 sources가 "
inline"을 포함하고 reportPolicy의 blocked destinations가 request의 destination을 포함하면, reportBlock을 true로 설정한다. -
block이 true이거나 reportBlock이 true이면, request, block, reportBlock, policy 및 reportPolicy로 위반을 보고한다.
-
block이 true이면 "
Blocked"를 반환하고, 그렇지 않으면 "Allowed"를 반환한다.
3.8.3. 위반 보고
dictionary :IntegrityViolationReportBody ReportBody {USVString ;documentURL USVString ;blockedURL USVString ;destination boolean ; };reportOnly
Request request, 불리언 block, 불리언 reportBlock, integrity policy policy, 그리고 integrity policy reportPolicy가 주어졌을 때 위반을 보고하려면 다음을 수행한다:
-
settingsObject를 request의 client로 둔다.
-
global을 settingsObject의 global object로 둔다.
-
Assert: global은
Window또는WorkerGlobalScope이다. -
url을 null로 둔다.
-
global이
Window이면, url을 global의 associated Document의URL로 설정한다. -
global이
WorkerGlobalScope이면, url을 global의 URL로 설정한다. -
documentURL을 url에 strip URL for use in reports를 적용한 결과로 둔다.
-
blockedURL을 request의 URL에 strip URL for use in reports를 적용한 결과로 둔다.
-
block이 true이면, policy의 endpoints에 있는 각 endpoint에 대해 반복한다:
-
body를 다음과 같이 초기화된 새
IntegrityViolationReportBody로 둔다:documentURL-
documentURL
blockedURL-
blockedURL
destination-
request의 destination
reportOnly-
false
-
다음 인수로 보고를 생성하고 큐에 넣는다:
- context
-
settingsObject
- type
-
"
integrity-violation" - destination
-
endpoint
- data
-
body
-
-
reportBlock이 true이면, reportPolicy의 endpoints에 있는 각 endpoint에 대해 반복한다:
-
reportBody를 다음과 같이 초기화된 새
IntegrityViolationReportBody로 둔다:documentURL-
documentURL
blockedURL-
blockedURL
destination-
request의 destination
reportOnly-
true
-
다음 인수로 보고를 생성하고 큐에 넣는다:
- context
-
settingsObject
- type
-
"
integrity-violation" - destination
-
endpoint
- data
-
reportBody
-
4. 프록시
응답을 수정하는 최적화 프록시와 기타 중간 서버는 해당 응답과 연결된 digest가 새 콘텐츠와 동기화된 상태로 유지되도록 보장해야 한다. 한 가지 방법은 리소스와 연결된 무결성 메타데이터가 갱신되도록 보장하는 것이다. 또 다른 방법은 페이지 작성자가 무결성 검증을 요청한 리소스에 대해 정식 버전만 전달하는 것이다.
중간 서버에 정보를 제공하기 위해, 리소스를 제공하는 서버는
그 리소스와 함께 값이 no-transform인
Cache-Control 헤더를
보내는 것이 좋다.
5. 보안 및 개인정보 보호 고려사항
이 절은 규범적이지 않다.
5.1. 비보안 컨텍스트는 비보안인 채로 남는다
HTTP 페이지와 같이 Secure Context가 아닌 컨텍스트에서 전달되는 무결성 메타데이터는 외부 리소스가 호스팅되는 서버의 손상에 대해서만 출처를 보호한다. 네트워크 공격자는 digest가 검증하려는 응답을 변경할 수 있는 것과 마찬가지로, 전송 중에 digest를 변경할 수 있다(또는 완전히 제거하거나, 문서에 대해 그 밖의 절대적으로 어떤 일이든 할 수 있다). 따라서 작성자는 무결성 메타데이터를 Secure Context에만 전달하는 것이 권장된다. 또한 Securing the Web을 참조하라.
5.2. 해시 충돌 공격
Digest는 이를 생성하는 데 사용되는 해시 함수만큼만 강하다. 사용자 에이전트는 알려진 약한 해시 함수의 지원을 거부하고, 충돌 저항성이 있는 것으로 알려진 알고리즘으로 지원 알고리즘을 제한하는 것이 권장된다. 권장되지 않는 해시 함수의 예로는 MD5와 SHA-1이 있다. 작성 시점에는 SHA-384가 좋은 기준선이다.
또한 사용자 에이전트는 지원하는 해시 함수를 정기적으로 재평가하고, 안전하지 않음이 드러난 함수의 지원을 폐기하는 것이 권장된다. 시간이 지남에 따라 해시 함수는 예상보다 훨씬 약하거나, 경우에 따라서는 깨진 것으로 밝혀질 수 있으므로, 사용자 에이전트가 이러한 발전을 계속 인지하는 것이 중요하다.
5.3. 교차 출처 데이터 누출
이 명세는 무결성으로 보호되는 교차 출처 요청이 CORS protocol을 사용하여 리소스의 콘텐츠가 요청자에게 명시적으로 공유되도록 요구한다. 이 요구사항이 생략되면, 공격자는 same-origin policy를 위반하고 교차 출처 리소스가 특정 콘텐츠를 가지고 있는지 확인할 수 있다.
공격자는 알려진 digest로 리소스를 로드하려 시도하고, 로드 실패를 관찰할 수 있다. 로드가 실패하면, 공격자는 응답이 해시와 일치하지 않았다고 추측하여 그 내용에 대한 일부 정보를 얻을 수 있다. 예를 들어, 사용자가 특정 서비스에 로그인했는지 여부를 드러낼 수 있다.
또한 공격자는 그 외에는 정적인 리소스에서 특정 값을 brute-force할 수 있다. 다음과 같은 JSON 응답을 고려하라:
공격자는 다양한 흔한 사용자 이름을 사용한 응답의 해시를 미리 계산하고, 문서를 반복적으로 로드하려 시도하면서 그 해시들을 지정할 수 있다. 로드가 성공하면 공격자가 사용자 이름을 올바르게 추측했음이 확인된다.
6. 감사의 말
여기 있는 콘텐츠의 상당 부분은 Gervase Markham의 Link Fingerprints 개념과 WHATWG의 Link Hashes에서 크게 영감을 받았다.
이 명세의 초기 버전에 귀중한 기여를 해 준 Mike West에게 특별히 감사드린다. Brad Hill, Anne van Kesteren, Jonathan Kingston, Fatih Kilic, Mark Nottingham, Sergey Shekyan, Dan Veditz, Eduardo Vela, Tanvi Vyas, Yoav Weiss, 그리고 Michal Zalewski에게 귀중한 피드백을 제공해 준 데 대해 감사드린다.