본문 바로가기
개발

HTTP 쿠키와 보안 그리고 CSRF

by 상5c 2024. 2. 18.

이 글에서는 백엔드 개발자 입장에서 쿠키를 사용하기 위해 알아야 하는 기초적인 지식을 다뤘습니다.

 

쿠키란 무엇인가

쿠키란 웹 사이트가 사용자의 웹 브라우저에 저장하는 작은 데이터 조각이다. 사용자가 사이트를 방문할 때마다 웹 서버로 전송되어 사용자의 이전 활동, 로그인 상태 등을 기억하게 해준다. 쿠키의 주요 목적은 웹 상에서 사용자의 상태를 유지하는 것이다.

 

왜 상태를 유지해야 할까?

웹 사이트가 데이터를 주고받는 HTTP 통신은 Stateless 프로토콜이다. 각 요청은 독립적이고 서로 상태를 공유하지 않는다. 이러한 특성은 설계를 단순화 시키지만 클라이언트의 이전 요청을 기억하지 않기에, 사용자의 상태를 유지하기 위한 추가적인 메커니즘이 필요하게 된다. 이 상태 유지를 돕는게 쿠키이다.

 

쿠키는 stateless 프로토콜의 한계를 극복하기 위해 사용된다.

사용자의 브라우저에 정보를 저장함으로써 서버가 사용자의 상태 정보를 유지할 수 있게 된다. 만약 인증 여부를 어딘가에 저장하지 않는다면 매 요청마다 인증 정보(아이디와 비밀번호)를 전송해야 서비스 이용이 가능할 것이다.

이외에도 쿠키는 client-side에 데이터를 저장, 활용하는 용도로 쓰인다(구현하기에 따라 개인화 설정, 장바구니, 방문한 페이지 등이 쿠키에 기록될 수 있다)

쿠키를 활용하는 다양한 방법이 있지만 여기서는 인증 목적의 쿠키에 대해 살펴보려 한다.

 

인증 목적의 쿠키 사용

서버가 사용자 로그인 상태를 유지하기 위한 방법으로 세션 기반 인증(session based authentication)과 토큰 기반 인증(token based authentication) 방식이 있다.

여기서 주목해야 하는 것은 인증 메커니즘이 아니다. 결국 두 방법 모두 클라이언트 사이드에 사용자 식별을 위한 값을 저장해야 하고, 저장 위치가 쿠키라면, 쿠키를 통해 인증 로직을 수행한다면 쿠키 보안을 신경써야 한다.

쿠키에 값을 저장해두면 브라우저가 HTTP Request 전송시 자동으로 값을 보내준다. 편리하기에 많이 사용되는 방법이다. 하지만 역시 공짜는 없다. 개발자가 편하면 해커도 편하다. 브라우저가 쿠키를 같이 전송한다는 특징을 이용하여 쿠키를 탈취하는 공격하는 기법이 많이 있다.

공격자는 여러가지 방법으로 쿠키를 탈취할 수 있다. 그 중 대표적인 방법으로 XSS(크로스 사이트 스크립팅), CSRF(크로스 사이트 요청 위조), MITM(중간자 공격), Session Fixation(세션 고정), Sniffing(스니핑) 등이 있다.

REST API라서, 토큰 기반 인증이라서 CSRF에 대해 안전하다는 글을 봤는데 이는 잘못된 이야기다. 토큰 기반 인증이냐 세션 기반 인증이냐는 CSRF와 관련이 없다. 쿠키를 사용하여 인증정보를 전달하느냐가 CSRF 공격 대상이 되냐 아니냐를 결정한다. JWT도 쿠키에 담아 인증을 수행하면 공격 대상이 된다.

대표적인 공격과 방어

가장 우선 적용해야 하는 것은 HTTPS 통신을 사용하는 것이다. HTTPS 통신은 데이터를 암호화하여 전송하기에 공격자가 중간에 가로채더라도 복호화된 원본 데이터를 알아내기 어렵다. 그렇다면 HTTPS는 위의 모든 공격을 막을 수 있을까?

HTTPS 사용만으로 MITM, 스니핑 등을 방지할 수 있으나, XSS, CSRF, Session Fixation 공격을 막기에 충분하지 않다. 그럼 어떤 작업들을 같이 해줘야 할까?

공격이 어떻게 이루어지는지 알아보자.

 

XSS(크로스 사이트 스크립팅, Cross-Site Scripting)

  • 내가 이용하는 서비스에 공격자가 스크립트를 심는 공격이다. 게시글에 <script> 태그를 포함시키는 것을 생각하면 된다.
<script> 
// 1. 쿠키를 읽는다
// 2. 공격자 서비스인 attack.com으로 값을 전송한다 
</script>
  • 공격 과정
    1. 공격자가 스크립트를 담은 게시물을 게시
    2. 사용자가 서비스 로그인 후 해당 게시물 접근
    3. 스크립트 실행되어 쿠키 탈취
  • 사용자의 인증 쿠키를 얻었기에 사용자를 흉내낼 수 있게 된다.

 

