6 sql注入漏洞

目录

6 sql注入漏洞

6.1 SQL 注入漏洞核心概念

6.2 SQL 注入漏洞产生原因

6 sql注入漏洞

6.1 SQL 注入漏洞核心概念

6.2 SQL 注入漏洞产生原因

6.3 SQL 注入漏洞解决办法(PreparedStatement 方案 )

6.4 总结


6 sql注入漏洞

6.1 SQL 注入漏洞核心概念

  • SQL 注入漏洞:是程序代码中存在的 “安全缺陷”(比如代码没过滤用户输入、直接拼接 SQL 语句),这是 “根源”。
  • SQL 注入:是黑客利用这个 “缺陷” 发起的 “攻击行为”(比如输入 aaa'or'1=1 来篡改 SQL 逻辑),这是 “结果”。

6.2 SQL 注入漏洞产生原因

  1. 本质逻辑:程序未对用户输入做过滤、验证,直接把用户输入拼接到 SQL 语句里执行,让用户输入能 “篡改原本 SQL 逻辑” 。
  2. 产生效果:在已知用户名的情况下,输入任意的密码,登陆进去。
  1. 前提条件
    * 先已知用户名
    * 后台的程序拼接SQL语句
  1. SQL注入的漏洞怎么产生?
SQL 注入产生原因是 SQL 语句的拼接,利用 SQL 关键字产生效果。比如:and和or的优先级、注释。sql 语句是在本地拼接好的,问题就出现在了本地字符串拼接
  1. 代码层面演示(以 Java 代码为例)
假设有登录功能,后台用如下有漏洞的代码处理用户输入:

6 sql注入漏洞

6.1 SQL 注入漏洞核心概念

  • SQL 注入漏洞:是程序代码中存在的 “安全缺陷”(比如代码没过滤用户输入、直接拼接 SQL 语句),这是 “根源”。
  • SQL 注入:是黑客利用这个 “缺陷” 发起的 “攻击行为”(比如输入 aaa'or'1=1 来篡改 SQL 逻辑),这是 “结果”。

6.2 SQL 注入漏洞产生原因

  1. 本质逻辑:程序未对用户输入做过滤、验证,直接把用户输入拼接到 SQL 语句里执行,让用户输入能 “篡改原本 SQL 逻辑” 。
  2. 产生效果:在已知用户名的情况下,输入任意的密码,登陆进去。
  1. 前提条件
    * 先已知用户名
    * 后台的程序拼接SQL语句
  1. SQL注入的漏洞怎么产生?
SQL 注入产生原因是 SQL 语句的拼接,利用 SQL 关键字产生效果。比如:and和or的优先级、注释。sql 语句是在本地拼接好的,问题就出现在了本地字符串拼接
  1. 代码层面演示(以 Java 代码为例)
假设有登录功能,后台用如下有漏洞的代码处理用户输入:
 
Scanner inScanner = new Scanner(System.in);
System.out.println("请输入用户名");
String username = inScanner.nextLine();
System.out.println("请输入密码");
String password = inScanner.nextLine();
// 直接拼接用户输入到 SQL 语句,存在漏洞!
String sql = "select * from t_user where username = '"+username+"' and password = '"+password+"'"; 
search(sql);
这里把用户输入的 username 和 password 直接拼接到 SQL ,没任何过滤,就给了攻击者篡改 SQL 逻辑的机会。
  1. 攻击案例拆解
  • 案例 1:输入 aaa'or'1=1(万能密码攻击 )
  • 用户输入:用户名填 aaa'or'1=1 ,密码随意输(比如 123 )。
  • 拼接后 SQL:
select * from t_user where username = 'aaa'or'1=1' and password = '123'
  • 此时 SQL 的逻辑被强制拆成:
(username = 'aaa') OR ('1=1') AND (password = '123')
  • SQL 中 OR 的优先级低于 AND。实际执行顺序等价于:
