CSRF는 사용자가 신뢰하는 웹사이트에서 본인의 의지와 무관하게 원치 않는 요청을 실행하도록 하는 공격 기법이다. 공격자는 사용자의 인증된 세션을 악용하여, 사용자가 특정 액션을 수행하도록 속일 수 있다.
CSRF 공격의 목적은 사용자가 의도하지 않은 요청을 실행하도록 유도 XSS 공격은 악성 스크립트를 삽입하여 피해자의 브라우저에서 실행 하는 것이 목적이다. 두 개의 공격 방식을 조합하면 더 강력한 공격을 수행할 수 있다.
- XSS를 이용한 CSRF 우회 공격
- CSRF 방어 기법 중 하나가 CSRF 토큰 사용인데, XSS를 이용하면 CSRF 토큰을 탈취할 수 있음.
- 공격자는 XSS를 이용하여 사용자의 브라우저에서 자동으로 CSRF 요청을 실행할 수 있음.
공격 예제: XSS로 CSRF 토큰 탈취 및 자동 요청
<script> // 1. 피해자의 브라우저에서 CSRF 토큰을 가져옴 fetch("https://bawool.com/get_csrf_token") .then(response => response.text()) .then(token => { // 2. 가져온 CSRF 토큰을 사용하여 악성 요청을 보냄 fetch("https://bawool.com/transfer", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: "csrf_token=" + token + "&to=attacker&amount=1000000" }); }); </script>
- 공격자가 XSS 취약점을 이용해 피해자의 브라우저에서 위의 스크립트를 실행.
- 피해자의 브라우저에서 CSRF 토큰을 가져옴.
- 공격자는 탈취한 CSRF 토큰을 이용해 송금 요청을 자동 실행.
- CSRF 방어 기법이 무력화되며 공격이 성공함.
- CSRF를 이용한 XSS 확산 공격
- CSRF를 이용하면 XSS 공격을 특정 사용자의 계정이나 시스템에 삽입할 수 있음.
- 공격자는 피해자의 계정에 XSS 코드가 포함된 데이터를 삽입하여 지속적인 악성 코드 실행을 유도.
공격 예제: CSRF로 XSS 코드 삽입
<img src="https://bawool.com/update_profile?bio=<script>alert('Hacked');</script>" />
- 공격자가 CSRF 공격을 이용해 피해자의 계정에 XSS 코드 삽입.
- 피해자가 로그인한 상태에서 위의 악성 요청이 실행됨.
- 피해자의 프로필 정보에 XSS 코드가 저장됨.
- 이후 다른 사용자가 피해자의 프로필을 방문하면 XSS 코드가 실행됨.
결과적으로, CSRF로 인해 피해자가 직접 악성 XSS를 삽입한 것처럼 되어버림!
CSRF 토큰은 CSRF(Cross-Site Request Forgery) 공격을 방어하기 위한 보안 기법이다. 서버가 발급한 난수 값을 요청에 포함하여, 공격자가 위조된 요청을 보내지 못하도록 함.
사용자가 로그인하면 서버가 난수(랜덤) 값을 생성하여 CSRF 토큰을 발급
서버는 해당 CSRF 토큰을 세션 또는 쿠키에 저장하고, 클라이언트는 요청을 보낼 때 이 토큰을 포함
사용자가 폼을 제출하면 CSRF 토큰이 요청과 함께 전송
서버는 요청의 CSRF 토큰과 저장된 토큰이 일치하는지 검증하고, 유효하지 않으면 요청을 차단
HTTP 요청의 Referer(또는 Origin) 헤더를 확인하여 신뢰할 수 없는 출처에서 온 요청을 차단하는 방법.
사용자가 웹사이트에서 요청을 보냄.
브라우저는 요청을 보낼 때 Referer 헤더를 포함함.
서버는 Referer 값을 확인하여, 요청이 신뢰할 수 있는 출처에서 왔는지 검증함.
만약 Referer가 없거나, 신뢰할 수 없는 도메인에서 온 요청이라면 요청을 차단함.
✔ 간단한 구현: CSRF 토큰 없이도 CSRF 공격을 차단할 수 있음.
✔ 자동 적용: 브라우저가 기본적으로 Referer 정보를 포함하므로 클라이언트 측 변경이 필요 없음.
✔ 기존 시스템과 호환: CSRF 토큰을 도입하기 어려운 환경에서 대체 방안으로 활용 가능.
한 출처(Origin)에서 로드된 웹페이지의 스크립트가 다른 출처의 리소스에 접근하는 것을 제한하는 보안 정책.
웹 브라우저는 같은 출처(Same-Origin)의 요청만 허용함.
✔ 동일 출처: 프로토콜 + 도메인 + 포트가 모두 같아야 함.
✔ 다른 출처(다른 Origin)의 요청은 차단됨.
동일 출처 (Same-Origin, 허용됨)
https://bawool.com/page1 → https://bawool.com/page2 ✅
✔ 같은 프로토콜 (https://)
✔ 같은 도메인 (bawool.com)
✔ 같은 포트 (443, HTTPS 기본 포트)
다른 출처 (Cross-Origin, 차단됨)
https://bawool.com → http://bawool.com ❌ (다른 프로토콜)
https://bawool.com → https://api.bawool.com ❌ (다른 서브도메인)
https://bawool.com → https://bawool.com:8080 ❌ (다른 포트)
✔ XSS(크로스사이트 스크립팅)으로 인한 데이터 탈취 방지
✔ CSRF(사이트 간 요청 위조)와 같은 공격 완화
✔ 악성 웹사이트에서 중요한 정보에 접근하지 못하도록 보호
SOP는 완전히 다른 출처의 요청을 차단하지만, 웹 애플리케이션 간의 데이터 공유가 필요할 경우 CORS 정책을 사용해야 함.
CORS는 SOP의 제한을 완화하여, 특정 출처에서 요청을 허용하도록 하는 메커니즘 즉, "서버에서 허락한 출처만 교차 출처 요청을 허용한다" 는 정책.
클라이언트(브라우저)가 다른 출처(Origin)의 리소스에 요청을 보냄.
서버는 HTTP 응답 헤더에 Access-Control-Allow-Origin 값을 포함하여 허용된 출처인지 확인.
만약 허용된 출처라면 요청이 성공적으로 수행됨.
허용되지 않은 출처라면 브라우저가 요청을 차단함.
Access-Control-Allow-Origin: https://allowed-origin.com
* 는 보안 취약 가능성이 있음)Access-Control-Allow-Origin: *
GET /data HTTP/1.1
Host: api.example.com
Origin: https://bawool.example.com
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://bawool.example.com
Access-Control-Allow-Origin 값이 요청 Origin과 일치하면 요청이 성공함!
✔ SOP(Same-Origin Policy) 는 보안 강화를 위해 다른 출처의 요청을 기본적으로 차단하는 정책.
✔ CORS(Cross-Origin Resource Sharing) 는 서버가 특정 출처에서의 요청을 허용할 수 있도록 예외를 설정하는 방식.
✔ 보안이 중요한 경우 CORS를 제한적으로 사용하고, 모든 출처(*) 허용은 지양해야 함.