天天看点

MySQL隐式转化整理存在的安全问题总结

今天还是和往常一样看着微信推的订阅号文章

有一篇 select * from user where uersname=0引起了我的思考

其实这个问题是MySQL隐式转化整理存在的安全问题

网上一搜比较多,我这里就参考师傅们写的文章进行总结和学校

官方给的解释:

MySQL 的隐式类型转换原则:

– 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种情况都不需要做类型转换

– 两个参数都是字符串,会按照字符串来比较,不做类型转换

– 两个参数都是整数,按照整数来比较,不做类型转换

– 十六进制的值和非数字做比较时,会被当做二进制串,和数字做比较时会按下面的规则处理

– 有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为 timestamp

– 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较

– 所有其他情况下,两个参数都会被转换为浮点数再进行比较

注意一个安全问题:假如 password 类型为字符串,查询条件为 int 0 则会匹配上。

在这里我就只是总结用法,详细的原理下面会给出师傅们链接。防止重复造轮子

在一般的网站登录的用户名和密码都是varchar类型

这样就可能存在安全问题(下面讨论就是比较经典,师傅们可以自由发挥好)

select * from user where uersname=$_POST['username']
user表有
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | admin1   |    12345 |
|  2 | admin2   |      123 |
|  3 | admin3   |      321 |
+----+----------+----------+
           

我们就可以直接利用payload:

select * from user where uersname=0

进行查询

MariaDB [test]> select * from user where username=0;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | admin1   |    12345 |
|  2 | admin2   |      123 |
|  3 | admin3   |      321 |
+----+----------+----------+
           

原因就是上面说的进行了隐式转化 username是varchar类型,但是查询的时候使用了0(int)类型

这样username的值就进行了隐式转化成0,刚刚好0=0,就查询出来了全部

MariaDB [test]> select "admin"=0;
+-----------+
| "admin"=0 |
+-----------+
|         1 |
+-----------+
#这样我们就可以尝试新方法的万能密码
           

但是如果username字段里面的值不能字母开头的是数字开头的那就不能进行万能密码

MariaDB [test]> select "1213admin"=0;
+---------------+
| "1213admin"=0 |
+---------------+
|             0 |
+---------------+
           

总结:

0. 从上面的例子可以看出,当把字符串转为数字的时候,其实是从左边开始处理的。

  1. 如果字符串的第一个字符就是非数字的字符,那么转换为数字就是0
  2. 如果字符串以数字开头

    2.1 如果字符串中都是数字,那么转换为数字就是整个字符串对应的数字

    2.2 如果字符串中存在非数字,那么转换为的数字就是开头的那些数字对应的值

参考

https://www.cnblogs.com/rollenholt/p/5442825.html