CSRF (크로스 사이트 요청 위조, Cross-Site Request Forgery)

  • 공격자가 다른 사이트에서 사용자가 의도하지 않은 요청을 보낸다
    • 쿠키 자동 전송 특성을 이용한 공격 방식이다
  • 공격 과정
    1. 사용자가 A 사이트 로그인
    2. 사용자가 공격자가 만든 B 사이트 접근
    3. B 사이트에서 A 사이트로 정보 변경 요청 전송 (사용자의 A 사이트 쿠키가 포함되어 전송됨)
    4. 사용자 정보가 공격자가 원하는대로 변경됨

 

Session Fixation (세션 고정)

  • 세션 고정 공격은 공격자가 특정 세션 ID를 미리 설정하고, 사용자가 그 세션 ID를 사용하도록 유도하여, 로그인 처리된 세션 ID를 공격자가 이용하는 것을 말한다.
    • 최초 접근시 생성된 세션을 사용하여 사용자가 대신 로그인해주는 방식이다.
  • 공격 과정
    1. 공격자가 세션 ID 획득
    2. 공격자는 사용자가 이 세션 ID를 사용하여 로그인 하도록 유도 (피싱 메일, 링크 조작 등)
    3. 피해자가 공격자가 고정한 세션 ID를 사용하여 시스템에 로그인
    4. 공격자는 미리 고정해둔 세션 ID로 시스템에 접근하여 피해자의 계정을 제어

공격이 어떻게 이루어지는지 알았으니 방어를 시작해보자.

 

SessionFixation 방어

Session Fixation의 원인은 로그인 전후 세션ID가 변경되지 않아서이다. 로그인 시점에 세션을 새로 만들어주면 해결되는 문제이니 간단히 해결할 수 있다.

XSS와 CSRF는 어떻게 막아야 할까?

 

XSS를 통한 쿠키 탈취 방어

XSS를 통한 쿠키 탈취는 A 서비스를 통해 발급받은 쿠키를 공격자가 JavaScript로 읽어서 B 서비스로 보내는 공격 방식이다. 이를 막으려면 클라이언트에 저장된 쿠키를 공격자가 JavaScript 등 스크립트를 통해 쿠키를 훔쳐갈 수 없도록 만들어야 한다.

방어는 쿠키의 HttpOnly 옵션을 활성화 하는 것만으로 간단히 적용할 수 있다. 추가로 고려해야하는 Secure 옵션도 있다. 이는 HTTPS 통신인 경우에만 쿠키를 서버로 전송하도록 하는 옵션이다.

두 옵션을 활성화 하면 A 서비스에서 발급받은 쿠키는 HTTPS 통신으로 A 서비스를 이용할때만 읽을 수 있다.

 

CSRF를 통한 쿠키 탈취 방어

HttpOnly와 Secure두 옵션으로 CSRF도 막을 수 있을까? 아쉽게도 아니다.

CSRF는 기본적으로 사용자의 브라우저를 통해 일어나는 일이기에 HttpOnly와 Secure로 막을 수 없다. 공격자 서비스를 통한 CSRF는 SameSite 옵션으로 막을 수 있다.

SameSite는 “출발지”를 검사하는 옵션이다. a.com에서 발급받은 쿠키는 b.com에서 전송한 request에 담기지 않는다.

그럼 모든 문제가 해결됐을까? 아쉽게도 아니다. XSS와 CSRF를 조합한 공격은 막히지 않았다.

 

XSS를 통한 CSRF 방어

XSS를 통해 쿠키를 탈취하지 않고, 직접 원하는 API를 호출했다고 가정해보자.

<script>
  // 비밀번호 변경 API를 호출하여 사용자 비밀번호를 1234로 변경
</script>

이는 사용자의 브라우저에서 전송하는 Request이고, 사용자가 접근중인 사이트 내에서 요청이 실행되기에 쿠키 옵션으로 막을 수 없다.

CSRF를 막는 방법으로 CSRF 토큰을 발급하는 방법도 있는데, 이 또한 XSS를 통한 CSRF 공격에 무력화된다. 결국 XSS 자체를 막는 방법밖에 없다.

만약 부득이하게 태그를 사용하도록 허용해야 하는 상황이 있다면 XSS 공격을 할 수 없도록 서버는 사용자의 입력에 대해 클렌징(escape) 작업을 수행해야 한다. 그리고 제한된(등록된) 태그만 사용할 수 있도록 작업이 필요하다.

 

마무리

개발자를 힘들게하는 쿠키 보안에 대해 간단히 알아봤다. 쿠키 기반으로 인증을 수행하면 편리하지만 약점도 존재한다. 

결국 보안은 사슬이다. CSRF 토큰을 적용하고, 쿠키 보안을 강화해도 XSS를 막지 않으면 보안에 구멍이 난다. 알려진 공격들에 대해서는 쉽게 방어할 수 있는 방법들이 많이 있으니 용어에 당황하지 말고 보안에 익숙해져보자.

 

참고