Foundry
보안
중급
핵심

CSRF와 SameSite 쿠키

로그인만 되어 있으면 남의 페이지가 내 요청을 보낸다

CSRF와 토큰, SameSite 쿠키

공격이 성립하는 조건

1. 피해자가 대상 사이트에 로그인 (쿠키 보유)
2. 공격자 페이지가 대상 사이트로 요청 발생
3. 브라우저가 쿠키를 자동 첨부 -> 서버는 정상 요청으로 처리

원인은 쿠키가 자동으로 붙는다는 점이다. 인증값을 코드가 직접 넣는 방식(Authorization 헤더)은 기본적으로 이 경로에 노출되지 않는다.

방어 수단

방법원리한계
동기화 토큰서버 발급값을 폼과 헤더로 검증서버 상태 필요
Double Submit Cookie쿠키값과 헤더값 일치 검증서브도메인 탈취에 약함
SameSite=Lax/Strict크로스 사이트 요청에 쿠키 미첨부예외 케이스 존재
Origin, Referer 검증요청 출처 확인헤더 부재 처리 필요

실무 포인트

  • 쿠키 세션이면 SameSite만 믿지 않고 토큰 검증을 함께 둔다(방어 계층 중첩)
  • SameSite=None은 반드시 Secure와 함께. 결제, SSO처럼 크로스 사이트가 필요할 때만
  • 상태를 바꾸는 요청을 GET으로 만들지 않는다. GET은 링크와 프리페치로도 트리거된다
  • XSS가 있으면 CSRF 방어는 무너진다. 토큰을 스크립트가 읽어 갈 수 있기 때문
면접에서 이렇게 나옵니다

Q.쿠키 세션 기반 서비스에 CSRF 방어를 넣는다면 어떤 조합을 택하겠습니까?

한 겹으로 끝내지 않고 세 가지를 겹칩니다.

장치역할
SameSite=Lax 쿠키다른 사이트에서 온 POST 와 fetch 를 막는다. 기본 방어
CSRF 토큰상태를 바꾸는 요청에 예측 불가한 값을 요구한다
Origin 또는 Referer 확인요청 출처를 서버에서 검증한다

SameSite 만으로 부족한 이유는 최상위 GET 이동에는 쿠키가 실린다는 점입니다. 링크를 눌러 이동하는 경로로 상태가 바뀌면 그대로 실행됩니다. 그래서 상태를 바꾸는 동작을 GET 에 두지 않는 것이 함께 가는 규칙입니다.

토큰은 세션에 묶어 두고 폼이나 헤더로 받습니다. 쿠키에만 담으면 같은 사이트 스크립트가 읽어 쓸 수 있어야 하므로 이중 제출 방식의 한계를 이해하고 씁니다.

흔한 실수: 토큰만 넣고 SameSite 를 두지 않는 것. 반대도 마찬가지입니다. 겹쳐야 하나가 실패해도 남습니다.

Q.SameSite=Lax만으로 충분하지 않은 경우는 언제인가요?

Lax 는 최상위 GET 이동에 쿠키를 함께 보냅니다. 그 경로가 열려 있으면 통합니다.

요청Lax 에서 쿠키
다른 사이트의 POST 폼 전송실리지 않는다
이미지 태그, iframe, fetch실리지 않는다
링크를 눌러 이동하는 GET실린다

그래서 이런 경우가 남습니다.

상태를 바꾸는 GET 엔드포인트가 있다
  /logout, /subscribe?on=1, /admin/delete?id=3
공격자가 링크만 보내면 실행된다

브라우저에 따라 최근 2분 안에 설정된 쿠키는 최상위 POST 에도 실리는 완화 규칙이 있어 로그인 직후 창도 생깁니다.

흔한 실수: Strict 로 바꾸면 해결된다고 답하는 것. 다른 사이트에서 우리 링크로 들어올 때 로그인이 풀려 보여 사용성이 크게 나빠집니다. 상태 변경을 GET 에서 빼고 토큰을 함께 쓰는 것이 실용적인 답입니다.

Q.Authorization 헤더로 토큰을 보내는 API도 CSRF 방어가 필요한가요?

대부분 필요하지 않습니다. CSRF 는 브라우저가 자동으로 인증 정보를 붙여 주는 상황에서 성립하는 공격입니다.

인증 방식자동 전송CSRF 위험
쿠키 세션브라우저가 자동으로 붙인다있다
Authorization 헤더스크립트가 직접 넣어야 한다낮다

다른 사이트의 스크립트는 우리 토큰을 읽을 수 없고(같은 출처 정책), 헤더를 임의로 붙인 요청은 사전 확인 요청을 거쳐 CORS 에서 막힙니다.

다만 조건이 붙습니다.

조건결과
토큰을 쿠키에도 저장해 서버가 쿠키에서 읽는다CSRF 위험이 돌아온다
CORS 설정이 모든 출처를 허용한다방어가 무력화된다

흔한 실수: "토큰 인증이면 CSRF 는 신경 안 써도 된다"고 단정하는 것. 실제 구현이 쿠키를 병행하는 경우가 많고, 그때는 쿠키 경로가 공격 표면입니다.

Q.CSRF와 XSS가 함께 존재할 때 어느 쪽을 먼저 막아야 하나요?

XSS 를 먼저 막습니다. XSS 가 있으면 CSRF 방어가 무력화되기 때문입니다.

XSS 로 스크립트를 실행할 수 있으면
  CSRF 토큰을 DOM 이나 응답에서 읽는다
  같은 출처에서 정상 요청을 만든다
  SameSite 쿠키도 같은 사이트이므로 실린다

즉 CSRF 방어 장치 전부가 같은 출처 안에서는 통과됩니다. 반대 방향은 성립하지 않습니다. CSRF 가 있어도 XSS 방어가 약해지지는 않습니다.

순서이유
1. XSS상위 취약점. 다른 방어를 무력화한다
2. CSRFXSS 가 없어도 남는 별개 위험

흔한 실수: 둘을 같은 무게로 두고 동시에 처리한다고 답하는 것. 급한 상황에서 순서를 정해야 하고, 그 근거를 대는 것이 이 질문의 요지입니다.

먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.

읽었으면 문제로 확인해보세요

보안 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.