最近在编程中遇到一个SQL注入防护的问题。在这里顺便把SQL注入小结一下。以MYSQL(5.1)为例。
观察SQL语句
SELECT * FROM [tableName] WHERE col1='value1'这个语句由3个部分组成,SELECT子句筛选得到结果,FROM子句指定了筛选的范围,WHERE子句指定了条件。当在其中进行如下置换:
SELECT * FROM [tableName] WHERE 1之后,选出了[tableName]表中的全部内容。分析其语法不难发现,WHERE将其后的真值表达式求值,然后作为筛选的条件。
SELECT * FROM [tableName] WHERE false or 1=‘1’ and '1'='1' and "1"="1"同样得到了[tableName]表种的全部内容。
SELECT * + FROM [tableName] + WHERE col1=' + value1 + '其中的value1常常是由输入所得。然而当WHERE子句具备(二)中的某种特征时就可能存在意外了。如果只是按照拼接來构建WHERE子句的话,那么WHERE子句可能会演化成这样的形式:
SELECT * FROM [tableName] WHERE col1='badvalue' or 1='1'也就是说,用户熟悉SQL语句并精心构造了一个包含SQL特殊字符的输入{badvalue‘ or 1=‘1},这时候会返回整张表。
SELECT * FROM [tableName] WHERE col1="badvalue" or 1="1"中的{badvalue" or 1="1}。
SELECT * FROM [tableName] WHERE col1='badvalue' ; select * from [another] where 1='1'也就是说,填入{badvalue‘ ; select * from [another] where 1=‘1}。完全可以把填入括号中的select换成drop、update等等。起作用的前提是程序员不作任何处理地将用户输入接入了SQL查询语句中。
/** * affirmNodePair 示例: * {"or col1=","value1"} * {"and col2>","value2"} * * / public string Where (Dictionary<string,string> affirmNodePair) { StringBuilder builder=new StringBuilder(); // 预处理 builder.Append(" where 1 "); foreach (var item in affirmNodePair) { builder.Append(item.Key); builder.Append("'"); //过滤用户输入:将用户输入的特殊字符转义 foreach (var c in item.Value) { switch (c) { case '\'': builder.Append(@"\"); break; case '\"': builder.Append(@"\"); break; case ';': builder.Append(@"\"); break; default: break; } builder.Append(c); } builder.Append("'"); builder.Append(" "); } return builder.ToString(); }
Where 1 or col1='value1' and col2>'value2'当填入{badvalue‘ or 1=‘1}后得到转义后的结果
Where 1 or col1='badvalue\' or 1=\'1'在我测试使用的MYSQL(5.1)中能够符合预期地报错。具体的部署要结合实际情况,限于工作条件,这里只提供了一个基础性思路。谢谢大家耐心看完。
原文地址:http://blog.csdn.net/u010289866/article/details/43027105