详解SQL注入问题

一、代码漏洞根源

核心危险代码:

复制代码
// 直接拼接用户输入拼接SQL语句
String sql="select * from password where username='"+username+"'and password='"+password+"'";

使用 Statement + 字符串拼接 SQL ,用户输入的内容会直接拼入 SQL 语句,数据库会执行输入里的 SQL 逻辑,造成注入攻击。

二、注入攻击演示

1. 恶意输入

  • 用户名输入:

    1111

  • 密码输入:

    1' or '1' ='1

2. 拼接后最终执行 SQL,恒成立

复制代码
select * from password where username='1111'and password='1' or '1' ='1'

输出:

三、SQL 能登录成功的核心逻辑

数据库是这样计算的:

复制代码
where (条件A  and  条件B)  or  条件C
  • 条件 Ausername='1111'
  • 条件 Bpassword='1'
  • 条件 C'1'='1'永远成立!

最终结果:

复制代码
假 and 假  or  真
= 假 or 真
= 真

只要有一个条件成立,整个 WHERE 就成立!直接查到数据 → 登录成功!

本来想让数据库验证:

复制代码
用户名正确 并且 密码正确

结果被用户改成了:

复制代码
(用户名正确 并且 密码正确) 或者 1=1

1=1 永远是对的,所以不管用户名密码是什么,都能登录!


五、SQL 注入原理

用户输入的内容里带 SQL 语法,直接破坏了原本的查询逻辑,可以实现绕过密码登录。

  1. 前端用户输入带有 SQL 语法的特殊字符
  2. 后端无过滤,直接把输入拼入完整 SQL
  3. MySQL 识别拼接后的完整 SQL 并执行恶意逻辑
  4. 实现越权查询、篡改、删除数据

六、高危注入危害输入

  • 篡改全部数据
  • 直接删除数据表

七、解决方案(杜绝 SQL 注入)

  1. 放弃 Statement,使用 PreparedStatement 预编译对象
  2. 使用 ? 作为占位符替代字符串拼接
  3. 预编译会把用户输入全部当成普通文本,不会解析执行 SQL 语法

安全修复代码

复制代码
package com.qcby.sql;

import java.sql.*;
import java.util.Scanner;

public class LoginUtil {
    public static void main(String[] args) throws Exception{
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入用户名");
        String username=scanner.nextLine();
        System.out.println("请输入密码");
        String password=scanner.nextLine();
        safeLogin(username,password);
    }

    public static void safeLogin(String username,String pwd) throws Exception{
        Class.forName("com.mysql.cj.jdbc.Driver");
        String url="你的数据库";
        String user="***";
        String password="****";
        Connection connection= DriverManager.getConnection(url,user,password);

        // 使用占位符,禁止字符串拼接
        String sql = "select * from password where username=? and password=?";
        PreparedStatement pstmt = connection.prepareStatement(sql);
        // 给占位符赋值
        pstmt.setString(1,username);
        pstmt.setString(2,pwd);

        ResultSet set=pstmt.executeQuery();
        if(set.next()){
            System.out.println("登录成功");
        }else{
            System.out.println("登录失败");
        }
        set.close();
        pstmt.close();
        connection.close();
    }
}
相关推荐
Nontee1 小时前
MySQL 插入冲突了怎么办?两种处理方式入门笔记
数据库·笔记·mysql
ltl1 小时前
Parquet 文件格式:row group、编码与谓词下推索引
数据库
OpenCloudOS1 小时前
从快速响应到问题发现:一次backport挖出全新漏洞CVE-2026-76641
服务器·网络·安全
ltl1 小时前
PostgreSQL Join 路径:优化器如何选中 Nested Loop
数据库
张文君1 小时前
ubuntu26.04从ext4改成mdadm的raid1+lvm启动
linux·运维·网络
德迅云安全-上官1 小时前
游戏攻防反套路:德迅云安全游戏盾如何破解黑产的“低成本精准打击”
网络·安全·游戏
2401_868534781 小时前
服务器实战
网络·beautifulsoup
ltl2 小时前
RocksDB 生产嵌入:Flink、TiKV 与 Kafka Streams 怎么用
数据库
ouynagda2 小时前
Linux 进程管理详解:从概念到实践
linux·运维·网络
dog2503 小时前
再论 TCP 的流式传输
网络·网络协议·tcp/ip