在通过联结数据库来确认用户名与密码问题的过程中如果我们这样写:
commandText="select * from T_Test where name='" + textBox_userName.Text + "' "+"and password='"+textBox_password.Text+"'";//
就给黑客可乘这机,你看他如果把密码写成:
' or '' = '
' or 1=1;--
1 or 1=1
" or ""="
这几种中的一种,你会奇怪的发现能任何可用用户名都能登录成功,
不要惊讶,这是事实。
实际开发中千成不要这样写!!!,这就是遗臭万年的SQL注入漏洞。
我们来分析一下,假设你的用户名为Admin,以' or 1=1;--为密码,代入其中,你看它的完整语句就成了这样:
select * from T_Test where name=’Admin’ and password=’ or 1=1;--
分析一下password那里,你看它,先给你整个小单引号,把你写那个单引号给匹配了,//悲剧的是英文状态下引号是不分左右的,中文的引号是通不过,
然后它又给你整了个or,这个是或的意思,明白吧,只要两个表达式其中一个为真,那么整个表达式就为真。
再看1=1,这个不用多说,1=1就是true,就是真
再看;,这个是SQL语句结束的意思,
最后这个--,表注释
真是太妙了!
你不是在程序里写了一个单引号吗?那么我就给你加个单引号把你前面那个先搞掉,后面那个单引我就用--给你注释掉,//系统是不理会注释语句的,
然后中间是一个真表达式,现在是不管你前面真不真反正我这儿是真,所以整个表达式就为真。
那我们就没有办法了吗?
解决方法肯定是有的,下面看我如何用参数化查询防止此类SQL注入攻击的:
我先把查询语句这样写:假设得到的SQLCommand引用为:sqlCmd
sqlCmd.commandText="select * from T_Test where name=@userName and password=@userPassword;
sqlCmd.Parameters.Add(new SqlParameter("userName",textBox_userName.Text));
sqlCmd.Parameters.Add(new SqlParameter("userPassword",textBox_userPassword.Text));
//注意这里的userName和userPassword可以随意写,只是前面那个”@”一定不要忘
这下不管你黑客再用前面列出的所谓“万能密码”就不管用了。
通过参数化查询系统不会把用户输入的东西简单的拼接到你的查询语句里面,你可以理解成它直接就把你输入的东西拿到数据库中比,你输入的这些玩意肯定没有匹配的,所以
万能密码就不管用了”