본문 바로가기
Web Security

Spring Security와 h2를 사용 시 왜 X-Frame-Options헤더를 지정해야 하는가

by blackjack_96 2024. 7. 30.

스프링부트 프로젝트 개발을 하며

Spring Security와 더불어, 개발과정에서 h2 데이터베이스에서 제공하는 In-Memory 기능을 이용하기로 하였다.

 

h2 데이터베이스와 스프링 시큐리티를 같이 이용하려면

특별히 몇 개의 설정을 더 해주어야 한다.

 

바로 다음과 Security Filter Chain을 등록해서

CSRF 보호 비활성화, X-Frame-Options 헤더를 SAMEORIGIN으로 설정하는 것이다.

 

 

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
        		...
                
                .csrf(AbstractHttpConfigurer::disable)
                .headers(headers -> headers
                        .frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin))
				
                ...

        return http.build();
    }

 

원래는 위와 같이 설정을 해 주어야 동작을 하지만,

나는 csrf 보호 비활성화만 지정을 해놓고,

X-Frame-Options와 관련된 헤더 설정을 하지 않은 채 

h2콘솔에 접속하니 다음 화면이 나왔다.

 

# localhost:8080/h2-console 접속 후 로그인

 

X-Frame-Options헤더 설정을 하지 않은 채로 h2 console에 접속한 화면

 

단 하나의 설정을 빠트린 대가가 이렇게나 크단 말인가.

대체 왜 이런 오류가 나왔는 지 알기 위해서

여러 자료를 찾아가며 공부를 하였다.

 

iframe 태그

 

 먼저 X-Frame-Options 헤더가 무엇인가를 공부하기 전에,

 <iframe>이라는 태그를 통해 다른 웹 페이지를 컨텐츠로 표시할 수 있는 기능에 대하여 공부를 하여야 효과적이다.

 

 다음과 같이, 현재의 웹 페이지 내에 다른 페이지의 컨텐츠를 표시할 수 있는 기능이 있다.

 

<iframe src="https://example.com" width="600" height="400"></iframe>

 

그러니까, 이 iframe 헤더를 이용하면 가로 600픽셀 세로 400픽셀의 크기로 

 "https://example.com"으로 접속했을 때 나오는 컨텐츠를 

 현재 웹 페이지상에 표시를 할 수가 있다.

 

흔히들 맛집 찾으러 다닐 때 맛집 정보가 나오고

그 다음에 구글맵같은걸 이용해서 화면에 지도가 표시될 때

이런 기능이 이용된다고 한다.

아마도 다음과 같이 구현되어 있을 것이다.

 

<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3151.835434509805!2d144.95373531531915!3d-37.81627997975184!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x6ad642af0f11c5e3%3A0x5045675218cee20!2sMelbourne%20CBD!5e0!3m2!1sen!2sau!4v1615960720531!5m2!1sen!2sau" width="600" height="450"></iframe>

 

ClickJacking 공격

 우리는 iframe헤더를 이용해서,

 내 웹 페이지 내에 다른 웹 페이지를 얼마든지 로드해서 사용할 수 있다는 것을 알게 되었다.

 하지만 이게 꼭 좋은 것인지는 생각을 해 봐야 한다.

 

 

 누군가는 다음과 같은 걱정을 할 수도 있다.

 "누군가가 내 웹 컨텐츠를 함부로 가져다가 자신의 웹 페이지에 표시되도록 하면 어떡하지?

 

실제로 해커가 만든 웹 페이지에서,

iframe을 통해 금융 거래 웹 사이트의 페이지를 불러와서 보이지 않게 숨기고,

버튼을 클릭하면, 금융거래 웹 사이트의 특정 버튼이 눌려져서 돈을 이체하도록 하는 공격을 할 수도 있다.

이런 공격을 클릭재킹 공격(ClickJacking)이라고 한다.

 

X-Frame-Options헤더

이러한 클릭재킹 공격이 일어나지 않도록 하기 위해서 어떻게 해야 할까?

답은 간단하다.

 

"나를 다른 곳에서 함부로 사용하지 못하도록"하면 된다.

 

위 은행 사이트 예시의 경우에는, "내 웹 사이트를 함부로 다른 도메인에서 iframe으로 불러오지 못하도록"하면 되는 것이다.

이 때 사용하는 것이 바로 X-Frame-Options헤더이다.

 

X-Frame-Options를 SAMEORIGIN으로 설정한다면,

오로지 동일한 도메인 내에서만 해당 페이지를 iframe으로 불러올 수가 있다.

 

스프링 시큐리티에서는 이 X-Frame-Options를 지정하지 않으면 디폴트로 Deny가 설정되어,

그 어떠한 경우에도, 어디서도 해당 페이지를 iframe으로 불러올 수 없게 된다.

 

H2-console에서 문제의 화면

X-Frame-Options헤더 설정을 하지 않은 채로 h2 console에 접속한 화면

 

문제의 화면을 다시 자세히 살펴보자.

 

 

개발자 도구를 이용해 살펴보면, h2-console화면은

frame이라는 태그를 통해 다른 자원을 표시하도록 구현이 되어 있다.

 

<frame noresize="noresize" frameborder="0" marginheight="0" marginwidth="0" src="header.jsp?jsessionid=0340fe8bf5d09068c343660456ea676e" name="header" scrolling="no">

 

그리고 맨 밑에를 보면, X-Frame-Options가 DENY로 설정이 되어 있어서 diaplay하지 못했다는 오류가 있다.

 

그렇다.

스프링 시큐리티에서 별도의 설정이 없을 경우에는 X-Frame-Options를 설정하지 않았으니

이 헤더의 값은 DENY로 자동설정이 되며,

이렇게 되면 해당 모든 도메인 내의 웹 페이지는 그 어디서도 <frame> 혹은 <iframe>태그로 로드될 수가 없게 되는 것이다.

 

그런데 위 frame에서는 어느 경로를 불러와서 컨텐츠로 표시하려고 하고 있는가?

바로 다음 부분이다.

 

http://localhost:8080/h2-console/header.jsp?jsessionid=0340fe8bf5d09068c343660456ea676e

 

http://localhost:8080이라는 도메인의 위 페이지를 로드하려는 순간 다음과 같은 순서로 전개된다.

 

1. HTTP 요청을 보냄

2. HTTP 응답을 받는다. 그리고 그 헤더를 확인해 보니, X-Frame-Options값이 DENY이다.

3. 브라우저가 이를 표시하기를 거부한다.

 

그래서 위와 같이 웹 페이지를 표시할 수 없다는 아이콘이 나왔던 것이다.

이처럼 브라우저 단에서도 각종 보안과 사용자의 안전을 위해 여러 안전 장치가 마련이 되어 있다.

 

끝을 맺으며

 Spring security가 6 이상 버전으로 올라가며

 코딩스타일이 Lambda DSL로 바뀌고,

 이 최신 스타일의 코드를 얻는 것이 쉽지 않다.. 그래서 아주 사소해 보이는 설정 하나를 생략했던 것인데

 이 설정 하나를 생략해서 결과적으로는 큰 오류를 범하게 되었던 것이다.

 덕분에 많은 공부를 하게 되었으니. 후회는 없다