1.1注入漏洞
在早期互联网上SQL注入漏洞普遍存在。有一个网站,用户需要进行注册,用户注册以后根据用户名和密码完成登录。假设现在用户名已经被其他人知道了,但是其他人不知道你的密码,也可以登录到网站上进行相应的操作。
1.2 漏洞代码
1.2.1 编写用户登录
public boolean login(String username,String password){
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
// 定义一个变量:
boolean flag = false;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 完成登录功能:
// 创建执行SQL语句的对象:
stmt = conn.createStatement();
// 编写SQL语句:
String sql = "select * from user where username = '"+username+"' and password = '"+password+"'";
// 执行SQL:
rs = stmt.executeQuery(sql);
if(rs.next()){
// 说明根据用户名和密码可以查询到这条记录
flag = true;
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(rs, stmt, conn);
}
return flag;
}
1.2.2 演示SQL注入漏洞
- 输入用户名
- aa’ or ‘1=1 密码随意
- aaa’ -- +空格 密码随意
/**
* SQL注入的漏洞
* @author jt
*
*/
public class JDBCDemo4 {
@Test
/**
* SQL注入漏洞的演示
*/
public void demo1(){
UserDao userDao = new UserDao();
// boolean flag = userDao.login("aaa", "123");
// boolean flag = userDao.login("aaa' or '1=1", "asdfjklsd");
boolean flag = userDao.login("aaa' -- ", "qweqwersdfsd");
if(flag){
System.out.println("登录成功!");
}else{
System.out.println("登录失败!");
}
}
}
1.3 漏洞解决
1.3.1 原理分析
// 编写SQL语句:
String sql = "select * from user where username = '"+username+"' and password = '"+password+"'";
- 输入的用户名
- aa' or '1=1 密码随意
- aaa' -- 密码随意
- 原因
- 在变量中存在SQL的关键字
- or
- -- :表示后面语句都是注释
- 这些都是SQL中的关键字
- 在变量中存在SQL的关键字
select * from user where username = 'aa' or '1=1' and password = '22d'
select * from user where username = 'aa' -- and password = '22d'
1.3.2 注入漏洞解决
需要采用PreparedStatement对象解决SQL注入漏洞。这个对象将SQL预先进行编译,使用?作为占位符。?所代表内容是SQL所固定。再次传入变量(包含SQL的关键字)。这个时候也不会识别这些关键字。
public class UserDao {
public boolean login(String username,String password){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
// 定义一个变量:
boolean flag = false;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 编写SQL语句:
String sql = "select * from user where username = ? and password = ?";
// 预编译SQL
pstmt = conn.prepareStatement(sql);
// 设置参数:
pstmt.setString(1, username);
pstmt.setString(2, password);
// 执行SQL语句:
rs = pstmt.executeQuery();
if(rs.next()){
// 说明根据用户名和密码可以查询到这条记录
flag = true;
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(rs, pstmt, conn);
}
return flag;
}