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. CSRF | XSS 가 없어도 남는 별개 위험 |
흔한 실수: 둘을 같은 무게로 두고 동시에 처리한다고 답하는 것. 급한 상황에서 순서를 정해야 하고, 그 근거를 대는 것이 이 질문의 요지입니다.
먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.
읽었으면 문제로 확인해보세요
보안 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.