sql注入是一个古老的话题了,但经常会被我们忽略。尤其是使用了ibatis.net之后。
Ibatis.net框架对sql注入问题已经做了很好的防护,但经常由于开发人员使用不当,会造成sql的注入隐患。在模糊查询中,经常会忽略这一问题。如下面的这个例子:
我们有一张UserInfo表,字段Name表示用户姓名,需要按用户名进行模糊查询,于是乎sqlmap写法如下:
select * from UserInfo where Name like '%$Name$%'
$Name$是有用户界面传入的,这样sql注入就成立了,用户输入 %' or 1=1 or name like '%,执行语句变成了这样:
select * from UserInfo where Name like '%%' or 1=1 or name like '%%',查询了所有的用户。
如果用户输入 ';delete from pt_userinfo where personid like ',执行语句变成这样:
select * from UserInfo where Name like '%';delete from UserInfo where personid like '%',这将是灾难性的后果。
解决方案,在模糊查询的地方,不要使用$$,而是要使用##,sqlmap的正确写法:
select * from UserInfo where Name like '%'+ #Name# + '%'
这样,当用户试图进行sql注入时,ibatis.net将进行防注入检查,如果检测到sql注入,将返回结果一个空集。
后续思考:ibatis.net中$$和##的区别
在ibatis.net中,$$只是简单的字符串拼接,ibatis.net不做任何处理,对于##,ibatis.net会采用参数化命令方式进行处理,有效防止sql注入。但为什么ibatis.net不将$$去掉,$$是有自己的特殊场景的,如果需要查询前十条记录,sqlmap写法如下:
select top $limit$ * from UserInfo,由于$$只是简单拼接,limit=10,执行语句为:select top 10 * from UserInfo;
如果sqlmap写为:
select top #limit# * from UserInfo,limit=10,执行语句为:select top '10' * from UserInfo;显然执行会报错的,达不到预期效果。