sql注入例子,假设DB中存在如下数据:
+----+---------+----------+
| id | uid | password |
+----+---------+----------+
| 1 | forrest | abc |
| 3 | denny | abc |
| 5 | peggy | abc |
| 6 | vivian | abc |
+----+---------+----------+
正常Query语句:SELECT * FROM user WHERE uid='vivian' AND password='abc';
用户名框注入:'123' OR '1'='1',密码框输入:'abc' --> sql语句变为:SELECT * FROM user WHERE (uid='123' OR '1'='1') AND (password='abc');
可查询到所有密码为abc的用户,并登陆成功。
密码框注入:'123' OR '1'='1',用户名框输入:'vivian' --> sql语句变为:SELECT * FROM user WHERE (uid='vivian' AND password='123') OR ('1'='1');
可查询到所有用户,并登陆成功。
用户名框注入:'123' OR '1'='1',密码框注入:'123' OR '1'='1' --> sql语句变为:SELECT * FROM user WHERE [(uid='123' OR '1'='1') AND password='123'] OR '1'='1';
可查询到所有用户,并登陆成功(可以看出结果和只在密码框中注入sql的结果是一样的)。
上面中的()[]是为了给sql断句,以便理解(这样就应该很好理解了吧,一个很简单的逻辑哦,我就不解释了)。实际应用中并无此类括号。
ps:如果知道了DB中某Table的tablename。则可以对其进行破坏,eg密码框注入:'123'; drop table tb_name; --> 真的很发指啊!!!
1、PreparedStatement
可对sql预编译. 你传入的任何内容就不会和原来的语句发生任何匹配的关系(前提是数据库本身支持预编译,但目前流行数据库都支持预编译了)
2、表单验证(正则表达式)对数据进行过滤(屏蔽掉注入关键词)
3、正则表达式检测已经形成的sql语句(在sql被execute前进行)
2.1、检测SQL meta-characters的正则表达式 /(\%27)|(\')|(\-\-)|(\%23)|(#)/ix
2.2、修正检测SQL meta-characters的正则表达式 /((\%3D)|(=))[^\n]*((\%27)|(\')|(\-\-)|(\%3B)|(:))/i
2.3、典型的SQL注入攻击的正则表达式 /\w*((\%27)|(\'))((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix
2.4、检测SQL注入,UNION查询关键字的正则表达式 /((\%27)|(\'))union/ix(\%27)|(\') - 单引号和它的hex等值union - union关键字。
2.5、检测MS SQL Server SQL注入攻击的正则表达式 /exec(\s|\+)+(s|x)p\w+/ix
4、Filter过滤
public static String filterContent(String content){
String flt ="'|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";
String filter[] = flt.split("|");
for(int i=0;i<filter.length ; i++){
content.replace(filter, "");
}
return content;
}
5、 避免动态SQL
动态SQL是动态查询的很好的工具,但这也会暴露脆弱点。很多情况下可以使用其他SQL语句或存储过程来代替动态SQL。当然,如果您在存储过程中依然通过用户输入来建立动态SQL查询,那么只靠替换还是不安全的。
6、最低权限原则
永远也不要在代码中用管理员级别权限的帐户来连接数据库。应用程序使用的帐户应该只拥有应用程序需要的最低级别的权限。这也能将已入侵者造成的破坏降低到最低限度。应用程序不能已sa或其他管理员帐号连接数据库,而且应定义使用的帐号能访问的范围。
7. 安全存储机密信息
不要用明文存储机密信息。较好的替代方法是使用加密或散列密码。散列密码较加密密码更安全,这是因为它们不能被解密。你还可以在散列加密之前添加一些随机值来增加安全性。
8. 只有知道如何注入,才能更有效的防注。一个例子
正常地址:
http://www.xxx.com/news.asp?id=1
加个',如果没过滤特殊字符,网页一定出错,就是看怎么出错法。画面能显示一部分,一部分提示数据库出错,找不到什么什么,最有希望注入。
http://www.xxx.com/news.asp?id=1'
下一步,试试 and 1=1 ,如果画面不出错,1=1是成立的,有希望了。
http://www.xxx.com/news.asp?id=1 and 1=1
下一步,试试 and 1=2 ,如果画面出错,1=2是不成立的,可以肯定这个地址可以注入。
http://www.xxx.com/news.asp?id=1 and 1=2
好戏来了:
http://www.xxx.com/news.asp?id=1 and (select * from admin)>0
不出错,证明数据库有admin这个表。
http://www.xxx.com/news.asp?id=1 and (select username from admin)>0
不出错,证明数据库的admin有username这个字段。
http://www.xxx.com/news.asp?id=1 and len(select top 1 username from admin)>5
不出错,证明数据库的admin的第一个username长度>5。
后面的自己测试……本文的目的仅用于各位站长检测自己的站有没有SQL注入漏洞。 |