你的位置:首页 > ASP.net教程

[ASP.net教程]初识Sql注入漏洞攻击


 以前就听说过Sql注入漏洞攻击,但一直没有对它进行细致的研究,所以了解甚少。最近我们学ADO.NET的时候,里面主要部分就是用带参数或不带参数的Sql语句对数据库进行操作,我忽然意识到了一个严重的问题,那就是Sql注入漏洞攻击。因为我们老师并没有提到这个编程领域中常见的问题,所以我通过各种渠道研究Sql注入漏洞攻击,现向朋友们分享一下我对Sql注入漏洞攻击的一点了解。注:以下所谈只涉及ADO.NET中的SQL注入漏洞攻击方式的其中一种。
    简单地说,Sql注入就是将Sql代码传递到应用程序的过程,但不是按照应用程序开发人员预定或期望的方式插入,相当大一部分程序员在编写代码的时候,并没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患。这种漏洞并非系统照成,而是由程序员在编程中忽略了安全因素。Sql注入漏洞攻击原理就是利用非法参数获得敏感信息,收集整理,分析出管理员账号密码。
    我们在学习ADO.NET的时候,每一次必不可少的会写对数据库操作的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注入漏洞攻击。
    好啦,今晚就谈这么多,其实我也就知道这么多,嘿嘿,逃课写了这篇日志,有点对不起老师啊!嘿嘿......