记一次sql注入实践
今天开发代码的时候发现自己的sql全是拼接的,不是where a = ?的那种,细思恐极啊,于是进行了一场sql注入实践。虽然失败了,但是还是得出了一些宝贵的经验。
首先从一个基础的分页查询语句开始分析:
Select r.a,r.b from role r where r.name like ‘role%’ order by r.create_time desc liimit 0,10;
说明:用户在界面输入的是role,其他都是stringbuilder拼接的。
一开始尝试使用如下输入:’delete from x ‘
那sql语句变成如下形式:
Select r.a,r.b from role r where r.name like ‘’delete from x ’%’ order by r.create_time desc liimit 0,10;
看到的现象是前端没有查询到数据,给了弹框提示,但是分页条显示undefined.
后来从网上查到sql 的like 注入可以是下面的形式:
%' AND 1=1 AND '%'='
那sql语句则变成如下形式:
SELECT r.a,r.b FROM role r WHERE r.name LIKE '%' AND 1=1 AND '%'='%' ORDER BY r.create_time DESC liimit 0,10;
这样的话一眼就看出来这是个正常的sql语句,并且可以被注入,是不是有点小儿科或者感到惊恐。放到数据库里执行应该是没有问题的。
那怎么才能更有威胁性呢,看如下sql语句:
SELECT r.a,r.b FROM role r WHERE r.name LIKE '%' AND 1=1 ;DELETE FROM rule WHERE 1=1 ; AND '%'='%' ORDER BY r.create_time DESC liimit 0,10;
那现在只要稍加修改就可以变成下面的形式:
SELECT r.a,r.b FROM role r WHERE r.name LIKE '%' AND 1=1 ;DELETE FROM rule WHERE 1=1 ;SELECT * FROM role r WHERE 1=1 AND '%'='%' ORDER BY r.create_time DESC liimit 0,10;
到此一个sql注入语句就出现了,这样的sql在可视化界面里是可以执行通过的,那用户实际输入的内容是什么呢,如下:
%' AND 1=1 ;DELETE FROM rule WHERE 1=1 ;SELECT * FROM role r WHERE 1=1 AND '%'='
当这个构造好的sql到应用程序里面会发生什么呢?
当然在我的服务器里报错了,报错日志显示sql语法不对,从delete开始到后面的构造部分。原因就在于PreparedStatement在起作用,具体原理不再叙述。
到这里就结束了,我没有在前端发起的注入内容删除数据。
为啥用户会这么输入呢??
当然是有人恶意攻击咯,如果真猜出你的数据库表名并准备实施攻击的话,那是不是要过一遍自己写的代码或者检查一下有没有用PreparedStatement预编译呢?
或者这是你自己进行的测试,如果你想有PreparedStatement的话是不是就万事大吉了。
答案是否定的,黑客可不会这么low.他们想这么做的话一定有办法。
虽然你的系统在内网,你的应用访问量不多,等等,但是我们必须要知道这种威胁的存在,并且防患于未然。
那最好的方式是什么呢?
1.从产品层面来说要规避用户输入特殊字符(不要相信前端输入的数据),因为正常用户不会输入这么复杂的文本来测试你的程序,我们要做的就是正常请求,正常返回。
2.从技术上来说可以将输入的特殊字符转译。(这个工作可以在前端做,也可在后端)
3.从技术组件来说要从底层使用PreparedStatement进行预编译。