MySQL有一个特点,当某个字段是字符串时,如果你的sql传数字
它会尝试把这一列所有值转换成数字进行匹配,如果不是数字则会转换为0.
创建表test,并插入测试数据
CREATE TABLE `test` (
`id` varchar(10) NOT NULL,
PRIMARY KEY (`id`)
);
insert into test values ('a');
insert into test values ('b');
正常情况下我们的查询应该是
select * from test where id = 'a';
为了复现这个漏洞我们使用
select * from test where id = 0;
或者
select * from test where id in (0);
神奇的事情就出现了
竟然查到了所有数据! 如果是删除或更新会是怎样一种场景呢?
没错,所有数据都被删除了 但是加上引号,这个问题就不会存在了
select * from test where id = '0';
想要利用这个漏洞,需要持久层拼出不带引号的sql。对于mybatis等,他们虽然是预编译的,如果没有强制指定值的类型,那么这个值的类型还是可以变化的,只要传入数字就能触发这个漏洞。 很多框架搭建者为了方便没有对复杂的参数进行对象封装,而是以JSON方式传递参数到后台,后台又用JSONObject这类通用对象,就可能导致这个数字0传入到数据库,触发清空表的漏洞了 目前在MySQL5.7以下版本存在这个问题,5.7以上版本 delete语句该问题已修复,select依旧可以复现