Fascination
article thumbnail

ClientSide: CSRF


# 들어가며 - 서론

- 쿠키: 이용자의 신원 정보가 포함되어 일종의 서명과 같은 역할을 함

- 이용자의 식별 정보가 포함된 쿠키: 클라이언트에서 보내진 요청이 이용자로부터 왔으며, 이용자가 동의했고, 따라서 요청에 이용자의 권한이 부여돼야 함을 의미함

- 쿠키를 탈취하는 공격과 이번 코스에서 배울 교차 사이트 요청 위조는 비슷함

- CSRF: 이용자를 속여서, 의도치 않은 요청에 동의하게 하는 공격

  > 그럴듯한 웹 페이지를 만들어서 이용자의 입력을 유도하고, 이용자가 값을 입력하면

    이를 은행이나 중요 포털 사이트 등으로 전송하여 마치 이용자가 동의한 것 같은 요청을 발생시킴

  > "자동 로그인" 기능: 브라우저에 세션 쿠키를 저장하고 있다면,

     실제로 계좌 이체가 발생하거나 비밀번호 초기화가 이루어질 수 있음

 

 

# Cross Site Request Forgery (CSRF)

1. Corss Site Request Forgery (CSRF)

- 웹 서비스: 쿠키 또는 세션을 사용해 이용자를 식별

- 임의 이용자의 쿠키를 사용할 수 있다면, 이는 곧 임의 이용자의 권한으로 웹 서비스의 기능을 사용할 수 있음

- CSRF는 임의 이용자의 권한으로 임의 주소에 HTTP 요청을 보낼 수 있는 취약점

- 공격자는 임의 이용자의 권한으로 서비스 기능을 사용해 이득을 취할 수 있음

  ex) 이용자의 계정으로 임의 금액을 송금해 금전적인 이득을 취하거나 비밀번호를 변경해 계정을 탈취하고,

       관리자 계정을 공격해 공지사항 작성 등으로 혼란을 야기할 수 있음

- 이용자의 송금 요청

GET /sendmoney?to=dreamhack&amount=1337 HTTP/1.1
Host: bank.dreamhack.io
Cookie: session=IeheighaiToo4eenahw3

- 송금 기능: CSRF 취약점이 존재하는 예제 코드로, 송금 기능을 수행

# 이용자가 /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."

> 이용자로부터 예금주와 금액을 입력받고 송금을 수행

> 이때 계좌 비밀번호, OTP 등을 사용하지 않기 때문에

로그인한 이용자는 추가 인증 정보 없이 해당 기능을 이용할 수 있음

 

2. Cross Site Request Forgery 동작

- CSRF 공격에 성공하기 위해서는 공격자가 작성한 악성 스크립트를 이용자가 실행해야 함

- 공격자가 이용자에게 메일을 보내거나 게시판에 글을 작성해 이용자가 이를 조회하도록 유도하는 방법 등이 있음

- 악성 스크립트: HTTP 요청을 보내는 코드

- CSRF 공격 스크립트는 HTML 또는 Javascript를 통해 작성할 수 있음

- 아래 그림은 HTML으로 작성한 스크립트

> 이미지를 불러오는 img 태그를 사용하거나

웹 페이지에 입력된 양식을 전송하는 form 태그를 사용하는 방법이 있음

> 이 두 개의 태그를 사용해 HTTP 요청을 보내면

HTTP 헤더인 Cookie에 이용자의 인증 정보가 포함됨

- HTML img 태그 공격 코드: img 태그를 사용한 스크립트의 예시

<img src='http://bank.dreamhack.io/sendmoney?to=dreamhack&amount=1337' width=0px height=0px>

해당 태그는 이미지의 크기를 줄일 수 있는 옵션을 제공하기 때문에

이용자에게 들키지 않고 임의 페이지에 요청을 보낼 수 있음

- Javascript 공격 코드 예시

/* 새 창 띄우기 */
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');

새로운 창을 띄우고, 현재 창의 주소를 옮기는 등의 행위가 가능

 

3. Cross Site Request Forgery 실습

- CSRF 실습 모듈

- 아래 코드로 작성된 모듈임

# 이용자가 /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."

- 일부 Javascript 실행이 제한되어 있으므로, HTML 태그를 통해 계좌 잔고를 1,000,000원 이상으로 늘려보기

제목과 내용을 입력하는 곳이 있음

<img src='http://bank.dreamhack.io/sendmoney?to=dreamhack&amount=1000000' width=0px height=0px>

to에는 dreamhack을 인자로, amount에는 문제에서 주어진 1000000을 입력

게시글 작성을 누르니 공격에 성공!

 

4. XSS와 CSRF의 차이

- XSS와 CSRF는 웹 페이지에 작성해 공격한다는 점에서 유사

- 공통점

  > 클라이언트를 대상으로 하는 공격이며, 이용자가 악성 스크립트가 포함된 페이지에 접속하도록 유도해야 함

- 차이점

  > XSS: 정보 인증인 세션 및 쿠키 탈취를 목적으로 하는 공격이며, 공격할 사이트의 오리진에서 스크립트를 실행

  > CSRF: 이용자가 임의 페이지에 HTTP 요청을 보내는 것을 목적으로 하는 공격. 또한, 공격자는 악성 스크립트가

     포함된 페이지에 접근한 이용자의 권한으로 웹 서비스의 임의 기능을 실행할 수 있음

             

 

# 마치며

- 키워드

① Cross Site Request Forgery (CSRF): 사이트 간 요청 위조, 이용자가 자신의 의지와는 무관하게 공격자가 의도한 행위를 특정 웹 사이트에 요청하게 만드는 공격

 

 

profile

Fascination

@euna-319

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!