CSRF란 무엇인가
CSRF(Cross-Site Request Forgery, 사이트 간 요청 위조)는 사용자가 로그인한 상태를 악용해, 사용자도 모르는 사이에 원치 않는 요청을 서버로 전송하게 만드는 공격입니다. 공격자는 사용자의 계정을 직접 해킹하지 않고도, 사용자의 ‘인증된 세션’을 훔쳐 쓰는 셈입니다.
비유하자면 이렇습니다. 당신이 은행 창구에서 신분 확인을 마치고 대기 중일 때, 누군가 몰래 당신 이름으로 된 이체 신청서를 창구에 슬쩍 끼워 넣는 것과 같습니다. 창구 직원(서버)은 이미 당신이 신분 확인을 마쳤다고 믿기 때문에, 그 요청이 진짜 당신의 의도인지 검증 없이 처리해버립니다.
동작 원리와 공격 예시
CSRF는 브라우저가 요청을 보낼 때 쿠키를 자동으로 함께 전송하는 특성을 악용합니다. 예를 들어 사용자가 bank.com에 로그인한 상태에서, 공격자가 만든 악성 페이지에 접속했다고 가정해봅시다. 그 페이지에는 다음과 같은 코드가 숨어 있을 수 있습니다.
<img src="https://bank.com/transfer?to=attacker&amount=1000000">
사용자는 이미지를 보는 것뿐이지만, 브라우저는 이 요청을 보낼 때 bank.com에 대한 로그인 쿠키를 자동으로 함께 전송합니다. 서버 입장에서는 정상적으로 인증된 사용자의 요청처럼 보이기 때문에 이체가 그대로 처리될 수 있습니다. 사용자는 자신도 모르는 사이에 공격에 이용당하는 것입니다.
실무에서의 방어 방법
이런 이유로 실무에서는 CSRF를 막기 위한 여러 장치를 반드시 적용합니다.
- CSRF 토큰: 요청마다 예측 불가능한 토큰을 발급하고, 서버는 이 토큰이 일치하는 요청만 처리합니다.
- SameSite 쿠키 속성: 쿠키에
SameSite=Lax또는Strict를 설정해 다른 사이트에서의 요청에는 쿠키가 자동으로 실리지 않도록 제한합니다. - Referer/Origin 헤더 검증: 요청이 실제로 자사 도메인에서 발생했는지 서버에서 한 번 더 확인합니다.
- 중요한 작업은 GET이 아닌 POST 등으로 처리하고, 상태를 변경하는 요청에는 반드시 인증 검증을 추가합니다.
CSRF는 XSS처럼 코드를 직접 주입하지 않고도 사용자의 신뢰 관계를 악용하는 공격이기 때문에, 프레임워크에서 기본 제공하는 CSRF 방어 기능을 임의로 끄지 않는 것이 중요합니다. 로그인 세션을 다루는 서비스를 만든다면, 이 개념은 선택이 아닌 필수 지식으로 익혀두어야 합니다.