防sql注入解决方法

SQL查询中的特殊字符处理 


我们都知道SQL查询过程中,单引号“'”是特殊字符,所以在查询的时候要转换成双单引号“''”。
但这只是特殊字符的一个,在实际项目中,发现对于like操作还有以下特殊字符:下划线“_”,百分号“%”,方括号“[]”以及尖号“^”。
其用途如下:
下划线:用于代替一个任意字符(相当于正则表达式中的 ? )
百分号:用于代替任意数目的任意字符(相当于正则表达式中的 * )
方括号:用于转义(事实上只有左方括号用于转义,右方括号使用最近优先原则匹配最近的左方括号)
尖号:用于排除一些字符进行匹配(这个与正则表达式中的一样)
以下是一些匹配的举例,需要说明的是,只有like操作才有这些特殊字符,=操作是没有的。
a_b...        a[_]b%
a%b...       a[%]b%
a[b...       a[[]b%
a]b...       a]b%
a[]b...      a[[]]b%
a[^]b...     a[[][^]]b%
a[^^]b...    a[[][^][^]]b%
 
在实际进行处理的时候,对于=操作,我们一般只需要如此替换:
' -> ''
对于like操作,需要进行以下替换(注意顺序也很重要)
[ -> [[]     (这个必须是第一个替换的!!)
% -> [%]    (这里%是指希望匹配的字符本身包括的%而不是专门用于匹配的通配符)
_ -> [_]
^ -> [^] 


一定要对用户可能输入的诸如引号,尖括号等特殊字符给予足够重视,它们可能引发严重的安全问题。SQL注入的基本手法之一,就是利用对单引号未加过滤的安全漏洞。 

用户的输入无非两个用途:对数据库操作或显示在页面上,下面分别对这两种情况下特殊字符的处理加以说明。 

1. 对数据库操作 
用户输入的数据用于对数据库进行操作时,又分为两种情况,一是进行写库操作,二是作为查询条件。 

1.1 写库操作 
(insert及update都视为写库操作,这果以insert为例说明,update的处理相同) 
一般采用insert语句或AddNew方法两种方式进行写库操作,我们先来看insert语句: 

DIM username,sqlstr 
username = trim(Request.Form("uname")) 
sqlstr = "insert into [userinfo] (username) values ('"& username &"')" 

以SQL Server为例,使用这种方式写库,如果username中含用单引号('),会出错。使用下面的自定义函数,可以将单引号进行转换: 

Rem 转换SQL非法字符 
function SQLEncode(fString) 
if isnull(fString) then 
SQLEncode = "" 

exit function 
end if 
SQLEncode=replace(fString,"'","''") 
end function 

以上函数将一个单引号转换为两个连续的单引号,数据库能够接受,并以一个单引号写入。SQL语句改为: 

sqlstr = "insert into [userinfo] (username) values ('"& SQLEncode(username) &"')" 

再来看AddNew方法: 

DIM username 
username = trim(Request.Form("uname")) 
'MyRst为Recordset对象,MyConn为Connection对象 
MyRst.open "[userinfo]",MyConn,0,3 
MyRst.AddNew 
MyRst("username").Value = username 
MyRst.Update 
MyRst.Close 

使用这种方式写库时,不必调用SQLEncode()对单引号进行转换,数据库会自行处理。 

对于存储过程的的参数,同样不必进行单引号的转换。 

建议大家利用存储过程进行操作,好处嘛,我在《ASP与存储过程》一文中已做了阐述。否则,建议使用AddNew方法写库,好处不仅仅在于避免对单引号进行处理,本文对此不作深入探讨。 

1.2 用户输入做为查询条件 
网页教学网 


如果用户输入的数据作为查询条件出现在where子句中,不论该where子句属于update语句、delete语句还是select语句,都要对单引号进行转换。 

2. 用户输入的数据作为输出,显示在页面上 
我们这里只讨论不允许用户使用HTML代码的情况,也就是说,即使用户输入了HTML代码,这些数据也不会以HTML代码的形式显示。至于允许用户使用HTML代码的情况,比较复杂,以后专文探讨。 

用户输入的数据是绝对不可以不加处理,原样显示的。如果其中包含HTML或js代码,使你的页面混乱不堪倒是小事,甚至可以格掉你的硬盘。 

输出显示在页面上的数据,有可能是用户的直接输入,或是取自数据库。可以看到以上在入库时的处理只是转换了单引号,对尖括号,双引号等特殊字符并未处理,我们放在输出的时候再进行处理。 

ASP中的server.HTMLEncode()方法可以将许多字符转换为“HTML字符”,如将<转换为<,将>转换为>等等。 

在数据显示在页面上之前,可以用server.HTMLEncode()对其进行转换。但是该方法不会对回车,空格进行转换,这样就造成以下问题:如果用户是通过textarea控件输入的数据,输出时将不会保留原有格式,不仅没有回车换行,多个空格也只会显示为一个。为了解决这个问题,我们使用以下自定义函数: 

Rem 转换HTML非法字符,用于输出显示时 
function HTMLEncode(fString) 
if not isnull(fString) then 
fString = Replace(fString, ">", ">") 
fString = Replace(fString, "<", "<") 
fString = Replace(fString, CHR(34), """) '双引号 
fString = Replace(fString, CHR(39), "'") '单引号 
fString = Replace(fString, CHR(32)&CHR(32), " ") '空格 
fString = Replace(fString, CHR(9), " ") 'tab键值 
fString = Replace(fString, CHR(10), "<br>") '换行 
fString = Replace(fString, CHR(13), "") '回车 
HTMLEncode = fString 
end if 
end function 

调用以上函数,输出通过textarea控件输入的数据,会得到满意的结果。 

如果数据输出在表单控件中,不论是何种控件,都可利用server.HTMLEncode()方法转换字符,即使是对于textarea控件,也不会产生问题。虽然回车空格没有被转换,但在该控件中可以被识别。但是,server.HTMLEncode()方法不转换单引号。所以,控件的值一定要使用双引号: Webjx.Com 

<input type=text name=uname value=""" & server.HTMLEncode(username) & """> 

否则,如果用户输入的是 '' οnclick=javascript:.... ,以上代码将显示为: 

<input type=text name=uname value='' οnclick=javascript:...> 

而javascript命令可以做的事情实在是太多了。 

以上,通过用户输入数据的两种用途,对特殊字符的处理做了大概的说明。还有一种情况:用户的输入作为GET请求的参数值。比如通过以下URL向服务器发送请求:test.asp?username=MyName 

我一般只把数值型的数据做此类提交,并在接收时对数据类型做验证。若是字符型的数据,如何处理特殊字符呢?有兴趣的朋友思考一下吧,呵呵。 

有些朋友喜欢用JAVAScript过滤特殊字符,而且限制输入的字符很多。我不建议这么做,一是JAVAScript是客户端运行的,不可靠。要知道,对服务器的请求是可以伪造的,伪造者可不会加上你的JAVAScript代码;二是JAVAScript不太友好;三者,实际上没有必要限制那么多字符,限制太多,用户会害怕的。 

总结一下我对特殊字符处理的经验吧: 


1. 对接收到的数据类型进行验证; 
2. 尽量通过存储过程对数据库进行操作; 
3. 如上一点不可行,尽量使用AddNew方法写库; 
4. 对作为查询条件的数据,使用自定义函数SQLEncode()转换单引号; 
5. 表单控件的值,一定要用双引号引起来; 
6. 在表单控件中显示数据时,使用server.HTMLEncode()方法转换字符; 
7. 对于通过textarea提交的数据,使用自定义函HTMLEncode()转换字符并保持格式; 
8. 尽量避免使用Request()接收数据,应使用Request.Form()或Request.QueryString(); 
9. 尽量避免通过URL传递字符参数(只用此方式传递数值参数) 


************************************************************ 
SQL查询中的特殊字符处理 

我们都知道SQL查询过程中,单引号“'”是特殊字符,所以在查询的时候要转换成双单引号“''”。 

但这只是特殊字符的一个,在实际项目中,发现对于like操作还有以下特殊字符:下划线“_”,百分号“%”,方括号“[]”以及尖号“^”。 

其用途如下: 

下划线:用于代替一个任意字符(相当于正则表达式中的 ? ) 

百分号:用于代替任意数目的任意字符(相当于正则表达式中的 * ) 

方括号:用于转义(事实上只有左方括号用于转义,右方括号使用最近优先原则匹配最近的左方括号) 

尖号:用于排除一些字符进行匹配(这个与正则表达式中的一样) 

以下是一些匹配的举例,需要说明的是,只有like操作才有这些特殊字符,=操作是没有的。 

a_b...        a[_]b% 



a%b...       a[%]b% 



a[b...       a[[]b% 



a]b...       a]b% 



a[]b...      a[[]]b% 



a[^]b...     a[[][^]]b% 



a[^^]b...    a[[][^][^]]b% 



在实际进行处理的时候,对于=操作,我们一般只需要如此替换: 

' -> '' 

对于like操作,需要进行以下替换(注意顺序也很重要)



[ -> [[]     (这个必须是第一个替换的!!) 



% -> [%]    (这里%是指希望匹配的字符本身包括的%而不是专门用于匹配的通配符) 



_ -> [_] 



^ -> [^]

注意:

在Oracle9i中,经过实际测试发现,需要处理的特殊字符有:

_(下划线)

%(百分号)

‘(单引号)

&(这个在Oracle中与后面的字符组成变量)

上面其他字符不需要处理。

对于前三种,需要使用ESCAPE进行转义,对于’&‘符号比较特殊,需要将’xxx&xxx'转化为'xxx&' || 'xxx'的形式,或者用chr(38)表示’&‘

转义符最好使用‘、‘(反斜线)。

使用’@‘,在全角字符过长时会发生错误,原因目前不明。

数据库sql的特殊字符:

1)单引号’:例如string a = “this is marry’s book.”;

             使用insert时就会出错。

             解决:a= a.Replace("'","''");

2)百分号% :例如string a = “50%”;

             使用like查询,查出带有50%的所有记录,则会被认为是通配符。

             解决:Select * FROM tbl where name LIKE '%/%%' ESCAPE '/' 

即a=a.Replace("%","/%%")

或者[%]

3)下划线_ :例如 string a = “m_n”;

              使用like查询,select * from tbl where name like ‘%m_n%’,下划线被认为是通配符。

              解决:[_]


4)方括号[]:主要是左括号:[[]

5)尖括号^:[^]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值