- Web Hacking_ClientSide: CSRF2024년 09월 22일 13시 48분 52초에 업로드 된 글입니다.작성자: sonootri
1. 서론
이용자의 신원 정보가 포함된 Cookie는 일종의 서명과 같은 역할을 한다. 이용자의 식별 정보가 포함된 쿠키는 클라이언트에 보내진 요청이 이용자로부터 왔으며, 이용자가 동의했고, 따라서 요청에 이용자의 권한이 부여돼야함을 의미한다.
실생활과 밀접한 웹 서비스가 많아지고 있기 때문에, 서명을 신중하게 관히라는 것 만큼 중요한 웹서비스의 쿠키도 잘 보관해야한다.
서명된 문서를 위조하는 것은, 이미 서명된 문서의 내용을 조작하는 것을 말한다.
CSRF(Cross Site Request Forgery)는 이와 비슷하게 이용자를 속여서 의도치 않은 요청에 동의하게 하는 공격을 의미한다. 그럴듯한 웹 페이지를 만들어서 이용자의 입력을 유도하고, 이용자가 값을 입력하면 이를 은행이나 중요 포털 사이트 등으로 전송하여 마치 이용자가 동의한 것 같은 요청을 발생시킨다.
2. Cross Site Request Forgery (CSRF)
웹 서비스는 Cookie 또는 Session을 사용해 사용자를 식별한다. 임의 이용자의 쿠키를 사용할 수 있다면, 이는 곧 임의 이용자의 권한으로 웹 서비스이 기능을 사용할 수 있는 것이다.
CSRF는 임의 이용자의 권한으로 임의 주소에 HTTP 요청을 보낼 수 있는 취약점이다. 공격자는 임의 이용자의 권한으로 서비스 기능을 사용해 이득을 취할 수 있다. 예를 들어, 이용자의 계정으로 임의 금액을 송금해 금전적인 이득을 취하거나 비밀번호를 변경해 계정을 탈취하고, 관리자 계정을 공격해 공지사항 작성 등으로 혼란을 야기할 수 있다.
2.1. CSRF 공격 방법
1) 공격자는 본인의 사이트에 일반 사용자가 접근하도록 유도한다 (메일 발송 등)
2) 공격자의 사이트에 접근한 사용자는, 접근한 페이지 내에서 img 태그나 form 태그에 공격자의 의도가 담긴 Parameter를 담아 공격할 서버에 전송하게 한다.
2.2. CSRF 동작
CSRF 공격에 성공하기 위해서는, 공격자가 작성한 악성 스크립트를 이용자가 실행해야 한다 (여기서 말하는 악성 스크립트는 HTTP 요청을 보내는 코드이다). 이를 위해 공격자는 이용자에게 메일을 보내거나 게시판에 글을 작성해 이용자가 이를 조회하도록 할 수 있다.
CSRF 공격 스크립트는 HTML 또는 JS를 통해 작성할 수 있다. 이미지를 불러오는 <img>태그를 사용하거나, 웹 페이지에 입력된 양식을 전송하는 <form>태그를 사용하는 방법이 있다. 이 두 개의 태그를 사용해 HTTP 요청을 보내면 HTTP 헤더인 Cookie에 이용자의 인증 정보가 표시된다.
아래 코드는 <img> 태그를 사용한 스크립트 예시이다. " width=0px height=0px "을 통해 사진의 크기가 0, 즉 사진이 보여지지 않게 한다. 이를 활용하면 이용자에게 들키지 않고 임의 페이지에 요청을 보낼 수 있다.
+) <img> 태그는 get방식, <form> 태그는 post 방식
<img src='http://bank.dreamhack.io/sendmoney?to=Dreamhack&amount=1337' width=0px height=0px>
3. CSRF 실습
- 취약한 게시판 기능: 공격자가 내용을 입력하면, 사용자들이 해당 내용이 담긴 게시물을 열람한다.
- 해당 엔트포인트에서 비밀번호 혹은 OTP 등을 이용해 추가적인 검증 과정을 거치지 않기 때문에, 취약한 게시판 기능과 /sendmoney 엔트포인트를 연계하여 CSRF 공격을 수행할 수 있다.
- 적절한 HTML 코드를 삽입하는 것으로 Dreamhack 계좌 잔고를 60,000원 이상으로 늘려라.
- <정보> Dreamhack 계정으로 로그인 된 상태이며, 사용자 6명이 페이지를 방문한다. Dreamhack 사용자를 제외한 각 사용자는 10,000원을 소지하고 있다.
# 이용자가 /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."
일단 게시판이 어떻게 작동하는지 살펴보기 위해 글을 하나 작성했다.
실습 밑에 있는 hits 수가 6까지 올라간다. 6명이 내 게시물을 열람하는것을 확인할 수 있다.
취약한 게시판 기능(사용자들이 공격자인 내가 쓴 게시물을 열람하는것) + /sendmoney 엔트포인트(비밀번호같은 추가 검증을 거치지 않는 부분)을 이용해 공격을 시도하면 될 것 같다.
<img>태그를 사용해서 익스플로잇 해보기로 했다. <img> 태그를 이용하면, 해당 img를 가져와야 하기 때문에 요청이 나간다. 그 요청에 해당하는 부분을 URL로 바꿔두면, 사용자가 공격자의 게시물을 클릭하였을 때 요청이 나가게 된다. 사용자가 게시물을 여는 순간 요청이 나가기 때문에 이 경우 서버 입장에서는 사용자가 요청한 것이 되므로 권한이 바뀌게 된다.
<img src="/sendmoney?to=Dreamhack&amount=10000"> <img src=1 onerror="fetch('/sendmoney?to=Dreamhack&amount=10000');"> //JS 사용
-> to=Dreamhack&amount=10000: Dreamhack으로 10000원을 보낸다 (내 계정이 Dreamhack이다.)
-> src=1은 존재하지 않는 이미지를 참조해 이미지 로딩 실패를 야기하다. 이로 인해 error가 발생한다
-> onerror: 이미지 로딩이 정상적으로 이루어지지 않을 때 실행할 JS 코드를 지정할 수 있다.
-> fetch 속성을 사용해 /sendmoney?to=Dreamhack&amount=10000 URL로 GET 요청을 보낸다.
4. CSRF 방어 기법
1) Referer 검증
Referer header는 Request에 포함된 요청하는 쪽의 웹 페이지 url을 나타낸다. 따라서 Referer 검증으로 CSRF 공격을 막아낼 수 있다.
2) 토큰 사용
서버에서 hash로 암호화된 토큰을 발급하고, 사용자는 매 요청마다 토큰을 함께 보내어 서버의 검증 과정을 거친다.
3) GET/ POST 요청 구분
GET과 POST 둘 모두 서버에 정보를 요청하는 HTTP 메서드이다.
GET은 서버로부터 정보를 요청할 때 사용하며, 파라미터에 내용이 노출되기 때문에 민감한 데이터를 다룰 때 사용하지 말아야 한다. POST는 GET보다 용량이 큰 데이터를 전송할 때 사용한다. 이 때는 파라미터에 정보가 담기지 않는다.
4. XSS와 CSRF의 차이
XSS와 CSRF는 스크립트를 웹 페이지에 작성해 공격한다는 점에서 매우 유사하다. 두 개의 취약점은 모두 클라이언트를 대상으로 하는 공격이며, 이용자가 악성 스크립트가 포함된 페이지에 접속하도록 유도해야한다.
두 개의 취약점은 공격에 있어 차이점을 보인다. XSS는 인증 정보인 세션 및 쿠키 탈취를 목적으로 하는 공격이며, 공격할 사이트이 오리진에서 스크립트를 실행시킨다. CSRF는 이용자가 임의 페이지에 HTTP 요청을 보내는 것을 목적으로 하는 공격이다. 또한 공격자는 악성 스크립트가 포함된 페이지에 접근한 이용자의 권한으로 웹 서비스의 임의 기능을 실행할 수 있다.
간단히 말하자면, XSS는 클라이언트를 공격하는 방식이라면 CSRF는 서버를 공격하는 방식이다.
'Dreamhack > Web Hacking' 카테고리의 다른 글
Web Hacking_csrf-2🚩 (0) 2024.09.24 Web Hacking_csrf-1🚩 (1) 2024.09.24 Web Hacking_Exercise: XSS - 2🚩 (0) 2024.09.22 Web Hacking_Exercise: XSS - 1🚩 (0) 2024.09.22 Web Hacking_ClientSide: XSS (0) 2024.09.18 다음글이 없습니다.이전글이 없습니다.댓글