SQL注入(案例演示)
一、SQL注入是什么?
在程序事先定义好的
查询语句中添加额外的SQL语句
,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询
,从而进一步得到相应的数据信息。
SQL注入通俗说就是:
通过SQL语句找到破绽,进行非法的数据读取。
二、实现步骤
说明:用一个简单的查询案列说明 SQL 注入
案例使用的为:Java语言与MySQL数据库
1.新建数据表
1.新建一个数据表并添加几条数据
# 新建表
CREATE TABLE `user` (
`user_name` varchar(255),
`password` varchar(255)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
# 向表中添加数据
INSERT INTO `user` VALUES ('zhangsan', '123456');
INSERT INTO `user` VALUES ('1', '2');
INSERT INTO `user` VALUES ('1', '1');
INSERT INTO `user` VALUES ('1', '3');
此时数据库的数据为下图所示:
2.SQL注入分析
1.定义SQL语句
可以看出在参数userName和password 的部分SQL语句是传递的字符串,也就是说可以传递任意内容
String sql = "select * from user where user_name = ’ " + userName + "’ and password = ’ " + password + " ’ ";
2.设置userName和password参数值
通过参数userName的传值来演示获取非法数据
将userName的值分为四种情况,password 的值在这四种情况下都为固定值 1
合法参数获取数据 |
---|
String userName = “1”; String password = “1”; |
传递参数后SQL语句变为: select * from user where user_name = ‘1’ and password = ‘1’ |
此时可从数据库中读取出一条数据: |
非法参数获取数据(1)—— 掌握一部分信息即可获取到其它信息 |
---|
String userName = “1’ or password = '”; String password = “1”; |
传递参数后SQL语句变为: select * from user where user_name = ‘1’ or password = ‘ ' and password = '1 ’ |
此时可从数据库中读取出三条数据: |
非法参数获取数据(2)—— 什么都不需要即可获取所有信息 |
---|
String userName = “’ or user_name like ‘%%’ or password = '”; String password = “1”; |
传递参数后SQL语句变为: select * from user where user_name = ‘’ or user_name like ‘%%’ or password = ‘ 'and password = '1 ’ |
此时可从数据库中读取出四条数据: |
非法参数获取数据(3)—— 利用# 注释掉多余SQL |
---|
String userName = "’ or user_name like ‘%%’ # or password = ’ "; String password = “1”; |
传递参数后SQL语句变为: select * from user where user_name = '' or user_name like '%%' # |
此时可从数据库中读取出四条数据: |
3.代码案例
1.新建一个User实体类
【说明】
如果不使用lombok的@Data注解,需要添加set get方法和toString方法
@Data
public class User {
private String userName;
private String password;
}
2.新建Demo类,体验SQL注入
public class Demo {
public static void main(String[] args) throws Exception{
// String userName = "1"; // 正常操作
// String userName = "1' or password = '"; // 掌握丢丢信息就可以获取其它信息
// String userName = "' or user_name like '%%' or password = '"; // 什么都不需要就可拿到所有信息
String userName = "' or user_name like '%%' # or password = ' "; // 升级版
String password = "1";
// 加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
// 创建数据库连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/user表所在的数据库名?" +
"characterEncoding=utf-8&useUnicode=true","root","123456");
// 定义SQL语句
String sql = "select * from user where user_name = '" + userName + "' and password = '" + password + "'";
// 打印出拼接后的SQL语句
System.out.println(sql);
// 创建SQL执行对象
Statement stmt = conn.createStatement();
// 执行SQL语句并返回结果集
ResultSet rs = stmt.executeQuery(sql);
// 遍历出结果集到List集合
List<User> userList = new CopyOnWriteArrayList<>();
while (rs.next()) {
User user = new User();
user.setUserName(rs.getString(1));
user.setPassword(rs.getString(2));
userList.add(user);
}
// 打印结果集
for (User user : userList) {
System.out.println(user);
}
}
}
三、防止SQL注入的方式
- SQL预编译(Java提供了PreparedStatement类)
- 校验参数(使用正则表达式等)