로그인 csrf 공격은 왜 막아야 하고, 어떻게 막을 수 있는가?

eora21·2024년 6월 27일
0

로그인 csrf 공격에 대해 고민하며 정리한 내용입니다.

로그인 csrf 공격

spring security 공식 문서를 보면, 악의적인 로그인 공격 방식에 대해 설명이 되어있습니다. 해당 논문에서도 csrf 토큰 검증 방식에 대해

There are a number of variations onthis approach, each fraught with pitfalls, and even sites that implement the technique correctly often overlook their login requests because login request lack a session to which to bind the token.
이 접근 방식에는 여러 가지 변형이 있으며, 각 방식에는 함정이 있으며, 이 기술을 올바르게 구현한 사이트에서도 로그인 요청에 토큰을 바인딩할 세션이 없기 때문에 로그인 요청을 간과하는 경우가 많습니다.

라고 적혀있습니다.
세션 기반 인증 방식에서는, 사용자가 웹사이트를 접속한 순간 특정 세션과 csrf 토큰을 만들어 로그인 csrf 공격을 어느 정도 막을 수 있을 것입니다.
그러나 jwt를 사용할 경우에는 보통 세션 생성을 STATELESS로 설정하고, csrf 토큰 검증을 disable합니다. 해당 상황에서 어떻게 하면 공격을 막을 수 있을지, 그 전에 왜 막아야 하는지 확인해 보겠습니다.

로그인 csrf 공격을 막아야 하는 이유

로그인 시 csrf 토큰을 검증하지 않는다면, 피해자의 브라우저에서 공격자의 계정으로 로그인되는 것을 막을 수 없습니다.
검색 엔진의 경우, 검색 기록 및 방문 기록을 남기고 확인하는 인터페이스가 존재합니다. 공격자의 계정으로 로그인된 사실을 알아차리지 못 한 피해자는 사이트를 사용하며 각종의 기록을 남기게 되고, 추후 공격자는 공격 계정으로 로그인해 피해자의 관심사나 활동에 대해 알아낼 수 있게 됩니다.

금융 쪽에서는 더욱 더 큰 피해를 입을 수 있습니다. 피해자가 신용카드를 등록하려고 할 때, 피해자가 알아차리지 못 한 사이에 공격자의 계정으로 변경(로그아웃, 공격자 계정으로 로그인)된다면 공격자의 계정에 피해자의 신용카드가 등록될 수 있습니다.

방어 방법

preSession(Session-Dependent Nonce)

사용자가 로그인 요청을 하기 전, 미리 임의의 세션과 csrf 토큰을 만들고 사용자에게 전달합니다.
사용자는 기존 csrf 토큰 검증 방법과 동일하게 요청을 확인받으면 됩니다.
토큰은 사용자 정의 헤더 등의 방법으로 제출할 수 있습니다.

가장 간단한 방법이지만, 세션 자체를 쓰지 않는 방식으로 구성해보고 싶었기 때문에 다른 방법을 찾아 보았습니다.

HTTPS + Referer

Referer를 통해 실제 요청 주소를 확실히 검증하고, 그 이후는 기존 인증 방식에 맡기면 됩니다.

We recommend strict Referer validation to protect against login CSRF because login forms typically submit over HTTPS, where the Referer header is reliably present for legitimate requests. If a login request lacks a Referer header, the site should reject the request to defend against malicious suppression.
로그인 양식은 일반적으로 합법적인 요청에 대해 리퍼러 헤더가 안정적으로 존재하는 HTTPS를 통해 제출되므로 로그인 CSRF로부터 보호하기 위해 엄격한 리퍼러 유효성 검사를 권장합니다. 로그인 요청에 리퍼러 헤더가 없는 경우 사이트는 악의적인 억제를 방어하기 위해 요청을 거부해야 합니다.

csrf 공격이 시도되는 경우 Referer 헤더가 아예 사라지기 때문에, 로그인 페이지의 uri와 다르거나 헤더가 없는 경우 요청을 거부하여 막을 수 있습니다.

반면 특정 브라우저나 HTTP, 일반적이지 않은 상황에서 Referer 헤더가 억제(클라이언트에서는 보냈으나 모종의 이유로 서버에는 도달하지 않음)될 수 있으므로 이러한 사실을 알고 있어야 할 것 같습니다.

또한 Referer 헤더를 통해 사용자의 검색 쿼리 내용 등을 확인할 수 있으며, 해당 정보가 유출될 수 있기 때문에 개인정보 침해 관련 이슈가 생길 수 있으므로 주의해야 합니다.
그러나 로그인 요청 페이지에 대해서만 검증한다면 문제가 없을 듯 합니다.

HTTPS + Origin

Referer 헤더와 비교하여 사용자의 쿼리가 포함되지 않고, POST 요청에 대해서만 전송되기 때문에 개인정보 보호 측면에서 더 좋은 방향이라고 하며, 덕분에 Referer와 비교해서 억제될 가능성이 더 적습니다.

단, 해당 방법은 몇가지 단점이 존재합니다.

  • Origin을 방어 수단으로 쓰려면 모든 상태 수정 요청은 POST를 사용해야 합니다. 모든 요청에 대해 전송되는 Referer와 달리, 기본적으로 Origin은 POST 요청에 대해서만 전송되기 때문입니다.
  • 몇몇 브라우저에서는 Origin도 Referer처럼 억제될 수 있는데, 아예 사라지는 Referer와 달리 Origin은 null 값을 지니게 되기 때문에 브라우저의 문제인지, 실제 공격이 들어온 건지 판단하기 쉽지 않습니다.
  • 동일 사이트 요청이라도 위조될 수 있기 때문에 다른 방어법과 같이 사용하는 걸 추천한다고 합니다.

모든 csrf 방어 기법으로는 해당 방법도 좋아 보이나, 로그인 csrf 공격 하나만 놓고 보자면 Referer를 사용하는 게 더 나아 보입니다.

결론

논문을 통해 HTTPS + Referer 헤더를 이용하여 검증하기로 했습니다.

Spring Security 사용 시 설정

@RequiredArgsConstructor
public class RefererValidFilter extends OncePerRequestFilter {

    private final String allowReferer;
    private final AuthenticationFailureHandler authenticationFailureHandler;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        if ("/login".equals(request.getRequestURI())) {
            String referer = request.getHeader("Referer");
            
            if (Objects.isNull(referer) || !referer.equals(allowReferer)) {
                authenticationFailureHandler.onAuthenticationFailure(request, response, new WrongRefererException());
                return;
            }
        }

        filterChain.doFilter(request, response);
    }
}

/login에 대한 요청인지 확인하고, 허용된 referer 헤더가 아닐 시 authenticationFailureHandler를 통해 문제 발생을 알리도록 했습니다.

allowReferer은 프로필마다 달라질 수 있고, authenticationFailureHandler는 security에서 따로 유지하고 있는 게 있으므로 파라미터를 통해 값을 받을 수 있도록 했습니다.

Reference

https://docs.spring.io/spring-security/reference/features/exploits/csrf.html#csrf-considerations-login
https://adambarth.com/papers/2008/barth-jackson-mitchell-b.pdf

profile
나누며 타오르는 프로그래머, 타프입니다.

0개의 댓글

관련 채용 정보