一、SQL注入简介
SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编写时的疏忽,通过SQL语句,实现无账号登录,甚至篡改数据库。
二、SQL注入攻击的总体思路
- 寻找到SQL注入的位置
- 判断服务器类型和后台数据库类型
- 针对不同的服务器和数据库特点进行SQL注入攻击
三、SQL注入攻击实例
SQL在线编辑器 数据脚本
CREATE TABLE t_user (
vc_name varchar(20),
vc_pwd varchar(20)
);
INSERT INTO t_user VALUES ('kyra', '123');
INSERT INTO t_user VALUES ('alanchen', 'abc');
3.1 SQL注入获取所有用户数据
public class Client {
public static void main(String[] args) {
String userName = "1' or '1'='1";
String passWord = "1' or '1'='1";
packSQL(userName,passWord);
}
private static void packSQL(String userName,String passWord) {
String strSQL = "select * from t_user where vc_name='" + userName + "' and vc_pwd = '"+passWord +"'";
System.out.println(strSQL);
}
}
得到执行SQL
select * from t_user where vc_name='1' or '1'='1' and vc_pwd = '1' or '1'='1'
将获得所有用户数据
3.2 SQL注入删除用户表
public class Client {
public static void main(String[] args) {
String userName = "1' or '1'='1";
String passWord = "1' or '1'='1';drop table t_user; -- ";
packSQL(userName,passWord);
}
private static void packSQL(String userName,String passWord) {
String strSQL = "select * from t_user where vc_name='" + userName + "' and vc_pwd = '"+passWord +"'";
System.out.println(strSQL);
}
}
得到执行SQL
select * from t_user where vc_name='1' or '1'='1' and vc_pwd = '1' or '1'='1';drop table t_user; -- '
用户表被删除,甚至可以删除整个库
四、产生SQL注入漏洞的原因
但凡有SQL注入漏洞的程序,都是因为程序要接受来自客户端用户输入的变量或URL传递的参数,并且这个变量或参数是组成SQL语句的一部分,对于用户输入的内容或传递的参数,我们应该要时刻保持警惕,这是安全领域里的「外部数据不可信任」的原则,纵观Web安全领域的各种攻击方式,大多数都是因为开发者违反了这个原则而导致的,所以自然能想到的,就是从变量的检测、过滤、验证下手,确保变量是开发者所预想的。
五、如何防御SQL注入
5.1 不要使用动态SQL
避免将用户提供的输入直接放入SQL语句中;最好使用准备好的语句和参数化查询,这样更安全。
5.2 绑定变量,使用预编译语句
MySQL的mysqli驱动提供了预编译语句的支持,不同的程序语言,都分别有使用预编译语句的方法实际上,绑定变量使用预编译语句是预防SQL注入的最佳方式,使用预编译的SQL语句语义不会发生改变,在SQL语句中,变量用问号?表示,黑客即使本事再大,也无法改变SQL语句的结构
5.3 限制数据库权限和特权
将数据库用户的功能设置为最低要求;这将限制攻击者在设法获取访问权限时可以执行的操作。如不要给web服务连接数据库的用户删库删表的权限。MySQL有一个操作安全设置:SQL_SAFE_UPDATES,delete数据需要通过id来删除,如果需要全表删除或者其他条件删除,需要将SQL_SAFE_UPDATES设置为0
5.4 避免直接向用户显示数据库错误
攻击者可以使用这些错误消息来获取有关数据库的信息。