CSRF
- Cross site request forgery, 사이트간 요청 위조.
- 인증된 유저의 계정을 사용해 악의적인 요청을 만들어 보내는 기법.
예시
- 은행 웹 사이트가 현재 로그인 한 사용자에게
다른 은행 계좌로 송금 할 수 있는 양식을 제공한다고 가정하자.
1) 다른 계좌에 송금하는 HTTP 요청은 다음과 같다.
POST /transfer HTTP/1.1
Host: bank.example.com
Cookie: JSESSIONID=randomid; Domain=bank.example.com; Secure; HttpOnly
Content-Type: application/x-www-form-urlencoded
amount=100.00&routingNumber=1234&account=9876
2) 해당 은행 웹 사이트에 로그인하여 인증된 상태에서 악의적인 웹 사이트에 우연히 접속하게 되었다.
3) 악의적인 웹 사이트에는 아래와 같은 HTML 페이지가 있다.
<form action="https://bank.example.com/transfer" method="post">
<input type="hidden"
name="amount"
value="100.00"/>
<input type="hidden"
name="routingNumber"
value="evilsRoutingNumber"/>
<input type="hidden"
name="account"
value="evilsAccountNumber"/>
<input type="submit"
value="Win Money!"/>
</form>
최악의 경우 Javascript를 이용하여 위 양식을 자동으로 제출하게한다.
<body onload="document.forms[0].submit()">
4) 이제 사용자는 악의적인 사용자에게 돈을 송금하게 될 것이다. 사용자의 인증정보인 쿠키와 함께 전송되기 때문이다.
방어 기법 1 : Referrer 검증
- 서버에서 Request의 Referrer을 확인하여 도메인이 일치하는지 확인한다.
방어 기법 2 : Synchronizer Token Pattern
- 쿠키 이외에도 매 요청에 임의로 생성된 토큰을 HTTP 매개 변수로 요청하도록 한다.
- 임의로 생성 된 토큰이 _csrf라는 HTTP 매개 변수에 있다고 가정한다.
- 송금 요청은 다음과 같다.
POST /transfer HTTP/1.1
Host: bank.example.com
Cookie: JSESSIONID=randomid; Domain=bank.example.com; Secure; HttpOnly
Content-Type: application/x-www-form-urlencoded
amount=100.00&routingNumber=1234&account=9876&_csrf=<secure-random>
- 악의적인 사이트는 _csrf 값을 알 수 없기 때문에 요청에 실패한다.