(username = 'aaa') OR ( ('1=1') AND (password = '123') )
  • '1=1' 恒为真,导致where恒为真,数据库返回存在该用户,攻击者成功登录。
  • 案例 2:输入 aaa'-- '(注释绕密码验证 )
    • 用户输入:用户名填 aaa'-- ' ,密码随意输。
    • 拼接后 SQL:
select * from t_user where username = 'aaa'-- ' and password = '123'
  • 逻辑篡改:-- 是 SQL 单行注释符,后面 and password = '123' 被注释,SQL 实际执行 select * from t_user where username = 'aaa' ,跳过密码验证,只要有对应用户名记录就登录成功。

6.3 SQL 注入漏洞解决办法(PreparedStatement 方案 )

  1. 产生 sql 注入的原因:sql 语句是在本地拼接好的,问题就出现在了本地字符串拼接。
  2. 如何去解决:sql 不在本地进行拼接。
  3. PreparedStatement 有一个功能—— 在拼接之前对要拼接的数据进行检验 如果遇到了 ' 会在前边加转义字符(\)。比如输入的 1'or'1='1 里的 ' 会被转义成 \' ,最终传入 SQL 的条件变成:
where username = 'aaa' and password = '1\'or\'1\'=\'1'
此时所有的 ' 都只是普通字符串里的引号,不再具备 “闭合字符串、拼接 SQL 逻辑” 的能力,数据库会把 1\'or\'1\'=\'1 当作完整的密码字符串去匹配,而不是 SQL 语法的一部分。
  1. 核心思路:用 PreparedStatement 接口(Statement 子接口 ),利用预编译 SQL 功能,让用户输入仅作 “数据”,不参与 SQL 语法构建,切断输入篡改逻辑的可能。
  2. 代码实现步骤
    1. 编写预编译 SQL:用 ? 占位符代替用户输入的参数(在具体一点的解释见MyBatis 9),示例:
String sql = "select * from t_user where username = ? and password = ?"; 
  1. 创建 PreparedStatement 对象:通过 Connection 的 prepareStatement 方法,传入预编译 SQL :
PreparedStatement statement = connection.prepareStatement(sql);
  1. 给占位符传值:用 setXxxx 方法(按参数类型选,如 setString 、setInt 等 ),根据 ? 位置(从 1 开始 )传值:
statement.setString(1, username); 
statement.setString(2, password); 
  1. 执行 SQL:调用 executeQuery(查询 )或 executeUpdate(增删改 ),无需再传 SQL 语句:
ResultSet re = statement.executeQuery(); // 查询示例
  1. 防注入原理
预编译时,SQL 语法结构已固定,? 只接收 “数据”。就算用户输入特殊字符(如 ' 、OR ),也会被当普通数据处理,不改变 SQL 逻辑,从根源杜绝注入。
完整代码示例(结合登录场景 ):
Scanner inScanner = new Scanner(System.in);
System.out.println("请输入用户名");
String username = inScanner.nextLine();
System.out.println("请输入密码");
String password = inScanner.nextLine();

// 预编译 SQL,用 ? 占位
String sql = "select * from t_user where username = ? and password = ?"; 
System.out.println("sql=" + sql);

search(sql, username, password);

public static void search(String sql, String username, String password) {
    try {
        Class.forName("com.mysql.jdbc.Driver"); 
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8"); 
        
        // 创建 PreparedStatement,预编译 SQL
        PreparedStatement statement = connection.prepareStatement(sql);
        // 给 ? 传值
        statement.setString(1, username); 
        statement.setString(2, password); 
        
        // 执行查询
        ResultSet re = statement.executeQuery(); 
        // 后续处理结果集...
    } catch (Exception e) {
        e.printStackTrace();
    }
}

6.4 总结

  • 漏洞产生:程序直接拼接用户输入到 SQL ,让输入能篡改执行逻辑。
  • 攻击利用:构造含 SQL 关键字、注释符的输入(如 aaa'or'1=1 、aaa'-- ' ),改变查询条件,绕权限验证。
  • 漏洞修复:用 PreparedStatement 预编译 SQL ,固定语法结构,让用户输入仅作数据,彻底解决注入风险 。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值