CSRF(Cross Site Request Forgery, 사이트 간 요청 위조)는 자신의 의지와 무관하게 공격자가 의도한 행위를 특정 사이트에 요청하게 하는 공격이다. 2008년 옥션 개인정보 유출 사건에서 사용된 공격 방식이다.
mybank.com
에 로그인 등의 과정으로 권한을 획득한 상태이다.GET https://mybank.com/transfer.jsp?recepient=attacker&value=1000
이 요청은 위의 그림에서 공격자에게 돈을 보내는 GET 요청이다. 공격자는 이 요청을 만들기 위해 링크나 <img>
태그를 이용할 수 있다. 링크를 이용하는 경우는 사용자가 그 링크를 클릭하는 경우 발생한다. 하지만 <img>
태그를 사용하는 경우 페이지가 로드되는 과정에서 이미지를 찾으려고 URL을 열게 되는데, 이 과정에서 요청이 실행된다.
<a href="https://mybank.com/transfer.jsp?recepient=attacker&value=1000"></a> //링크 이용
<img src="https://mybank.com/transfer.jsp?recepient=attacker&value=1000" />
POST https://mybank.com/transfer.jsp
POST를 이용하는 경우에는 GET 이용 방식에서 언급된 링크, <img>
태그가 동작하지 않기 때문에 <form>
태그를 이용한다.
<form action="https://mybank.com/transfer.jsp" method="POST">
<input type="hidden" name="recepient" value="attacker" />
<input type="hidden" name="value" value="1000"
...
</form>
공격자는 위의 그림과 같이 스크립트를 사용해 form 양식을 자동으로 전송시킬 수 있다.
<script>document.forms[0].submit()</script>
그래서 XSS랑 뭐가 다른 건가요?
XSS는 악성 스크립트가 사용자의 브라우저에서 실행되고, CSRF는 사용자의 권한을 도용해 악성 요청을 서버에 전송한다. 즉, XSS는 클라이언트 단에서의 공격이고, CSRF는 서버 단의 공격이다.
HTTP 헤더의 요청을 한 페이지의 정보를 가지고 있는 Referer 속성을 검증한다. 요청이 들어온 페이지가 다른 도메인이면 그 요청을 차단하는 것이다. 이 방법은 Paros, Zap, Fiddler 등의 프로그램으로 조작이 가능하다는 단점이 있다.
서버는 페이지를 전송할 때 임의의 값으로 만들어진 토큰을 페이지에 포함해 사용자에게 전송하고 세션에 저장한다. 이후 사용자 요청 시 사용자는 이 토큰을 서버로 전송하게 된다. 서버는 이 토큰 값이 세션에 저장된 값과 일치하는지 확인해 이 요청이 위조된 것이 아니라는 것을 확인한다. 확인 후 토큰은 폐기하고 다음 페이지를 전송할 때 다시 이 과정을 반복한다.
권한이 필요한 페이지에서 추가 인증 수단(ex) CAPTCHA)을 사용해 실제 사용자가 요청한 것이 맞는지 확인한다.