Cross Site Request Forgery
임의 이용자의 권한으로 임의 주소에 HTTP 요청을 보낼 수 있는 취약점
우선 이 공격이 성공하려면 공격자가 작성한 악성 스크립트를 이용자가 실행을 해야 한다.
이런 스크립트의 실행을 유도하는 방법으로 메일로 보내거나 게시판에 글을 올리는 등등의 방식으로 유도한다.
CSRF 공격 스크립트는 HTML 또는 Javascript를 통해 작성할 수 있다.
<img src='http://bank.dreamhack.io/sendmoney?to=yamewrong&amount=1337' width=0px height=0px>
위 코드는 img 태그를 사용한 스크립트의 예시인데, 해당 태그는 이미지의 크기를 줄일 수 있는 옵션을 제공해서 이렇게 하면 사용자에게 들키지 않고 임의 페이지에 요청을 보낼수 있당
window.open('http://bank.dreamhack.io/sendmoney?to=dreamhack&amount=1337');
위 코드는 새 창을 띄우는 것이다
location.href = 'http://bank.dreamhack.io/sendmoney?to=dreamhack&amount=1337';
location.replace('http://bank.dreamhack.io/sendmoney?to=dreamhack&amount=1337');
위 코드는 현재 창 주소를 옮기는 것이다
예를 들어서 아래 코드와 같이 송금 기능이 있는 웹 서비스가 있다고 가정하자
# 이용자가 /sendmoney에 접속했을때 아래와 같은 송금 기능을 웹 서비스가 실행함.
@app.route('/sendmoney')
def sendmoney(name):
# 송금을 받는 사람과 금액을 입력받음.
to_user = request.args.get('to')
amount = int(request.args.get('amount'))
# 송금 기능 실행 후, 결과 반환
success_status = send_money(to_user, amount)
# 송금이 성공했을 때,
if success_status:
# 성공 메시지 출력
return "Send success."
# 송금이 실패했을 때,
else:
# 실패 메시지 출력
return "Send fail."
위와 같이 구성되어 있고, 계정은 dreamhack일때, dreamhack의 계정에 송금하는 CSRF스크립트문을 게시판을 이용해서 작성해보자.
위와 같은 경우 javascript문은 제한되어 있으므로 HTML 코드를 사용해서 접근해보도록 하자.
이때, 게시판에 아래와 같은 코드를 넣어서 송금을 유도할 수 있다.
<img src="/sendmoney?to=dreamhack&amount=1337">
<img src=1 onerror="fetch('/sendmoney?to=dreamhack&amount=1337');">
<link rel="stylesheet" href="/sendmoney?to=dreamhack&amount=1337">
둘다 스크립트를 웹 페이지에 작성하는 공격이다
둘다 클라이언트를 대상으로 하는 공격이고, 유도를 해야한다는 공통점이 있다
하지만
서로 목적이 다르다.
XSS는 인증 정보인 세션 및 쿠키 탈취를 목적으로 하는 공격이다. 이는 공격할 사이트의 오리진에서 스크립트를 실행시킨다.
CSRF는 이용자가 임의 페이지에 HTTP 요청을 보내는 것이 목적이다. 또한, 공격자는 공격당한 이용자의 권한으로 웹 서비스의 임의 기능을 실행할 수 있다.