在web应用架构下,终端用户无法直接访问数据库,需要通过http请求到java应用服务器,然后由java应用服务器来访问后端数据库,恶意用户想要获取数据库中的核心价值数据就绕不开Java应用程序,唯一的途径是利用业务程序的漏洞,伪装自己的请求,欺骗业务程序达到最终获取数据库数据的目的。
SQL注入:用户在输入表单或url参数中输入sql命令达到欺骗Java应用程序的目的,破坏原有sql语义,发送恶意的sql到后端数据库,导致数据库信息出现泄露的漏洞。
例如:用户表单登录:用户名:zhangsan’;-- (<-有一个空格)
提交之后:select * from user where username=’zhangsan’;-- ‘ and password = ‘111’;
导致--后面的内容被注释
原因:利用java服务器的动态拼接sql的漏洞,破坏了原先java程序设定的sql语义,欺骗服务器达到恶意获取数据的目的。
解决方案:调用.preparedStatement(sql)方法传入格式化的sql
select * from user where username=? And password = ? (?:占位符)
代码如下:
public static User login(String userName, String password) throws ClassNotFoundException{
Connection conn = null;
PreparedStatement ptmt = null;
ResultSet rs = null;
User user = null;
//装载驱动程序
Class.forName(JDBC_DRIVER);
//建立数据库连接
try{
conn = DriverManager.getConnection(DB_URL,USER,PASSWD);
//执行sql语句
ptmt = conn.prepaerStatement("select * from user userName = ? and password = ?");
ptmt.setString(1,userName);
ptmt.setString(2,password);
rs = ptmt.executeQuery();
//获取执行结果
while(rs.next()){
user = new User();
user.setUserName(rs.getString("userName"));
user.setSex(rs.getBoolean("sex"));
}
}catch(SQLException e){
//异常处理
e.printStackTrace();
}finally{
//清理资源
try{
if(conn != null) conn.close();
if(ptmt != null) ptmt.close();
if(rs != null) rs.close();
}catch(SQLException e){
}
}
return user;
}
注意事项:
- 严格的数据库管理权限:仅给与Web应用访问数据库的最小权限;避免 Drop table等权限。
- 封装数据库错误:禁止直接将后端数据库异常信息暴露给用户;对后端异常信息进行必要的封装,避免用户直接查看后端异常。
- 机密信息禁止明文存储:涉密信息需要加密处理,使用AES_ENCRYPT和AES_DECRYPT加密和解密