Web站点的SQL注入与防御总结
最近,我们的网站出现了SQL注入的问题,或许是网站关注的人多了,还是有人在捣乱,总归数据库被注入恶意代码,让人一时间不知如何是好,从网上搜索SQL 注入,那个数据可叫多呀,耐着性子阅读(不读也没办法),但是大部分是过滤恶意字符串的方法,方法如下:
一、过滤恶意字符串
string XH_In, XH_In2;
//自定义需要过滤的字串,用 "|" 分隔
XH_In = "'|;|and|exec|insert|select|delete%20from|update|count|*|%|chr|mid|master|truncate|char|declare|drop%20table|from|net%20user|xp_cmdshell|/add|net%20localgroup%20administrators|Asc|char";
XH_In2 = "'|;|and|exec|insert|select|delete%20from|update|count|chr|mid|master|truncate|char|declare|drop%20table|from|net%20user|xp_cmdshell|/add|net%20localgroup%20administrators|Asc|char";
string[] SqlInject = XH_In.Split('|');
string[] SqlInject2 = XH_In2.Split('|');
//--------POST部份------------------
if (!Request.Form.Equals(""))
{
foreach (string XH_Post in Request.Form)
{
for (int j = 0; j < SqlInject.GetLength(0); j++)
{
if (Request.Form[XH_Post].ToLower().IndexOf(SqlInject[j]) != -1)
{
Response.Write("操作IP:"+Request.ServerVariables["REMOTE_ADDR"]);
Response.Write("操作页面:"+Request.ServerVariables["URL"]);
Response.Write("提交方式:"+"POST");
Response.Write("提交参数:"+XH_Post);
Response.Write("提交数据:"+Request.Form[XH_Post]);
}
}
}
}
//--------GET部份------------------
if (!Request.QueryString.Equals(""))
{
foreach (string XH_Get in Request.QueryString)
{
for (int j = 0; j < SqlInject.GetLength(0); j++)
{
if (Request.QueryString[XH_Get].ToLower().IndexOf(SqlInject[j]) != -1)
{
Response.Write("操作IP:"+Request.ServerVariables["REMOTE_ADDR"]);
Response.Write("操作页面:"+Request.ServerVariables["URL"]);
Response.Write("提交方式:"+"GET");
Response.Write("提交参数:"+XH_Get);
Response.Write("提交数据:"+Request.Form[XH_Get]);
}
}
}
}
//--------COOKIE部份------------------
if (!Request.Cookies.Equals(""))
{
foreach (string XH_Cookie in Request.Cookies)
{
for (int j = 0; j < SqlInject2.GetLength(0); j++)
{
if (Request.Cookies[XH_Cookie].ToString().ToLower().IndexOf(SqlInject2[j]) != -1)
{
Response.Write("操作IP:"+Request.ServerVariables["REMOTE_ADDR"]);
Response.Write("操作页面:"+Request.ServerVariables["URL"]);
Response.Write("提交方式:"+"Cookie");
Response.Write("提交参数:"+XH_Cookie);
Response.Write("提交数据:"+Request.Form[XH_Cookie]);
}
}
}
}
这种方法,有一定的可行性,但是不能每一个页面都加呀,这会儿就只能写到HttpModule模块中了,将上的代码做一定的变化,写入到自定义的一个模块中,然而,这样做之后,又出来一个问题,就是我们发布的正常信息,由于包含了这样的关键字,而无法正常添加,这也是一个很难受的问题,那怎么办呢,最后,我发现不能偷懒,写SQL语句时,每个语句都进行相应的检查,确实很困难,这时,我建议,尽量采用Parameter参数化的SQL命令来执行了,这种办法可以彻底杜绝SQL 注入,代码样例如下:
添加数据:
public bool Add(ECorpSite.Model.SiteNewsCls model)
{
StringBuilder strSql=new StringBuilder();
strSql.Append("insert into SiteNewsCls(");
strSql.Append("infoClsID,clsName,parentID,childCount,depth,userClsID,isHasPic,picSize)");
strSql.Append(" values (");
strSql.Append("@infoClsID,@clsName,@parentID,@childCount,@depth,@userClsID,@isHasPic,@picSize)");
OleDbParameter[] parameters = {
new OleDbParameter("@infoClsID", OleDbType.VarChar,12),
new OleDbParameter("@clsName", OleDbType.VarChar,30),
new OleDbParameter("@parentID", OleDbType.VarChar,12),
new OleDbParameter("@childCount", OleDbType.Integer,4),
new OleDbParameter("@depth", OleDbType.Integer,4),
parameters[0].Value = model.infoClsID;
parameters[1].Value = model.clsName;
parameters[2].Value = model.parentID;
parameters[3].Value = model.childCount;
parameters[4].Value = model.depth;
DbHelperOleDb.ExecuteSql(strSql.ToString(), parameters);
strSql.Remove(0, strSql.Length);
strSql.Append("update SiteNewsCls set ");
strSql.Append("childCount=childCount+1");
strSql.Append(" where infoClsID='" + model.parentID + "'");
return DbHelperOleDb.ExecuteSql(strSql.ToString()) > 0;
}
删除数据:
/// <summary>
/// 删除一条数据
/// </summary>
public bool Delete(string infoClsID)
{
bool rtnValue = false;
StringBuilder strSql=new StringBuilder();
strSql.Append("select infoClsID from SiteNewsCls where parentID=@infoClsID");
OleDbParameter[] parameters = {
new OleDbParameter("@infoClsID", OleDbType.VarChar,50)};
parameters[0].Value = infoClsID;
return DbHelperOleDb.ExecuteSql(strSql.ToString(), parameters)>0;
}
上面两个为参考代码,其它代码类同,这种方法比较好,初一看,好像写起来很费事,但是,在实际应用中,却可以提高速度与降低出错率,当然更可防止SQL注入,写出来供大家参考,有不同意见的回帖讨论。
对于我们的数据库被注入问题,主要也是由于早期写的代码没有使用参数化的SQL语句造成的,还望新手引以为鉴。