例:有一张学生成绩表(姓名,科目,成绩),需要能够根据姓名进行过滤。我们可以使用DataView的RowFilter实现这个功能:
String inputName=txtBoxName.Text;
RowFilter=String.Format("Name=’{0}‘”,inputName);
看似没问题的代码其实存在着隐患。当姓名中有单引号时,程序会出错。并且,如果我们使用类似Sql注入的方式构造一个特殊的字符,可以使得该过滤条件根本无效。假如程序中使用这样的方式进行信息隐藏,那么在过滤条件失效的情况下,客户就可以看到本不该他看到的东西。
解决的办法当然并不难,就是替换所有的单引号
String inputName=txtBoxName.Text.Replace("'","''");
顺便复习一下防止Sql注入的方法(摘自http://msdn.microsoft.com/zh-cn/magazine/cc163917(en-us).aspx 微软杂志2004.9)
Principle | Implementation |
---|---|
Never trust user input | Validate all textbox entries using validation controls, regular expressions, code, and so on |
Never use dynamic SQL | Use parameterized SQL or stored procedures |
Never connect to a database using an admin-level account | Use a limited access account to connect to the database |
Don't store secrets in plain text | Encrypt or hash passwords and other sensitive data; you should also encrypt connection strings |
Exceptions should divulge minimal information | Don't reveal too much information in error messages; use customErrors to display minimal information in the event of unhandled error; set debug to false |
1.对所有的输入进行验证,这必须根据输入内容进行验证。比如邮箱地址。另外就是长度的限制。
2.不要使用动态拼接SQL,而使用参数化的SQL跟存储过程。直接使用SQL语句与使用参数化的语句的区别:
使用SQL Profiler监测,我们可以发现,直接执行拼接后的SQL语句,比如“Select * From Table Where Name=’name‘”,SQL Server会直接执行该语句;而使用带参数的语句,SQL Server执行的是
exec sp_executesql N'SELECT * FROM Table WHERE Name=@name ',N'@name varchar(50)',@name='name'.假如输入的参数中带有单引号,会自动转成两个单引号。
3.不要使用管理员账号.
4.不要把敏感信息以原文形式存在数据库中。比如登陆账号,这里提到,使用hash值比加密更好。因为hash值是不可逆的,就算他拿到了密码的hash值,也没办法得到密码。
5.不要在页面中显示错误的详细信息,而使用统一的出错页面,禁止调试功能。