Spring Security 에서 Http Response 에 대한 header 값을 설정하는 부분이 .headers 옵션이다.
기본적은 Spring Security headers 설정은 아래와 같다.
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires:0
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
.frameOptions(X-Frame-Options)
Http 헤더에서 X-Frame-Options 속성을 설정하는데 프레임(iframe)에 웹사이트를 제한하거나 접근 허용 범위를 설정할 수 있다. 쉽게 말해 <iframe> 이라는 html 태그가 존재하는데 해당 태그안에 다른 웹페이지를 삽입할 수 있다.
해당 iframe 태그를 사용하게 되면 클릭재킹이라는 해킹공격에 취약하다.
* 클릭재킹
삽입하는 웹페이지 내 악의적인 코드를 집어 넣어 정상적인 동작처럼 보이게 만든 후 사용자의 정보를 갈취하거나
사용자를 속이는 공격이다.
기본적으로 Spring Security 에서는 DENY 설정하여 클릭 재킹 공격을 막는다.
옵션 종류
- DENY : iframe 삽입을 차단
=> X-Frame-Options: DENY
- SAMEORIGIN : 동일 도메인 내에서 iframe 을 허용
=> X-Frame-Options: SAMEORIGIN
=> 예) example.com 의 페이지는 example.com 도메인 내에서만 iframe 삽입 가능
- ALLOW-FROM {도메인} : 특정 도메인 접근 가능
Content Security Policy(CSP)
CSP 란 웹 페이지에 대한 표준으로 , 스크립트, 스타일, 이미지 등의 리소스를 어떤 출처에서 로드할 수 있는지
명시하는 정책을 설정할 수 있다.
컨텐츠 보안 정책은 XSS 와 같은 컨텐츠 내의 인젝션 공격에 대한 취약점을 개선할 수 있는 설정이다.
위 설정을 보면 script-src 가 설정되어 있다.
javascript 에서 스크립트를 실행하게 되면 script-src 에 설정되어 있는 범위의 리소스가 맞는지 확인한 후
실행할지 결정한다.
script-src 'self' 다음 도메인에 대한 설정이 없으면 항상 스크립트를 실행할 수 없고
"script-src 'self' https://www.naver.com" 처럼 도메인이 설정되어 있으면 해당 도메인만 실행할 수 있다.
설정값
- default-src : src 로 끝나는 모든 리소스의 기본 동작을 설정
- script-src : Javascript 태그 관련 권한과 출처 설정
- style-src : 스타일시트 관련 권한과 출처 설정
구성값
- none : 모든 출처를 허용하지 않음
- self : Origin 내에서 로드하는 리소스만 허용
- unsafe-inline : 인라인 코드의 사용을 허용
.headers(headers -> headers
.frameOptions(frameOptions -> frameOptions
.sameOrigin()
.contentSecurityPolicy(contentSecurityPolicy -> contentSecurityPolicy
.policyDirectives("script-src 'self'")
)
)
)
.sameOrigin().contentSecurityPolicy(csp -> csp
.policyDirectives("script-src 'self'")
)
.sameOrigin() 을 통해 같은 도메인상에서만 허용한다고 설정한다.
.contentSecurityPolicy 설정을 통해 CSP 설정을 하며 스크립트, 리소스, 이미지 등 어떤 출처에서 로드할 수 있는지
설정 가능하다.
본인은 인라인 스크립트인 <script></script> 내 스크립트 제한을 위해 "script-src 'self'" 설정을 했다.
***** 여기서 다른 방법이 있는걸 찾았다... *****
.headers(headers -> headers
.frameOptions(options -> options
.sameOrigin()
//.contentSecurityPolicy(csp -> csp.policyDirectives("script-src 'self'"))
)
.contentSecurityPolicy(csp -> csp
.policyDirectives("script-src 'self'")
)
)
.frameOptions 의 .sameOrigin() 하위에 있는 .contentSecurityPolicy 를 설정하지 않고
.headers 하위에도 .contentSecurityPolicy 가 있다.
두개다 동일한 성격을 띄지만 다른점은 앞으로 찾아보겠다...
contentTypeOptions(X-Content-Type-Options)
contentTypeOptions() 설정은 응답 헤더의 X-Content-Type-Options 를 설정하며
Spring Security 의 기본값은 "nosniff" 설정이며 컨텐츠 스니핑을 비활성화 한다.
.xssProtection
브라우저의 내장 XSS 필터를 활성화하거나 비활성화하는 설정이다.
.headers(headers -> headers
.xssProtection(xss -> xss
.block(true) // XSS 탐지 시 페이지 렌더링을 차단
.enabled(true) // 필터 활성화
)
)
HTTP Strict Transport Security(HSTS)
.headers(headers -> headers
.httpStrictTransportSecurity(hsts -> hsts
.includeSubDomains(true)
.preload(true)
.maxAgeInSeconds(31536000)
)
)
특정 웹사이트에 URL 을 적어 접근할때 https:// 처럼 문구를 생략하고 접근할때가 많다.
이러한 URL 접근은 중간자 공격에 취약하다.
이러한 취약점을 예방하기 위해 HSTS 설정이 필요하다.
HSTS 설정은 HTTP 로 액세스 하려는 모든 시도에 대해 HTTPS 요청으로 자동 변환해야 한다고 브라우저에게
알려주는 기능을 한다. 즉, 브라우저가 HTTP 대신 HTTPS 만 사용하도록 강제하는 설정이다.
쉽게 말해 사용자가 http 프로토콜로 접근했을 떄 브라우저에게 해당 웹사이트는 HTTPS 프로토콜로 접근해야
한다라고 미리 알 수 있게 한다.
HTTPS 로 서비스중일 때만 이 설정이 효과가 있다고 한다.
preload=true는 HSTS preload 리스트에 도메인이 등록되어야 실제로 적용된다.
- includeSubDomains(true) : 하위 도메인도 HSTS 도메인으로 취급해야한다 라고 알린다.
- preload(true) : 브라우저에게 이 도메인을 미리 HSTS 도메인으로 로드하도록 알린다.
- maxAgeInSeconds(시간) : 시간 설정
🧠 요약 표
설정 |
헤더 |
기능 |
상태 |
.xssProtection() |
X-XSS-Protection |
브라우저 XSS 필터 설정 |
❌ 오래된 방식, 비추천 |
.httpStrictTransportSecurity() |
Strict-Transport-Security |
HTTPS 강제, MITM 방지 |
✅ 적극 권장 |
* 참고 내용
https://docs.spring.io/spring-security/site/docs/5.2.0.RELEASE/reference/html/default-security-headers-2.html