csrf 맘대로 꺼도될까

HiroPark·2022년 9월 13일
1

문제해결

목록 보기
1/7
post-custom-banner

스프링 부트와 aws로 구현하는 웹서비스 책을 따라하다 보니, 시큐리티 부분에 대해 잘 모른채 책에서 시키는 대로 구현하는데 집중하였다.
문제는 내가 책과 달리 데이터베이스를 h2가 아닌 MySQL로 설정하였다는 것에서 시작하는데...

.csrf().disable().headers().frameOptions().disable()

SecurityConfig의 이 설정!

@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private final CustomOAuth2UserService customOAuth2UserService;

    @Override
    protected void configure(HttpSecurity http) throws Exception{
        http
                .csrf().disable().headers().frameOptions().disable().and()

책에 써있기로는 "h2-console 화면을 사용하기 위해 해당 옵션들을 disable한다" 라고만 간단하게 쓰여있었기에.. 나는 h2안쓰니까~ 하면서 쿨하게 주석처리 해주었습니다.

그런데, 댓글 기능을 추가하기 위해서 전체적인 기능을 확인하려는데 글 등록시 계속 403 에러가 발생하였습니다.

뭐가 문젠지 한참 헤매다가 해당 설정의 주석을 해제해 주었는데 더이상 403에러가 발생하지 않습니다.

이것들이 무엇인지 알아보도록 하겠습니다.

CSRF(Cross-site request forgery)

  • 사이트 간 요청 위조 라는 뜻으로, 사용자가 자신이 의도치 않은(=공격자가 의도한 행위)를 특정 웹사이트에 요청하게 하는 공격입니다.
  1. 공격자는 악용 URL을 만듭니다
  2. 공격자는 이메일이나 게시판 등을 이용하여 이 링크를 사용자에게 전달합니다.
  3. 공격용 HTML페이지 안에는 이러한 이미지 태그가 있습니다(이체하기 위해 사용하는 링크이지만, 이체 대상을 도둑으로 변조하였습니다)
<img src= "https://bank.service.com/transfer?.amount=10000&.dst=도둑">
  1. 사용자가 공격용 페이지를 열고, 이미지 파일을 받아오기 위해 해당 url을 엽니다.
  2. 사용자의 클릭 여부와 상관없이 공격자가 원하는 요청이 자동으로 trigger 됩니다.

이러한 csrf공격을 막기 위하여 스프링은

  • 동기화 토큰 패턴
  • 세션 쿠키에 SameSite 속성 지정
    을 사용합니다.

다만, 스프링 시큐리티는 세션 쿠키를 직접적으로 제어하지 않으므로, SameSite속성에 대해 지원하지 않습니다.

동기화 토큰 패턴 은 세션 쿠키 외에 각 HTTP요청에 CSRF토큰이라는 보안 무작위 생성 값이 있어야 함을 요구하는 것입니다.
CSRF토큰이 없거나, 실제 CSRF토큰과 일치하지 않는다면 요청을 거부합니다.
HTTP 매개변수, 또는 HTTP 헤더 CSRF토큰을 포함할 것이 요구됩니다.

제가 해왔던 요청에는 CSRF토큰이 없습니다. 그래서 계속 문제가 발생했던 것입니다.

꺼도 되는가

이 csrf속성을 꺼주지 않아서 문제가 발생한 듯 보입니다. 그런데 csrf속성을 꺼주지 않으면 문제가 발생하지 않을까요??

When should you use CSRF protection? Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection.

스프링 공식 문서에 따르면 논-브라우저 클라이언트(wget,curl같은 것)들만이 사용하는 서비스라면 CSRF 속성을 꺼도 좋다고 합니다.

근데 제가 생각하기엔, 이 게시판은 언젠가 브라우저 클라이언트가 사용하게 될 것이고, 그러면 CSRF가 필요한 것 아닌가? 하는 의문이 생겼습니다.

저와 같은 의문을 가진 사람이 있군요
https://stackoverflow.com/questions/52363487/what-is-the-reason-to-disable-csrf-in-spring-boot-web-application


이분 말에 따르면 현재는 jwt등의 토큰 메커니즘을 사용하고 있지 않은 저의 서비스는 csrf가 필요한듯합니다.


튜토리얼을 쉽게 만드려고 그렇다는 의견도 있군요

이 링크의 첫번째 답변이 큰 도움이 됐습니다

결론부터 말하면 현재로서는 CSRF 끄면 안됩니다.

답변에 따르면

  • NO Cookies = No CSRF
  • 세션 사용 = Client Side를 추적 중 = STATELESS하지 않음 = RESTful하지 않음 => CSRF에 취약
  • 추가적으로 쿠키에 "로그인 토큰"을 담아서 사용하길 권합니다

현재의 세션 기반 인증은 쿠키를 사용합니다.

No Cookies도 아니고, stateless 하지 않기에 csrf에 취약합니다.

왜 저자분께서 CSRF를 disable하셨는지는...잘 모르겠습니다. 컴팩트한 책이다보니 진행의 용이함을 위해 빼셨을 수도 있고, 제가 모르는 무언가가 있을 수도 있습니다.

아무튼! 제가 이해한 바로는 현재의 세션 인증 방식으로는 CSRF 방어가 필요합니다.
다만,
1. 아직 로컬에서만 개발중인 단계이고
2. 시큐리티에 대한 이해가 충분하지 않은 상태이니
이대로 두겠습니다.

추후에 JWT기반 인증으로 바꾸는 과정을 거칠것입니다.

마지막으로, disable() 뒤의 headers().frameOptions().disable()는 무엇일까요?

해당 스택오버플로 를 참고했습니다

  • X-frame-Option
    이 헤더는 기본적으로 브라우저가 페이지를 frame 혹은 iframe을 render하지 못하게 합니다.
    - frame : 하나의 화면에서 여러개의 페이지를 분할 하여 보여줌
    - iframe : 페이지 안에 페이지를 삽입
    위에서 페이지 안에 삽입된 이미지로 인해 CSRF공격이 trigger 된 것을 생각하면 프레임과 아이프레임을 금지하는 것이 이해가 갑니다.

그러나, h2 콘솔의 ui는 (책에서는 h2콘솔을 사용) frame 을 사용하고 있기에, X프레임 옵션을 끄지 않는다면 에러가 날 것입니다.
h2콘솔을 사용하기 위해 해당 설정을 꺼준듯 보입니다. 당연히 공격에는 취약할 것입니다.

참고 https://ko.wikipedia.org/wiki/%EC%82%AC%EC%9D%B4%ED%8A%B8_%EA%B0%84_%EC%9A%94%EC%B2%AD_%EC%9C%84%EC%A1%B0
https://www.synopsys.com/glossary/what-is-csrf.html
https://rusyasoft.github.io/java/2019/02/15/spring-security-csrf-from-context/
https://zzang9ha.tistory.com/341
https://docs.spring.io/spring-security/site/docs/5.3.x/reference/html5/#csrf
https://www.quora.com/What-are-non-browser-clients

profile
https://de-vlog.tistory.com/ 이사중입니다
post-custom-banner

0개의 댓글