본문 바로가기
Hacking/DreamHack

[DreamHack] 드림핵 out of money

by st-og 2024. 1. 19.

문제 확인

 

해당 문제는 여러 코인의 구매와 대출을 통해 DHH코인을 1000개를 모으고 빚이 없을 경우 플래그를 획득할 수 있는 문제이다.

서비스 분석

해당 페이지를 처음 접속하면 로그인 페이지를 확인할 수 있다.

로그인 페이지

 

해당 입력칸에 자신의 이름을 입력하면 사설 거래소와 유동성 풀로 접근할 수 있는 인덱스 페이지를 확인할 수 있다.

인덱스 페이지 /

 

아래 그림은 산타 사설 거래소의 페이지이다.

산타 사설 거래소 /santa/

해당 페이지에서는 DHH코인을 빌릴 수 있으며 각 코인을 다른 코인으로 바꾸는 기능과 Flag를 구매할 수 있는 것을 확인할 수 있다.

 

아래 그림은 드림 유동성 풀의 페이지이다.

드림 유동성 풀 /dream/

해당 페이지에서는 DHC코인을 담보로 DHD코인을 빌릴 수 있으며 예금 기능이 가능한 것을 확인할 수 있다.

소스 코드

아래 그림은 /santa 페이지의 소스코드이다.

해당 페이지에 접속하였을 때 화면에 santa.html을 출력하는 코드이다.

 

 

아래 그림은 /santa 페이지에서 DHH 빌리기 버튼을 눌렀을 때 실행되는 코드이다.

37: 입력한 값을 float형태로 바꾸어 value변수에 저장한다

39~40: 지금까지 빌린 DHH값과 입력한 값이 10000 이상일 경우 더 이상 빌리지 못하도록 한다

41~42: 현재 내 DHH값과 입력한 값이 0보다 작을 경우 잘못된 값이므로 메시지를 출력하며 해당 요청은 무시한다.

44~46: 위의 경우가 아닐 경우 현재 내 DHH 값에 입력한 값을 추가하고 빌린 DHH값에도 입력한 값을 추가하며 요 청이 성공적으로 이루어졌음을 나타내는 메시지를 출력한다.

 

 

아래 그림은 /santa 페이지에서 flag구매를 선택하였을 경우 실행되는 코드이다.

현재 가지고 있는 DHH코인이 1000 이상이 되며 빌린 DHH코인이 0일 경우 flag를 획득하며 그렇지 않은 경우 각 경우에 맞는 에러 메시지를 출력한다.

 

 

아래 그림은 /santa페이지에서 코인 바꾸기 버튼을 눌렀을 때 실행되는 코드이다.

59~61: from과 to는 str형태로 요청이 오기에 int형태로 바꾸어주며 value값은 float의 형태로 바꿔 준다.

63~64: value의 값이 0보다 작을 경우 에러메시지를 출력한다.

66~69: frm과 to의 변수에 저장된 숫자에 따라 지정된 값으로 변경해 준다. {DHH:0} {DHC:1} {DHD:2}

71~72: 현재 내가 가지고 있는 코인 수가 value의 값보다 작을 경우 에러메시지를 출력한다.

74~81: 다른 코인으로 변환할 경우라면 from과 to의 session값을 변경하여 준다.

아래 그림은 /dream 페이지의 소스코드이다.

해당 페이지에 접속하였을 때 화면에 dream.html을 출력하는 코드이다.

 

아래 그림은 /dream페이지에서 DHC 담보내기 버튼을 클릭했을 때 실행되는 코드이다.

91: 입력받은 값을 float형태로 바꾸어 value변수에 저장한다

93~99: 입력한 값이 음수일 경우 담보를 반환한다. 이때 빚이 있을 경우 에러메시지를 출력한다.

100~101: 현재 가지고 있는 DHC코인보다 큰 담보금이 입력될 경우 에러메시지를 출력한다.

103~105: 위의 경우가 아닐 경우 입력한 만큼 DHC코인을 담보금에 저장한다.

 

 

아래 그림은 /dream페이지에서 예금하기 버튼을 클릭했을 때 실행되는 코드이다.

109~110: 예금액과 예금코인 타입을 각 변수에 float과 int형태로 저장한다.

112~113: 예금코인 타입이 0 또는 1이 아닐 경우에 에러메시지를 출력한다.

115~116: 예금 코인 타입이 0일 경우 DHC, 1일 경우 DHD로 변경한다.

117~118: 가지고 있는 코인보다 큰 금액을 예금할 시 에러메시지를 출력한다.

119~120: 기존 예금액에서 더 큰 금액을 출금하려 하면 에러 메시지를 출력한다.

121~124: 위의 경우가 아닐 경우 입력한 금액만큼 예금 또는 출금한다.

 

 

아래 그림은 /dream페이지에서 DHD 빌리기 버튼을 클릭했을 때 실행되는 코드이다.

128: 입력한 값을 float형태로 변경 후 value변수에 저장한다.

130~133: dhc_price와 dhd_price변수에 get_price함수를 통해 1.0이라는 값이 저장되며 max_lend변수에 0.8의
값이 저장된다. 해당 과정은 담보 기준 현재 빌릴 수 있는 금액을 지정하기 위한 과정이다.

137~138: 가지고 있는 DHD코인과 입력된 값의 합이 0보다 작을 경우 잘못된 값이므로 에러 메시지를 출력한다.

139~140: 최대 담보금보다 높은 금액이 입력될 경우 에러메시지를 출력한다.

142~145: 위의 경우가 아닐 경우 DHD코인을 대출받는다.

문제 해결

해당 문제의 해결 방법은 아래의 코드에서 답을 찾을 수 있다.

/dream/lend 코드 일부

DHD코인은 현재 내가 가진 담보의 max_lend만큼 빌릴 수 있다. 하지만 한 번에 빌릴 수 있는 DHD코인만 지정해 두고 최대량은 정해두지 않았다 해당 취약점을 이용하여 DHD코인을 여러 번 빌릴 경우 담보금 보다 더 큰 코인을 빌릴 수 있다.

 

먼저 담보금을 구하기 위해 /santa 페이지에서 DHH코인을 2000만큼 빌렸다.

그 후 담보금을 넣기 위해 DHH코인을 DHC 코인으로 변경하였다.

 

 

 

가지고 있는 DHC코인을 /dream페이지에서 담보로 하였다.

 

 

해당 담보를 통해 1000 DHD코인 빌리기를 3번 시도하였다.

기존의 담보금 보다 더 큰돈을 빌릴 수 있는 것을 확인하였다.

 

다시 /santa페이지로 돌아가 빌린 DHD코인을 DHH코인으로 변환하였다.

 

빚을 없애기 위해 DHH 빌리기 입력칸에 -2000을 입력하여 빚을 없애 주었다.

빚이 없는 상태로 1000원을 들고 있으므로 flag 구매를 할 수 있게 되었다.

Flag 구매 버튼을 클릭을 하면 

성공적으로 flag를 획득할 수 있다.

FLAG

DH{https://etherscan.io/tx/0x958236266991bc3fe3b77feaacea120f172c0708ad01c7a715b255f218f9313c}