사이드 프로젝트를 할 때는
CSRF 같은 보안 이슈를 깊게 고민해본 적이 거의 없었다.
사용자도 많지 않았고,
솔직히 말하면 이런 생각이 더 컸다.
“설마 누가 이걸 공격하겠어?”

하지만 서비스를 실제로 배포하고,
“모든 케이스를 고려해야 하는 상황”이 되니까
생각이 완전히 바뀌었다.
이제 보안은 옵션이 아니라 기본값이었다.
그래서 가장 먼저 정리하기로 한 게 CSRF였다.
CSRF는 사이트 간 요청 위조를 의미한다.
웹 보안 취약점 중 하나로, 사용자가 자신의 의지와는 상관없이
공격자가 의도한 요청을 특정 웹사이트로 보내게 만드는 공격이다.
예를 들면 이런 것들이다.
특성에 따라 공격자는
사용자의 계정 권한으로 중요한 행위를 직접 실행해버릴 수 있다.
간단하게 정리하자면!
공격자가 내 계정에 로그인하는 게 아니라,
내 브라우저를 이용해서 “내 계정으로” 요청을 만든다.
CSRF는 아무 상황에서나 발생하지 않는다.
보통 아래 조건들이 동시에 만족돼야 한다.
사용자는 이미 로그인된 상태여야 한다
→ 브라우저에 인증 쿠키 / 세션이 남아 있음
서비스가 쿠키 기반 인증을 사용해야 한다
→ 요청마다 브라우저가 쿠키를 자동으로 포함
공격자가
“어떤 요청이 상태를 바꾸는지”를 알고 있어야 한다
→ 엔드포인트, 파라미터 구조가 예측 가능해야 함
API 구조가 프론트에 그대로 노출되어 있거나
REST 규칙을 너무 정직하게 지키고 있을수록
오히려 공격 포인트가 되기도 한다.
여기서 자주 생기는 오해가 하나 있다.
❌ “공격자가 세션 쿠키를 훔쳐야 CSRF가 되는 거 아닌가요?”
👉 아니다.
대부분의 CSRF 공격은
쿠키를 훔치지 않는다.
흐름은 생각보다 단순하다.

session_id / access_token 이 저장된다즉 핵심은 이거다.
공격자는
쿠키를 읽을 필요도 없고, 훔칠 필요도 없다.
사용자의 브라우저가 대신 요청을 보내주기만 하면 된다.
취약한 서비스에서
배송지 변경 API가 이렇게 열려 있다고 가정해보자.
POST /api/account/shipping-address
Cookie: session_id=s3ss10n_xxxxxxxxx
Content-Type: application/json
{"address":"서울시 어딘가 123-45"}
사용자가 이미 로그인된 상태라면
공격자는 session_id 값을 전혀 몰라도 된다.
외부 페이지에서
이 요청만 한 번 유도하면 끝이다.
서버 입장에서는
“로그인한 사용자가 보낸 요청”처럼 보이기 때문이다.
CSRF 이야기에서 빠지지 않는 주제가 하나 더 있다.
바로 GET 요청이다.
GET은 원래 조회용인데,
실수로 상태 변경 API를 GET으로 열어두면 바로 위험해진다.
/logout/unsubscribe/delete-account<img src="https://vulnerable-app.local/logout" />
이 코드 한 줄만 있어도
클릭 없이 요청이 나간다.
그래서 결론은 명확하다.
상태를 바꾸는 요청은
무조건 POST / PUT / PATCH / DELETE 로만 처리한다.
사용자 입장에서 할 수 있는 건 사실 많지 않다.
요청 헤더의 Referer 또는 Origin 값을 보고
우리 도메인에서 온 요청인지 검사하는 방식이다.
정상 요청 예시
Host: app.local
Referer: https://app.local/profile
외부에서 유도된 요청
Host: app.local
Referer: https://evil.local/page
이걸 보고 다르면 차단한다.
Referer는 항상 오는 값이 아니다
→ 브라우저 / 정책에 따라 누락될 수 있음
절대적인 신뢰 값이 아니다
→ curl, Postman 같은 클라이언트에서는 조작 가능
그래서 결론은 하나다.
Referer / Origin 체크는
보조 수단이지, 단독 방어책은 아니다.
원리는 단순하다.
access_token → httpOnly=truecsrf_token → httpOnly=falsedocument.cookie로 csrf_token 읽음x-csrf-token 헤더에 담아 전송csrf_tokenx-csrf-token 비교핵심 포인트는 이거다.
x-csrf-token 헤더를 구성할 수 없다아니다.
여기서 항상 나오는 질문이 있다.
“자바스크립트로 쿠키 읽어서 헤더 넣는 구조면
스크립트로 요청 보내면 되는 거 아닌가요?”
맞다. 그건 CSRF가 아니라 XSS다.
공격자가 우리 사이트 컨텍스트에서 JS를 실행할 수 있다면
document.cookie 읽을 수 있고그래서 결론은 이거다.
CSRF 방어는 XSS 방어와 같이 가야 좋을듯하다고 생각이 된다.