WEB安全解决方案一之SQL注入防范
一、SQL注入防范
在一个WEB动态页面中(例如aspx或者jsp),这个页面允许用户在输入框中输入字符,这个字符可以被引入到数据库中去进行查询(这里的查询是通用的说法,实际上包括了增删改查)操作。一个黑客在这个输入框中输入了一个畸形查询字符串,从而改变了原有的查询,这可以被用来插入,改变,或损害后台数据库。怎么可能呢?请看下面的例子。
以登陆为例,后台代码通过构造SQL语句“select * from user where username = 'txtUserName.Text.Trim() 'and password ='txtPwd.Text.Trim()';如果用户在输入框中输入用户名为admin'or'1'='1, 让后任意输入比如123为密码,则后台执行的SQL语句为select * from user where username='admin'or'1'='1'and password='123';这是,无论密码是否正确,最终SQL语句查询结果都不为空,这便是一个典型的SQL注入攻击,通过此种方式,攻击者成功绕过密码验证,登陆系统。一个典型的解决方案是构造“select count(*) from user where username='txtUserName.Text.Trim() 'and password = 'txtPwd.Text.Trim()'这样的SQL语句,这样如果攻击者采取上述攻击方式,则会因为返回的count值大于1而验证失败。
但问题并不会因此结束,如果攻击者构造如下的攻击语句呢?比如“select count(*) from user where username=’txtUserName.Text.Trim() ‘--and password =’txtPwd.Text.Trim’,注意加粗的部分实际上是被注释掉了,也就是说验证将会成功。更厉害的,攻击者会构造出“select count(*) from user where username ='txtUserName.Text.Trim() ';drop table user ;--’ and password ='txtPwd.Text.Trim';注意到不仅验证通过,而且user表被删除,这下子谁都不要想再登陆了。
类似的,黑客们通过精巧的构造,可以达到绕过密码认证,修改破坏关键数据,乃至获取系统完全控制权的目的。这里你也许会问攻击者如何得到数据库中的表名和字段,这里一种方法是暴力破解,根据规律尝试,比如系统多存在user表,用来存放用户信息。另外一种方法是利用SQL注入攻击猜解,通过构造一些能够使数据库产生错误信息的SQL语句,获取数据库的敏感信息,进行表名和字段的猜解,密码破解等。
解决方法
1. 避免使用动态生成的SQL语句
通过字符串相加的方式动态生成的SQL语句正是SQL注入的万恶之源,
相关文档:
Oracle SQL 的优化规
一:尽量少用IN操作符,基本上所有的IN操作符都可以用EXISTS代替 ,用IN写出来的SQL,的优点是比较容易写及清晰易懂,但是用IN的SQL
性能总是比较低的,从ORACLE执行的步骤来分析用IN的SQL与不用IN的SQL有以下区别:
ORACLE试图将其转换成多个表的连接,如果转换 ......
SQL用select语句查询重复记录
http://hi.baidu.com/bilbit/blog/item/5ed5de16a6f6b412962b43eb.html
用select语句,查询重复记录
假设,表名为 T1 子段为 A,B,C
select count(*) ,A,B,C from T1
group by A,B,C having count(*) > 1
测试数据:
A100 &n ......
SQL用select语句查询重复记录
http://hi.baidu.com/bilbit/blog/item/5ed5de16a6f6b412962b43eb.html
用select语句,查询重复记录
假设,表名为 T1 子段为 A,B,C
select count(*) ,A,B,C from T1
group by A,B,C having count(*) > 1
测试数据:
A100 &n ......
从tablename 表中取出第 n 条到第 m 条的记录
SQL SERVER的写法
SELECT TOP m-n+1 *
from tablename
WHERE (id NOT IN
(SELECT TOP n-1 id from tablename))
你这是一个分页算法的,我提供的比较简单,网上还有很多不错的,如果你对这个不满意,再去网上找找 关键字 “分页算法”
ORACLE的话改一下 ......
1 TOP
这是一个大家经常问到的问题,例如在SQLSERVER中可以使用如下语句来取得记录集中的前十条记录:
SELECT TOP 10 * from [index] ORDER BY indexid DESC;
但是这条SQL语句在SQLite中是无法执行的,应该改为:
SELECT * from [index] ORDER BY indexid DESC limit 0,10;
其中limit 0,10表示从第0条记录开始,往后 ......