《SQL》注入漏洞
1.漏洞演示
-
SQL注入漏洞的来源:在文本框向SQL语句中输入了关键字
-
只知道用户名就可以进行登录
-
程序演示
package com.imooc.jdbc.demo2; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import org.junit.Test; import com.imooc.jdbc.utils.JDBCUtils; /** * 演示JDBC的注入的漏洞 * @author jt * */ public class JDBCDemo4 { @Test /** * 测试SQL注入漏洞的方法 */ public void demo1(){ boolean flag = JDBCDemo4.login2("aaa' or '1=1", "1fsdsdfsdf"); if(flag == true){ System.out.println("登录成功!"); }else{ System.out.println("登录失败!"); } } /** * 产生SQL注入漏洞的方法 * @param username * @param password * @return */ public static 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; }else{ flag = false; } }catch(Exception e){ e.printStackTrace(); }finally{ JDBCUtils.release(rs, stmt, conn); } return flag; } }
2.漏洞解决
-
漏洞根本问题:SQL语句字符串的拼接
-
解决方法:用PreparedStatement对象——预处理对象,使用占位符对SQL语句变量的地方进行占位
- PreparedStatement是Statement的子接口,它的实例对象可以通过Connection.preparedStatement(sql)方法获得
- PreperedStatement可以避免SQL注 入的问题,Statement会使数据库频繁编译SQL ,可能造成数据库缓冲区溢出。
- PreparedStatement可对SQL进行预编译,从而提高数据库的执行效率。并且PreperedStatement对于sq|中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。
-
程序演示
package com.imooc.jdbc.demo2; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import org.junit.Test; import com.imooc.jdbc.utils.JDBCUtils; /** * 演示JDBC的注入的漏洞 * @author jt * */ public class JDBCDemo4 { @Test /** * 测试SQL注入漏洞的方法 */ public void demo1(){ boolean flag = JDBCDemo4.login2("aaa' or '1=1", "1fsdsdfsdf"); if(flag == true){ System.out.println("登录成功!"); }else{ System.out.println("登录失败!"); } } /** * 避免SQL注入漏洞的方法 */ public static boolean login2(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; }else{ flag = false; } }catch(Exception e){ e.printStackTrace(); }finally{ JDBCUtils.release(rs, pstmt, conn); } return flag; }