한양과학기술고등학교

에듀테크 프로젝트 대시보드

CSRF 공격

🏦 정상 은행 앱 bank.example.com
💀 악성 사이트 evil-site.com
사용자가 은행에 로그인한 상태에서 이 악성 사이트를 방문하면…
브라우저에 저장된 세션 쿠키가 자동으로 함께 전송됩니다.
CSRF 방어 활성화 OFF
<!-- evil-site.com 에 숨겨진 폼 --> <form action="http://bank.example.com/transfer" method="POST" id="csrf"> <input type="hidden" name="to" value="해커계좌"/> <input type="hidden" name="amount" value="1000000"/> </form> <script> document.getElementById("csrf").submit(); // 사용자 모르게 자동 제출! </script>
🐍 FastAPI 서버 코드 main.py
@app.post("/transfer") async def transfer( request: Request, to: str = Form(...), amount: int = Form(...), ): # ❌ 세션만 확인 — CSRF 토큰 없음! session = request.cookies.get("session") if not session: raise HTTPException(401) # 세션만 있으면 바로 송금 처리 💀 return {"status": "transferred", "to": to, "amount": amount}
📋 서버 요청 로그 실시간
// 서버 대기 중...

📊 피해 현황
정상 송금 횟수 0
CSRF 공격 성공 0
CSRF 공격 차단 0
⚡ CSRF 공격 흐름
① 사용자 로그인
② 세션쿠키 발급
③ 악성사이트 방문
④ 숨겨진 폼 자동제출
⑤ 쿠키 자동 포함 전송
⑥ 서버: 정상 처리 💀
핵심 원인: 브라우저는 요청 출처(origin)에 상관없이 해당 도메인의 쿠키를 자동으로 함께 보냅니다. 서버는 쿠키만으로는 "누가 보낸 요청인지" 구별할 수 없습니다.
🛡️ FastAPI 방어 방법 3가지
① CSRF 토큰
로그인 시 서버가 난수 토큰 생성 → 폼에 hidden 필드로 포함 → 서버에서 검증.
악성 사이트는 토큰값을 알 수 없어서 위조 불가.

② SameSite 쿠키
세션 쿠키에 SameSite=Strict 또는 Lax 설정.
다른 도메인에서 출발한 요청에는 쿠키가 전송되지 않음.

③ Origin / Referer 검증
요청 헤더의 Origin이 허용된 도메인인지 미들웨어로 확인.
# FastAPI 미들웨어 예시 @app.middleware("http") async def check_origin(request, call_next): origin = request.headers.get("origin") if origin and origin != "https://bank.example.com": return Response("Forbidden", 403) return await call_next(request)