最近在编程中遇到一个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