预防查询语句数据库注入漏洞攻击
简单地说,Sql注入就是将Sql代码传递到应用程序的过程,但不是按照应用程序开发人员预定或期望的方式插入,相当大一部分程序员在编写代码的时候,并没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患。这种漏洞并非系统照成,而是由程序员在编程中忽略了安全因素。Sql注入漏洞攻击原理就是利用非法参数获得敏感信息,收集整理,分析出管理员账号密码。
当开发应用程序时,尤其是有关数据库信息的查询,查询语句中可能会有拼接字符串注入漏洞,这便会导致用户资料泄露。那么该如何防范此类漏洞的出现。
可以为查询语句设置参数,方法实例如下面所示:
Using(Sqlconnection cn = new sqlconnection(“连接字符串”))
{
cn.open();
using(sqlcommand cmd = cn.creatcommand())
{
cmd.commandtext=”select * from T_table where name=’”+textbox.text+”’”;
(此时如果在文本框中输入1’ or ‘1’=’1)就可以获取数据库信息。会造成信息的泄露。解决办法就是引入参数。方法如下。
cmd.commandtext=”select * from T_table where name=@Name”;
cmd.Parameters.Add (new sqlParameter ("@Name", textbox.text))};
这样查询数据就会从数据库查询比对,不会再出现注入漏洞攻击的情况。
}
}
每一次必不可少的会写对数据库操作的Sql语句,例如以下验证登陆的Sql语句:
string strSql="select * from Table Where UserName='"+textBoxUserName.Text+'"and UserPassord='"+textBoxPassword.Text+"'";
或者
string strSql=string.Format("select * from Table where UserName='{0}' and UserPassword='{1}'",textBoxUserName.Text,textBoxPassword.Text);
在上面的语句中,对数据库操作的Sql语句使用字符串拼接的方式写的,这种方式是前期的程序员以及初学者通用的对数据库操作的一种Sql语句写法,上述代码中的textBoxUserName是用户在textBoxUserName文本框中提交的用户名,textUserpassword是用户在textUserpassword文本框中提交的密码,在理想的状态下,用户 为了对系统进行攻击,用户(就是黑客)可能尝试篡改Sql语句,达到登录的目的。例如用户可能在用户名文本框中输入下面的语句:
1' or 1=1 --
下面我们把上面一行的语句代入到前面用于登录的Sql语句中,得到下面的Sql语句:
select * from Table where UserId='1' or 1=1 --'and UserName=' '
稍微学过数据库Sql语句的,很快就会发现上面一句话的不正常,这条Sql语句会返回Table表的全部数据,这就是黑客有机可乘的地方,黑客可以用这种方法成功登陆,还可以获取该Table表的所有信息。下面解释一下这句Sql语句:如果只有select * from Table,就会返回该Table表的所有信息,where后是查询条件,1=1永远为True,不管User='1'为True还是为False,UserId='1' or 1=1 都为True。至于--'and UserName=' ' ,因为两个连字符(--)是MS Sql Server的注释标记(My Sql和Oracle数据库也使用相同的技术,不过My Sql使用的注释标记师是符号#,Oracle使用的是分号;),--后面的内容传到数据库查询时都被注释了,那么--后面的内容就没用了,Sql语句不会执行了,所以where后的查询条件永远为True,综上所述,上面的Sql查询语句会返回Table表的所有信息!
通过这种Sql语法漏洞,黑客们可以达到他们的目的,但Sql注入漏洞攻击绝对不止这一种,复杂的还有很多,我不在说了。下面我谈一下我知道在.NET中应对上面这种Sql注入攻击的防范措施。
我们所能做的,如果不修改上面的Sql查询语句,那一种方法就是利用TextBox控件的MaxLength属性,这样就键入了黑客键入字符的数量,从而可以限制黑客向服务器发送大量的非法命令,但这种方法只是掩耳盗铃,治不了根本。第二种方法就是删除用户输入中的单引号,方法是在单引号后面加一个或多个单引号,或者利用空格替换单引号,这样就可以预防此类攻击。但局限性是如果用户的用户名或密码中就含有单引号呢,那就不可行了!
最完美的一种方法就是使用ADO.NET Command对象的参数集合,在前面的可以进行Sql注入漏洞攻击的Sql语句中,通过使用字符串拼接方法动态创建查询,在这里我们可以利用ADO.NET Command的对象的Parameters属性提供的功能,传递执行Sql语句所使用的参数,在这种方法中参数名必须以字符@为前缀,例如以下Sql查询语句:
string strSql="select * from Table where UserName=@UserName and UserPassword=@UserPassword";
在该语句中,@UserName和@UserPassword就是参数名,可以使用以下语句为该参数传值:
SqlCommand cmd=new SqlCommand(strSql,conn);
SqlParameters[] pams=new SqlParameters(new SqlParameters("@UserName",textBoxUserName.Text),new SqlParameters("@UserPassword",textBoxPassword.Text));
cmd.Parameters.AddRange(pams);
参数名不区分大小写,这种方法也适宜存储过程和SqlDataAdapter对象。
我们在动态创建Sql语句中使用了@UserName和@UserPassword名称,而不是拼接多个字符串,这样就可以使用SqlCommand对象的Parameters集合传递值,该方法可以安全的创建动态Sql连接。参数在Sql Server内部不是简单的字符串替换,Sql Server直接0用添加的值进行数据比较,因此不会有Sql注入漏洞攻击。