http://www.cnblogs.com/taizhouxiaoba/archive/2009/02/11/1388228.html
1. 什么是SQL注入
所谓SQL注入,就是通过把SQL命令插入到表单窗体递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行一些恶意的SQL命令。通过递交参数构造巧妙的SQL语句,从而成功获取想要的数据。
2. SQL注入的种类
从具体而言,SQL注入可分为五大类,分别是:数字型注入、字符型注入、搜索型注入(like)、in型的注入、句语连接型注入。
从应用来说,要特别注意IP、搜索、批量删除、从数据库转到数据库等地方的SQL注入。
3,如何进行的注入
下面我们看一个典型例子
1
SqlCommand cmd
=
new SqlCommand("
SELECT
*
FROM
PE_USERS
WHERE
UserName
=
'
"
2
+ UserName + "
'
AND
UserPassword
=
'
" + PassWord + "
'
", conn);
由于没有对UserName和PassWord进行任何验证,如果UserName=” admin’ OR 1=1--“
所执行的SQL语句就成了:
1
SELECT
*
FROM
PE_USERS
WHERE
UserName
=
’admin’
OR
1
=
1
—‘
AND
UserPassword
=
’’
2
这就造成了SQL注入,条件永远为真,也就不用密码也能登陆成功。
4.如何防止SQL注入
1.过滤或转换可疑字符串
通过编写过滤或者转换危险字符串的函数,然后在GLOBAL.ASAX或者重写上下文实例来实现防止SQL注入
这里有个例子
1
public
static bool SqlFilter2(string InText)
2
{
3
string word
=
"
and|
exec
|
insert
|
select
|
delete
|
update
|
chr
|
mid
|
master
|or|
truncate
|
char
|
declare
|join
";
4
if
(InText
==
null
)
5
return
false;
6
foreach(string i
in
word.Split(
'
|
'
))
7
{
8
if
((InText.ToLower().IndexOf(i
+
" ")
>-
1
)
||
(InText.ToLower().IndexOf(" "
+
i)
>-
1
))
9
{
10
return
true;
11
}
12
}
13
return
false;
14
}
二,Global.asax
1
protected void Application_BeginRequest(Object sender, EventArgs e)
2
{
3
//
遍历Post参数,隐藏域除外
4
foreach(string i
in
this.Request.Form)
5
{
6
if
(i
==
"__VIEWSTATE")
continue
;
7
this.goErr(this.Request.Form
[
i
]
.ToString());
8
}
9
//
遍历Get参数。
10
foreach(string i
in
this.Request.QueryString)
11
{
12
this.goErr(this.Request.QueryString
[
i
]
.ToString());
13
}
14
}
1
private void goErr(string tm)
2
{
3
if
(WLCW.Extend.CValidity.SqlFilter2(tm))
4
this.Response.
end
()
5
}
优点:该种方面是大多数初级程序员用来防止SQL注入,看起来效果还不错,能防止大多数情况下的注入。
缺点:1.会过滤一些本来不是用来进行注入的字符,造成意想不到的问题。比如,一个论坛的会员名字里如果含有和所过滤字符相同的字符的话,会造成一些列意想不到的问题和麻烦。
2.每次都需要进行过滤或者转换,降低程序效率
2.使用存储过程进行参数化查询
SQL注入主要目的是想通过提交恶意的SQL代码,来达到在数据库里执行恶意命令的目的。所以只要在执行SQL命令前做处理,就可以有效防止SQL注入。进行参数化查询可以达到有效防止SQL注入的目的。
实例
1
const string strSql
=
"
SELECT
*
FROM
[
PE_Users
]
WHERE
UserName
=
@UserName
";
2
Parameters parms
=
new Parameters("
@UserName
", DbType.String, userName);
上面有一个参数@UserName, 使用Prarmeter对象,通过它把参数添加到Command对象上,
这样就获得参数化查询。
如上述语句,ADO.NET 会向SQL Server 发送下面的SQL语句:
1
Exec
sp_executesql N ‘
select
*
from
[
pe_users
]
where
username
=
@username
‘,N
2
‘
@username
nvarchar
(
20
) ‘,
@username
=
N ‘name’
SQL Server 把@username 替换成字符串”name”,然后再执行查询.
假设有下面的输入:
1
'
union select @@version,null,null—
生成的SQL语句如下所示:
1
Exec
sp_executesql N ‘
select
*
from
[
pe_users
]
where
username
=
@username
‘,N
2
‘
@username
nvarchar
(
20
) ‘,
@username
=
N ‘’’
union
select
@@version
,
null
,
null
--
’
可以看到ADO.NET转义了输入。
1
public
SqlParameter Add(
string
parameterName, SqlDbType sqlDbType,
int
size);
DbTye或SqlDbType可以是多种数据类型。
可根据你的数据类型来选择。
在某些地方,也可似指定参数的长度:int size。这样也能有效防止数据库溢出和SQL注
入的可能性。
优点:有效地防止了SQL注入的产生。
缺点:有些地方不能应用,如 in 。
3.白名单
描述:
对于一些已知的参数范围,可用白名单的形式处理,能有交防止SQL注入和查询出
错,如:order by +列名,列名以参数形式传入时,可制定一个白名单,先判断一下参
数是否在白名单内,再进行查询,否则出错处理。
优点:安全可靠
缺点:应用范围小