CSRF (Cross-Site Request Forgery)
핵심 인사이트 (3줄 요약)
- 본질: CSRF(Cross-Site Request Forgery)는 공격자가victim의 브라우저를 利用하여victim이 이미 인증된 웹사이트에 대해 의도하지 않은 요청(게시물 작성, 비밀번호 변경, 송금 등)을 자동 실행시키는 공격이다.
- 가치: 사용자의 유효한 세션/쿠키가 자동으로 요청에 포함되므로, 공격자는victim의 인증 정보를알 필요 없이 상태 변경 요청을発行할 수 있다. 2009년 Netflix, 2010년 YouTube, 2016년 SWIFTbank 등 대규모 금융 사기사고의攻撃 벡터로活用되었다.
- 융합: CSRF는 브라우저의 쿠키 메커니즘, Same-Origin Policy, HTTP 동사 보안, 토큰 기반 방어, 그리고 XSS와 결합하여 방어 없이 서로 다른 웹/App의 要求를混淆하는 복잡한 보안 분야이다.
Ⅰ. 개요 및 필요성 (Context & Necessity)
개념 정의
CSRF는 웹 애플리케이션이 사용자의 인증 상태를 쿠키에만 의존하여 확인하고, 요청 출처(Referer, Origin 헤더)의 검증 없이 요청의 유효성을 판단할 때 발생하는 취약점이다. 공격자는victim의 브라우저에恶意 사이트에서 요청을発行하게 하여,victim의 유효한 세션 쿠키가 자동으로 해당 요청에 포함되도록 만든다. 웹 애플리케이션은 이 요청을victim의 합법적 요청으로 오인하여 처리한다. 예를 들어 은행网站에서victim이 이미 로그인되어 있는 상태에서, 공격자가victim에게恶意 사이트를 방문하게 하면, 해당 사이트의 JavaScript 또는 forms.auto-submit로 은행 계좌이체를 요청할 수 있다.
필요성
CSRF가 가능한根本적 원인은 HTTP가 무상태(Stateless) 프로토콜이지만, 사용자 인증을 위해 상태를 유지하는 쿠키를 사용하기 때문이다. 브라우저는 동일 도메인에 대한 모든 요청에 해당 도메인의 쿠키를 자동으로 포함하므로,攻撃자가victim을 유혹하여恶意 사이트에서 요청을発行하면,victim의 인증 쿠키가 자동으로 포함되어 애플리케이션은 요청의 진정성을判断할 수 없게 된다. 因此서버 사이드에서 요청 출처를 명시적으로 검증하고, 예측 불가능한 토큰(CSRF Token)을要求에 포함시켜야 한다.
💡 비유
CSRF는 전화 거래소에서 고객이 전화를 끊지 않은 채-bank의 상담원을 졸음verkLicence에 두고, 다른 사람이 그 전화로"s Geld naar mijn account(내 계좌로 돈 송금해줘)"라고 요청하는 것과 같다.-bank은 고객의 목소리(세션)가 유효하다고 믿고 거래를 실행한다. 상담원이 상대방의 신원을 추가 확인(CSRF Token)하면, 전화 너머의 다른 사람은 거래를 실행할 수 없을 것이다.
등장 배경 및 발전 과정
CSRF는 2001년 나무security researcher들이"Nested Image Tags in Email"으로Proof of Concept을演示하면서 업계에 널리 알려지기 시작했다. 2007년 OWASP가 CSRF를 OWASP Top 10에 포함시키면서 보안 표준 항목으로 자리잡았다. 2008년 GitHub, 2010년 Twitter, 2019년 Fortnite 게임내 거래 사기 등 다양한 플랫폼에서 CSRF 취약점이 악용되었다. SameSite 쿠키(Lax, Strict)의 도입(2016년 Chrome 51, 이후 Firefox, Safari 적용)으로 브라우저 레벨 방어가 추가되어, 현대 브라우저에서의 CSRF 위험은 크게 감소했다.
Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)
CSRF 공격 흐름
CSRF 공격은victim이 인증된 상태에서恶意 사이트를 방문할 때 자동으로 실행된다. 이 흐름을이해하면 방어 기법의在哪里 적용해야 하는지 명확해진다.
┌─────────────────────────────────────────────────────────────────────┐
│ CSRF 공격 흐름 │
├─────────────────────────────────────────────────────────────────────┤
│
│ ① [victim이 은행 网站에 로그인] │
│ 브라우저 ◀──▶ 은행 서버 (세션 쿠키 설정됨) │
│ │
│ ② [victim이 공격자의恶意 사이트 방문] │
│ 브라우저 ──▶ 공격자 사이트 접속 │
│ │
│ ③ [악의적 HTML/JavaScript 자동 요청 발생] │
│ │
│ [방법 1: auto-submit form] │
│ <form action="https://bank.com/transfer" method="POST"> │
│ <input name="to" value="attacker" /> │
│ <input name="amount" value="10000" /> │
│ </form> │
│ <script>document.forms[0].submit();</script> │
│ │
│ [방법 2: img src 요청] │
│ <img src="https://bank.com/transfer?to=attacker&amount=10000">│
│ │
│ ④ [브라우저가 은행에 요청 자동 전송] │
│ 브라우저 ──▶ 은행 서버 │
│ ◀── 요청에 victim의 쿠키 자동 포함! │
│ │
│ ⑤ [은행 서버가 유효한 요청으로 처리] │
│ 세션 쿠키 유효 → 요청 처리 (송금 실행) │
│ │
└─────────────────────────────────────────────────────────────────────┘
[다이어그램 해설] ①victim이 은행 网站에 로그인하여 세션 쿠키(JSESSIONID 등)를 발급받는다. ②victim이 공격자의恶意 사이트(evil.com)를 방문한다. ③恶意 사이트는 victims의 브라우저에서 은행으로 자동 요청을発行하는 HTML 요소를 삽입한다. img 태그의 src는 GET 요청을発行하고, auto-submit form은 POST 요청을発行한다. ④브라우저는 요청을 은행 서버로 전송할 때 해당 도메인의 쿠키(은행 网站의 세션 쿠키)를 자동으로 포함한다. 공격자의 사이트에서 요청이発行되었지만, 브라우저는 Same-Origin Policy에 따라 쿠키를 SAME-SITE 고려 없이 전송한다. ⑤은행 서버는 유효한 세션 쿠키를 확인하고, 요청 출처(Referer/Origin 헤더) 검증을 수행하지 않으면victim의 의지无关하게 송금 요청을 처리한다.
CSRF 방어 기법
CSRF 방어의 핵심은 "요청이사용자의 의도적인 행동에서 비롯되었는가"를 서버 사이드에서 검증하는 것이다. 이를 위한 대표적인 기법으로 CSRF Token, SameSite 쿠키, Origin/Referer 검증, Double Submit Cookie 등이 있다.
┌─────────────────────────────────────────────────────────────────────┐
│ CSRF 방어 기법 │
├─────────────────────────────────────────────────────────────────────┤
│
│ [1. CSRF Token 방식] │
│
│ 서버 ──▶ (<form>에 숨겨진 토큰) ──▶victim의 브라우저 │
│ 토큰: 랜덤 문자열 (예: A3f9z...8k2) │
│ │
│ victim의 요청 ──▶ 토큰 포함 ──▶ 서버 검증 (토큰 일치?) ──▶ 처리 │
│ │ │
│ └── 없으면/불일치 → 거부 │
│
| [2. SameSite 쿠키] |
│
| Set-Cookie: sessionId=abc123; SameSite=Strict |
| ◀── Strict: 모든 cross-site 요청에서 쿠키 미전송 │
| ◀── Lax: Cross-site POST 요청에서만 미전송 (GET은 전송) |
|
| [3. Origin/Referer 검증] |
|
| 요청 헤더: Origin: https://legitimate.com |
| Referer: https://legitimate.com/page |
| 서버는 Origin/Referer이White-list 허용 도메인과 일치하는지 검증 |
|
| [4. Double Submit Cookie] |
|
| 쿠키: sessionId=abc123 |
| 요청 본문: csrf_token=xyz789 |
| 서버는 csrf_token값과 X-CSRF-Token 헤더값의 일치 여부를 검증 │
| (서버에 세션 스토어가 없는 경우 Stateless 검증 가능) |
|
└─────────────────────────────────────────────────────────────────────┘
[다이어ktur 해설] CSRF Token은 서버가 폼 생성 시predict 불가능한 랜덤 토큰을 생성하여 세션과关联시키고, 해당 토큰이 요청 본문에 포함되어야 처리하도록 하는 방법이다. 공격자가victim의 세션 쿠키를알더라도, 토큰을알지 못하면 요청을構成할 수 없다. SameSite 쿠키는 브라우저 레벨에서跨사이트 요청 시 쿠키 전송을 차단하여,攻撃者の사이트에서発行된 요청에victim의 쿠키가 포함되지 않도록 한다. Strict 모드는 모든跨사이트 요청에서 쿠키를 차단하므로用户体验が低下할 수 있어, POST 요청만 차단하는 Lax 모드가 일반적으로 권장된다. Origin/Referer 검증은 요청 헤더의 출처를 확인하지만, 공격자가 이를조작하거나 브라우저/프록시에서 제거할 수 있으므로 다른 방어와 함께 사용해야 한다.
다중 방어 전략
현대 웹 애플리케이션에서는 여러 CSRF 방어 기법을 함께 사용하여 Defense in Depth를 구현한다. 브라우저의 SameSite 쿠키가 기본 방어선이 되고, 애플리케이션 레벨에서 CSRF Token과 Origin 검증이 추가 방어선으로 기능한다.
┌─────────────────────────────────────────────────────────────────────┐
│ CSRF 다중 방어 아키텍처 │
├─────────────────────────────────────────────────────────────────────┤
│
│ [브라우저 레벨 (기본 방어)] │
│ SameSite=Lax/Strict 쿠키 ──▶ Cross-site 요청 시 쿠키 전송 차단 │
│
│ [애플리케이션 레벨 (추가 방어)] │
│
│ GET 요청: idempotent (상태 변경 없음) ──▶ CSRF 토큰 불필요 │
│ │
│ POST/PUT/DELETE 요청: │
│ ① CSRF Token 검증 (세션 기반) │
│ ② Origin/Referer 헤더 검증 │
│ ③ Custom Header (X-Requested-With: XMLHttpRequest) presence check │
│
│ [AJAX 요청 특화] │
│
│ - AJAX 헤더에 CSRF 토큰 포함 │
│ - fetch()/axios 사용 시 credentials: 'include'로 쿠키 자동 전송 │
│ - CORS preflight를 통해 Cross-Origin 요청 제어 │
│
│ [주의: GET 요청에서 상태 변경 금지] │
│ GET /transfer?to=attacker&amount=10000 은 CSRF 토큰 검증 불가! │
│ ◀── GET 요청은 상태 변경에 사용하지 않아야 함 │
│
└─────────────────────────────────────────────────────────────────────┘
[다이어그램 해설] GET 요청은 브라우저 주소창에 URL이 표시되고, 즐겨찾기, 공유, 웹 크롤러 접근 등 안전한 操作으로 가정되므로, 상태 변경을 위한 GET 요청은 CSRF 위험이 내재되어 있다. 因此모든 상태 변경은 POST, PUT, DELETE 등의 HTTP 동사를 사용해야 하며, GET 요청은 데이터 조회만 하도록 설계해야 한다. CSRF Token은 폼을 렌더링할 때 서버가 세션과关联된 토큰을生成하여 폼 히든 필드로 삽입하고, 요청 수신 시 세션에 저장된 토큰과 비교하여 일치하지 않으면 거부한다. AJAX 요청에서는 X-CSRF-Token 헤더에 토큰을 포함하여 전송하며, fetch()/axios 등의 모던 HTTP 클라이언트는 이 과정을 자동화하는 옵션을 제공한다.
- 📢 섹션 요약 비유: CSRF 방어는 전화를 받을 때 caller ID(Origin/Referer) 확인하고, 추가 비밀번호(CSRF Token)를 묻고, 전화를 건 사람이 정말 본인인지 확인하는 것과 같다. 같은 집안 전화(Same-Site Cookie)에서는追加 확인이 불필요하지만, 외부에서 온 전화(Cross-Site Request)에서는 반드시 신원 확인을 해야 한다.
Ⅲ. 융합 비교 및 다각도 분석
비교 분석: CSRF vs XSS
CSRF와 XSS는 흔히 혼동되지만, 본질적으로 다른 취약점이며 서로 다른 방어가 필요하다. CSRF는victim의 브라우저가 공격자의 요청을 보내도록 하는 것이고, XSS는 공격자의 코드를victim의 브라우저에서 실행시키는 것이다.
| 비교 항목 | CSRF | XSS |
|---|---|---|
| 본질 | victim의 브라우저가 의도된 요청을実行 | 공격자의 코드가victim의 브라우저에서実行 |
| 쿠키 처리 | victim의 쿠키가 요청에 자동 포함 | XSS는 쿠키 값 자체를 탈취하여 사용 |
| 防护対象 | 서버 사이드 요청 유효성 검증 | 클라이언트 사이드 코드 실행 방지 |
| 브라우저 장벽 | Same-Origin Policy가 защит하지 않음 | Same-Origin Policy가同一出처 내에서만 보호 |
| 防御 수단 | CSRF Token, SameSite 쿠키 | 출력 인코딩, CSP |
XSS와 CSRF는 서로 독립적이지만 결합 가능하다. XSS를 利用하면 CSRF Token을 탈취하거나, CSRF Token 검증 없이 XSS로 직접 요청을発行할 수 있다. 因此두 취약점 모두 방어되어야 하며, XSS 방어가CSRF 방어의 전제 조건이 될 수 있다.
과목 융합 관점
- 브라우저 보안 모델: Same-Origin Policy는 CSRF를 직접 방어하지 않으며, 쿠키의 SameSite 속성이 실질적인 브라우저 레벨 CSRF 방어 수단이다.
- 네트워크 보안: CORS(Cross-Origin Resource Sharing)는 Cross-Origin 요청을 통제하므로, CORS 정책을 잘못 설정하면 CSRF 위험이 증가할 수 있다.
- 프론트엔드 개발: React, Angular, Vue 등 프레임워크는 CSRF Token 자동 처리 기능을 提供하므로, 이를活用하면 개발자가 수동으로 검증 로직을 구현할 필요가 없다.
Ⅳ. 실무 적용 및 기술사적 판단
실무 시나리오
-
시나리오 — SNS 플랫폼의 상태 변경 API: 게시물 삭제, 프로필 변경, 비밀번호 변경 등의 상태 변경 API가 CSRF Token 검증 없이 개발되어, 공격자가victim의 브라우저에서 해당 API를 요청하게 만들어 프로필이 변조되거나 계정이 탈퇴되는 상황. 아키텍트는 모든 상태 변경 API에 CSRF Token 검증을 필수로 적용하고, GET 요청은 데이터 조회만 허용하는 RESTful 설계를徹底하여 방어했다.
-
시나리오 — 파일 다운로드 CSRF: CSRF Token이 POST 요청에만 적용되고 GET 요청(파일 다운로드, 데이터 조회)에는 적용되지 않아, 악성 링크 클릭 시victim의 브라우저에서 인증된 사용자로 GET 요청이発行되어 개인정보가 유출되는 상황. 아키텍트는 GET 요청도 상태 변경이 없는 안전한 操作으로 제한하고, 민감한GET 응답에는 Cache-Control: private, no-store 헤더를 적용하여 민감 데이터의 캐싱을 방지했다.
도입 체크리스트
- 기술적: 모든 상태 변경 요청(POST, PUT, DELETE)에 CSRF Token이 적용되어 있는가? SameSite 쿠키가 적용되어 있는가? GET 요청은 데이터 조회 전용으로 설계되어 있는가?
- 운영·보안적: Third-party 사이트에서 自社 사이트로의 요청이 필요한 경우, CORS 정책과 CSRF Token의 상호작용을 검토했는가?
안티패턴
-
GET 요청에서의 상태 변경: GET 요청은 CSRF Token 검증이 어려운 구조이므로, GET으로 상태를 변경하면 CSRF 취약점이 된다.
-
CSRF Token을 URL에 포함: CSRF Token을 GET 파라미터로 전달하면, Referer 헤더를 통해 유출되거나 서버 로그에 기록될 수 있다.
-
쿠키 검증에만 의존: 쿠키 값만으로 인증을 판단하고, 요청 출처나 토큰 검증을 수행하지 않으면 CSRF에 취약하다.
-
📢 섹션 요약 비유: CSRF 방어는 금융 기관에서 전화를 받은 상담원이 "본인 확인을 위해 추가 비밀번호 2개를 말씀해주세요"라고 묻는 것과 같다. 기존 세션(첫 전화 연결)만으로 거래를許可하면 속삭임에 넘어갈 수 있지만, 추가 인증(CSRF Token)을 요구하면 공격자가 거래를実行할 수 없다.
Ⅴ. 기대효과 및 결론
정량/정성 기대효과
| 구분 | 방어 도입 전 | 방어 도입 후 | 개선 효과 |
|---|---|---|---|
| 정량 | CSRF 취약점 15건 | 0건 | 취약점 100% 제거 |
| 정량 | SameSite 쿠키 미적용 | SameSite=Lax 적용 | 브라우저 레벨 1차 방어 |
| 정성 | CSRF Token 개별 구현 | 프레임워크 표준 지원 활용 | 일관된 보안 정책 |
미래 전망
SameSite 쿠키의 보편화로 CSRF 위험이 크게 감소하고 있으며, 모던 브라우저(Chrome, Firefox, Safari)에서는 SameSite=Lax가 Default로 적용되어, 명시적 SameSite 지정 없이도跨사이트 POST 요청에서 쿠키가 전송되지 않는다. 그러나 레거시 브라우저 지원이 필요한 경우나, CORS와 SameSite의 상호작용에서 예외 상황이 있을 수 있으므로, CSRF Token 방어는 여전히 권장된다. 또한 SPA(Single Page Application)에서는 JWT를LocalStorage에 저장하는 경우가 많은데, 이 경우 쿠키 기반 CSRF 방어가 적용되지 않아,X-CSRF-Token 헤더 기반 방어가 필수이다.
📌 관련 개념 맵 (Knowledge Graph)
| 개념 명칭 | 관계 및 시너지 설명 |
|---|---|
| XSS | XSS를 利用하면 CSRF Token을 탈취하거나, 토큰 검증 없이 요청을発行할 수 있어, XSS 방어가 CSRF 방어의 전제 조건이 된다. |
| SameSite Cookie | 브라우저 레벨에서 Cross-Site 요청 시 쿠키 전송을 차단하여, CSRF攻撃의 主要 벡터인 자동 쿠키 전송을防止한다. |
| CSRF Token | 서버가 생성한 예측 불가능한 토큰을 요청에 포함시켜, 공격자가victim의 요청을構成할 수 없도록 하는 애플리케이션 레벨 방어이다. |
| CORS | Cross-Origin 요청을 명시적으로 허용/차단하며, CORS 설정 오류는 CSRF 위험을 증가시킬 수 있다. |
| RESTful API | GET은 상태 변경 없는 조회 전용으로 설계하면 CSRF 위험을구조적으로 줄일 수 있다. |
👶 어린이를 위한 3줄 비유 설명
-
CSRF는 어른이 잠깐 자리를 비웠을 때, 옆에 있던 자녀가 "엄마 동의 없이" 부모님 카드로 온라인 쇼핑을 하는 것과 같아요. 점원이 전화를 받지 않고,(쿠키가 자동 전송되어) 보호자 확인 없이 결제가 되어버리는 거예요.
-
그래서 방법은, 웹사이트에서 중요한 버튼(송금, 구매, 삭제)을 누를 때마다 "비밀確認 코드"(CSRF 토큰)를 입력하게 하는 것이에요. 이렇게 하면 누군가 모르게 요청을 보내도, 코드 없이는 실제 거래가 이루어지지 않아요.
-
또 다른 방법으로는, 같은 가게에서 직접 찾은 사람(같은 사이트 요청)에만 카드를自動 인식시키고, 다른 곳에서 전화로 온 사람(다른 사이트 요청)에게는 카드를사용 못하게 하는 거예요. 이것이 바로 "SameSite 쿠키"라는 이름의ブラウザ 기능이에요.