通用防Sql注入 -- 不可能!
Sql注入是咋回事,在这没必要再啰嗦了。
为什么说通用防注入不可能,通用防注入,一般都是改写/限制/过滤危险关键字的思路实现的,
如果需求里,允许使用这些所谓的危险关键字怎么办?
像博客园/csdn/这类技术社区,发的内容里“危险关键字”有得是!
a) 改写/过滤:就是对内容的破坏,行不通
b) 限制:正常的一句话,不能不让人家说吧?
Sql语句中,不同的数据类型,写法是不一样的
a) 数值:a=1
b) 字符:a='1'
c) 日期:datediff(d,xx,'2009-6-6')
d) insert into (f_int,f_str,f_date) values(100,'100','2006-9-5')
e) select * from xxx where a=5 and b='100' and c like '%123456%' and datediff(d,d,'2006-5-9')>0
所以注入方式也不一样,a)字符和日期型都需要用单引导号括一下,b)数值则不用引
所以,防注入需要针对这两种情况进行。
1) 数值型防注入:
简单极了,判断一下接到的参数能不能直接的转为数值就OK了
2) 字符型防注入:
只需要将接到的参数中的单引号,替换为两个单引号即可(Sql中的转义字符)就OK了
有些朋友刚开始认为这样做不够严谨,这里我详细说一下:
以一个查询语句为例(ASP/服务端javascript,语法上能和C#接近些)
var Para=Request.Querystring('SearchKey');
var Sql='select * from Article where Title like \'%'+Para+'%\'';
Response.Write(Sql); //假设Para=abc ,则输出:select * from Article where Title like '%a%'
/*
字符串注入时,需要Para里包含单引号,与程序中的Sql语句拼接后,形成闭合,从而使参数中的字串成为真正的Sql语句
例,Para=' union all select Username from Admin and UserName like '
则输出:select title from Article where Title like '%' union all select Username from Admin and UserName like '%'
在真正执行的,时候,就麻烦了
*/
Sql=Sql.replace(/'/ig,'\'\''); //只将单引号替换为两个单引即可
Response.Write(Sql);
//此时输出:select title from Article where Title like '%'' union all select Username from Admin and UserName like ''%'
//如有怀疑的话,可以贴到查询分析器里试试,不好使不要钱
conn.execute(Sql); //再运行就没问题了!!
var Sql='select * from Article where Title like \'%'+Para+'%\'';
Response.Write(Sql); //假设Para=abc ,则输出:select * from Article where Title like '%a%'
/*
字符串注入时,需要Para里包含单引号,与程序中的Sql语句拼接后,形成闭合,从而使参数中的字串成为真正的Sql语句
例,Para=' union all select Username from Admin and UserName like '
则输出:select title from Article where Title like '%' union all select Username from Admin and UserName like '%'
在真正执行的,时候,就麻烦了
*/
Sql=Sql.replace(/'/ig,'\'\''); //只将单引号替换为两个单引即可
Response.Write(Sql);
//此时输出:select title from Article where Title like '%'' union all select Username from Admin and UserName like ''%'
//如有怀疑的话,可以贴到查询分析器里试试,不好使不要钱
conn.execute(Sql); //再运行就没问题了!!
对于通用防注入程序,它是无法知道程序里的Sql语句中的参数是数值还是字符的。
所以,通用防注入程序,不可能!
补一句,其实通用防注入不是完全不可能,但实现需求不完美,有弊端,某些需要实现不了
必杀:使用参数化SQL (不过我感觉这种方式写起来有点麻烦,还是依需求和个人喜好使用吧)
拼Sql语句,有朋友说用什么编码可以绕过去,我也没闹太明白,有高人可以指点指点!