Java 中 SQL 注入问题剖析
一、引言
在当今数字化时代,数据是企业和组织的核心资产之一。许多应用程序都依赖于数据库来存储和管理数据,而 Java 作为一种广泛使用的编程语言,常被用于开发与数据库交互的应用程序。然而,SQL 注入这一安全漏洞却如同隐藏在暗处的炸弹,时刻威胁着这些应用程序的数据安全。
二、SQL 注入的原因
2.1 拼接 SQL 语句
在 Java 应用程序中,当开发人员直接将用户输入的数据拼接到 SQL 语句中时,就为 SQL 注入攻击埋下了隐患。以下是一个简单的示例代码:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
public class SQLInjectionExample {
public static void main(String[] args) {
try {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb", "root", "password");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = scanner.nextLine();
System.out.println("请输入密码:");
String password = scanner.nextLine();
String sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
if (rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}
rs.close();
stmt.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
在上述代码中,用户输入的用户名和密码直接被拼接到 SQL 语句中。如果攻击者输入恶意的 SQL 代码,就可能改变原 SQL 语句的语义。
2.2 缺乏输入验证
当应用程序没有对用户输入进行严格的验证和过滤时,攻击者可以轻松地输入恶意的 SQL 代码。例如,在上述登录示例中,如果用户输入的密码为' OR '1'='1,那么最终生成的 SQL 语句将变为:
SELECT * FROM users WHERE username = 'xxx' AND password = '' OR '1'='1'
由于'1'='1'始终为真,这个 SQL 语句将返回users表中的所有记录,攻击者就可以绕过正常的身份验证机制登录系统。
三、SQL 注入的种类
3.1 基于字符串的注入
这是最常见的 SQL 注入类型之一。在这种注入方式中,攻击者利用应用程序对字符串输入处理不当的漏洞。例如,在前面提到的 Java 登录示例中,如果输入的用户名或密码字段没有正确处理,攻击者输入类似' OR '1'='1 --的字符串。其中,OR '1'='1用于改变 SQL 语句的逻辑,使其永远为真,而--是 SQL 中的注释符号,用于注释掉后面可能存在的 SQL 语句部分,从而达到绕过验证或获取非法数据的目的。
3.2 数字型注入
当应用程序期望用户输入数字,并将其直接用于 SQL 查询时,容易发生数字型注入。例如,SQL 语句可能是SELECT * FROM products WHERE product_id = + userInput。如果攻击者输入1 OR 1=1,则最终的 SQL 语句变为SELECT * FROM products WHERE product_id = 1 OR 1=1。由于1=1恒为真,该查询将返回products表中的所有记录。
3.3 布尔盲注
布尔盲注发生在应用程序对 SQL 查询结果的反馈只有两种状态(通常是真或假,比如页面显示正常或错误)的情况下。攻击者通过构造不同的 SQL 注入语句,根据应用程序返回的不同状态来推断数据库中的信息。例如,攻击者可以构造这样的注入语句' AND (SELECT COUNT(*) FROM users WHERE username = 'admin') > 0 --,如果返回的页面状态表示条件为真,那么就可以推断出数据库中存在名为admin的用户。攻击者不断改变注入语句中的条件,通过多次尝试来逐步获取数据库中的数据。
3.4 时间盲注
时间盲注利用了数据库执行特定操作时的时间延迟来推断信息。当应用程序对 SQL 查询结果没有直接的反馈信息时,攻击者可以通过让数据库执行一些耗时操作,根据操作执行的时间来判断注入语句是否成功。例如,在 MySQL 数据库中,攻击者可以使用' AND SLEEP(5) --这样的注入语句,如果数据库执行该语句后页面延迟了 5 秒加载,就说明该注入语句可能被成功执行,攻击者可以通过类似的方式逐步推断数据库中的数据。
3.5 联合查询注入
联合查询注入允许攻击者在原有的 SQL 查询基础上添加额外的查询语句。例如,假设原 SQL 语句是SELECT name, age FROM users WHERE user_id = + userInput。攻击者输入1 UNION SELECT database(), version() --,那么最终的 SQL 查询将变成SELECT name, age FROM users WHERE user_id = 1 UNION SELECT database(), version()。这样攻击者就可以获取数据库的名称和版本等信息。
四、相关SQL注入的事件
4.1 美国零售商塔吉特(Target)数据泄露事件
2013 年,美国零售商塔吉特遭遇了严重的 SQL 注入攻击。攻击者通过入侵塔吉特的支付系统,获取了约 4000 万张信用卡信息和 7000 万客户的个人信息。此次攻击导致塔吉特公司遭受了巨大的经济损失,包括赔偿客户、修复系统漏洞等费用,同时也严重损害了公司的声誉。
4.2 索尼 PlayStation Network 数据泄露事件
2011 年,索尼的 PlayStation Network 遭受了 SQL 注入攻击,导致约 7700 万用户的个人信息泄露,包括姓名、地址、出生日期、电子邮件地址等。此次攻击导致 PlayStation Network 服务中断数周,给索尼公司带来了巨大的经济损失和声誉损害。
五、SQL 注入导致的问题
4.1 数据泄露
攻击者可以通过 SQL 注入漏洞获取数据库中的敏感信息,如用户的账号密码、信用卡号、个人身份信息等。这些信息一旦泄露,可能会给用户和企业带来巨大的损失。
4.2 数据篡改
攻击者可以利用 SQL 注入漏洞修改数据库中的数据,例如修改用户的账户余额、订单状态等。这不仅会影响企业的正常运营,还可能导致法律纠纷。
4.3 数据库损坏
在某些情况下,攻击者可以通过 SQL 注入执行删除数据库表、删除数据库等操作,导致数据库无法正常使用,给企业带来严重的经济损失。
六、预防 SQL 注入的方法
6.1 使用预编译语句(PreparedStatement)
预编译语句是预防 SQL 注入的最有效方法之一。在 Java 中,PreparedStatement接口会对 SQL 语句进行预编译,将用户输入的数据作为参数进行处理,而不是直接拼接到 SQL 语句中。以下是使用PreparedStatement改写后的登录示例代码:
TypeScript
取消自动换行复制
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Scanner;
public class SecureLoginExample {
public static void main(String[] args) {
try {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb", "root", "password");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = scanner.nextLine();
System.out.println("请输入密码:");
String password = scanner.nextLine();
String sql = "SELECT * FROM users WHERE username =? AND password =?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}
rs.close();
pstmt.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
在这个代码中,?是占位符,用户输入的数据会被安全地设置到占位符位置,数据库驱动会自动处理数据的转义等操作,从而有效防止 SQL 注入。
6.2 输入验证与过滤
除了使用预编译语句,对用户输入进行严格的验证和过滤也是必不可少的。可以使用正则表达式等方式验证用户输入是否符合预期的格式。例如,对于用户名,可以限制只能包含字母和数字:
取消自动换行复制
import java.util.regex.Pattern;
public class InputValidation {
public static boolean isValidUsername(String username) {
String pattern = "^[A-Za-z0-9]+$";
return Pattern.matches(pattern, username);
}
}
对于密码等敏感信息,也可以设置强度要求,并进行验证。同时,要过滤掉用户输入中的特殊字符,如单引号、双引号、分号等可能用于 SQL 注入的字符。但需要注意的是,输入验证和过滤不能完全替代预编译语句,它只是作为一种额外的安全措施。
6.3 最小权限原则
在数据库中,为应用程序使用的数据库用户分配最小的权限。例如,如果应用程序只需要读取某些表的数据,那么就只赋予该用户对这些表的SELECT权限,而不给予INSERT、UPDATE、DELETE等其他不必要的权限。这样即使发生 SQL 注入攻击,攻击者也无法执行修改或删除数据等危险操作。
6.4 安全框架与工具的使用
利用成熟的安全框架,如 Spring Security 等,这些框架提供了一系列的安全功能,包括防止 SQL 注入的机制。同时,使用静态代码分析工具,如库博静态代码分析工具等,它们可以在开发过程中检测代码中潜在的 SQL 注入风险,帮助开发人员及时发现和修复问题。
七、结论
SQL 注入是一种严重的安全漏洞,它可能会给企业和用户带来巨大的损失。在 Java 开发中,开发人员应该避免直接拼接 SQL 语句,而是使用预编译语句(PreparedStatement)来防止 SQL 注入。同时,要对用户输入进行严格的验证和过滤,遵循最小权限原则,并合理使用安全框架与工具。通过采取这些措施,可以有效降低 SQL 注入攻击的风险,保护企业和用户的数据安全。为了更好地发现软件代码中SQL注入的问题,可以采用静态代码审计提前发现问题,及时解决,防止软件上线后被不法分子攻击。由北京北大软件工程股份有限公司自主研制开发的库博静态代码分析工具可以在不运行软件代码的情况下,对代码中各类SQL注入问题进行自动化检测,发现问题,并提供解决方案,进一步保障企业和用户的数据安全。

相关文章:
Java 中 SQL 注入问题剖析
一、引言 在当今数字化时代,数据是企业和组织的核心资产之一。许多应用程序都依赖于数据库来存储和管理数据,而 Java 作为一种广泛使用的编程语言,常被用于开发与数据库交互的应用程序。然而,SQL 注入这一安全漏洞却如同隐藏在…...
华为数字芯片机考2025合集2已校正
单选 1. 题目内容 关于亚稳态的描述错误的是( )。 1. 解题步骤 1.1 理解亚稳态(Metastability)的核心特性 亚稳态是指触发器无法在指定时间内稳定输出有效逻辑电平(0或1)的状态,其关键特点…...
Leedcode刷题 | Day27_贪心算法01
一、学习任务 455.分发饼干代码随想录376. 摆动序列53. 最大子序和 二、具体题目 1.455分发饼干455. 分发饼干 - 力扣(LeetCode) 假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。 对…...
深度学习项目--分组卷积与ResNext网络实验探究(pytorch复现)
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 前言 ResNext是分组卷积的开始之作,这里本文将学习ResNext网络;本文复现了ResNext50神经网络,并用其进行了猴痘病分类实验…...
CSS 笔记——Flexbox(弹性盒布局)
目录 1. Flex 容器与 Flex 项目 2. 主轴与交叉轴 3. Flex 容器的属性 display flex-direction justify-content align-items align-content flex-wrap 4. Flex 项目的属性 flex-grow flex-shrink flex-basis flex align-self 5. Flexbox 的优点 6. Flexbox 的…...
[实战] linux驱动框架与驱动开发实战
linux驱动框架与驱动开发实战 Linux驱动框架与驱动开发实战一、Linux驱动框架概述1.1 Linux驱动的分类1.2 Linux驱动的基本框架 二、Linux驱动关键API详解2.1 模块相关API2.2 字符设备驱动API2.3 内存管理API2.4 中断处理API2.5 PCI设备驱动API 三、Xilinx XDMA驱动开发详解3.1…...
cpp(c++)win 10编译GDAL、PROJ、SQLite3、curl、libtiff
cpp(c)编译GDAL、PROJ、SQLite3 Sqlite3libtiffcurlprojGDAL Sqlite3 1、下载 Sqlite3 源码、工具、二进制预编译 exe Sqlite3 官网:https://www.sqlite.org/download.html 下载 sqlite-amalgamation-3430200.zipsqlite-dll-win64-x64-3430…...
每日一题(小白)暴力娱乐篇23
由题意得知给我们一串数字,我们每次交换两位,最少交换多少次成功得到有顺序的数组。我们以平常的思维去思考,加入给你一串数字获得最少的交换次数,意味着你的交换后续基本不会变,比如说2 1 3 5 4 中1与2交换后不变&…...
01-Redis-基础
1 redis诞生历程 redis的作者笔名叫做antirez,2008年的时候他做了一个记录网站访问情况的系统,比如每天有多少个用户,多少个页面被浏览,访客的IP、操作系统、浏览器、使用的搜索关键词等等(跟百度统计、CNZZ功能一样)。最开始存储…...
【从零开始学习JVM | 第一篇】快速认识JVM
什么是JVM? JVM--Java虚拟机,它是Java实现平台无关性的基石。 Java程序运行的时候,编译器将Java代码编译为平台无关的Java字节码文件(.class),接下来对应平台的JVM对字节码进行运行解释,翻译成…...
使用RabbitMQ实现异步秒杀
搭建RabbitMQ 在虚拟机上用docker搭建RabbitMQ,首先拉取镜像 docker run --privilegedtrue -d -p 5672:5672 -p 15672:15672 --name rabbitmq rabbitmq:management mkdir -p /usr/local/docker/rabbitmq再创建rabbitmq容器,下面的命令已经能够创建之后…...
Spring Boot 配置文件加载优先级全解析
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 Spring Boot 配置文件加载优先级全解析 Spring Boot 的配置文件加载机制是开发者管理不同环境配置的核心功能之一。其通过外部化配置(Externaliz…...
解决华硕主板Z890m下载ubuntu20.04后没有以太网问题
问题描述: 华硕主板Z890m下载双系统ubuntu20.04后,发现ubuntu不能打开以太网。 问题原因: 华硕主板的网卡驱动是r8125,而ubuntu20.04的驱动版本是r8169,所以是网卡驱动不匹配造成 解决方案 开机界面按下F2进入BOIS模式&#…...
xLua的Lua调用C#的2,3,4
使用Lua在Unity中创建游戏对象,组件: 相关代码如下: Lua --Lua实例化类 --C# Npc objnew Npc() --通过调用构造函数创建对象 local objCS.Npc() obj.HP100 print(obj.HP) local obj1CS.Npc("admin") print(obj1.Name)--表方法希…...
Debian系统_主板作为路由器_测试局域网设备间网速
Debian系统_主板作为路由器_测试局域网设备间网速 一、360软件测网速 360测出来的网速实际上是宽带的速度,并不是路由器LAN口到电脑这一段的网速 二、使用iperf3 进行双向带宽测试 1、开发板端下载软件 //Debian系统或者/Ubuntu sudo apt update && sudo…...
从 macos 切换到 windows 上安装的工具类软件
起因 用了很多年的macos, 已经习惯了macos上的操作, 期望能在windows上获得类似的体验, 于是花了一些时间来找windows上相对应的软件. 截图软件 snipaste windows和macos都有的软件, 截图非常好用 文件同步软件 oneDrive: 尝试了不同的同步软件, 还是微软在各…...
JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等,array.map()的使用详解(附实际应用代码)
目录 JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等,array.map()的使用详解(附实际应用代码) 一、什么时候该使用Array.map()࿰…...
去除Mysql表中的空格、回车、换行符和特殊字符
系列文章目录 文章目录 系列文章目录前言一、示例1.sql层面2.java层面 前言 一、示例 1.sql层面 参考 ## 例子1 ## CHAR(10) 表示换行符 ## CHAR(13) 表示回车UPDATE 表名 SET 列名 REPLACE(REPLACE(列名, CHAR(10), ), CHAR(13), )## 例子2 ## 删除字段中的空格、换行符、…...
P9242 [蓝桥杯 2023 省 B] 接龙数列
这道题说要求最少删多少个使剩下的序列是接龙序列,这个问题可以转换为序列中最长的接龙序列是多少,然后用总长度减去最长接龙序列的长度就可以了,在第一个暴力版本的代码中我用了两个for循环求出了所有的接龙序列的长度,但是会超时…...
macos下 ragflow二次开发环境搭建
参考官网链接 https://ragflow.io/docs/dev/launch_ragflow_from_source虚拟环境 git clone https://github.com/infiniflow/ragflow.git cd ragflow/ # if not pipx, please install it at first pip3 install pipxpipx install uv uv sync --python 3.10 --all-extras 安装 …...
SQL优化技术分享:从 321 秒到 0.2 秒的性能飞跃 —— 基于 PawSQL 的 TPCH 查询优化实战
在数据库性能优化领域,TPC-H 测试集是一个经典的基准测试工具,常用于评估数据库系统的查询性能。本文将基于 TPCH 测试集中的第 20个查询,结合 PawSQL 自动化优化工具,详细分析如何通过 SQL 重写和索引设计,将查询性能…...
密码学基础——DES算法
前面的密码学基础——密码学文章中介绍了密码学相关的概念,其中简要地对称密码体制(也叫单钥密码体制、秘密密钥体制)进行了解释,我们可以知道单钥体制的加密密钥和解密密钥相同,单钥密码分为流密码和分组密码。 流密码࿰…...
在 Linux 终端中轻松设置 Chromium 的 User-Agent:模拟手机模式与自定义浏览体验
在 Linux 系统中,通过终端灵活控制 Chromium 的行为可以大幅提升工作效率。本文将详细介绍如何通过命令行参数和环境变量自定义 Chromium 的 User-Agent,并结合手机模式模拟,实现更灵活的浏览体验。 为什么需要自定义 User-Agent?…...
ChatGPT 4:引领 AI 创作新时代
文章目录 前言一、ChatGPT 4 的技术革新二、AI 文案创作:精准生成与个性化定制三、AI 绘画艺术:从文字到图像的神奇转化四、AI 视频制作:自动化剪辑与创意实现五、知识库与 ChatGPT 4 的深度融合六、全新的变革和机遇七、相关书籍推荐《ChatG…...
http页面的加载过程
HTTP/2 核心概念 1.1 流(Stream) • 定义:HTTP/2 连接中的逻辑通道,用于传输数据,每个流有唯一标识符(Stream ID)。 • 特点: ◦ 支持多路复用(多个流并行传输&#…...
MySQL【8.0.41版】安装详细教程--无需手动配置环境
一、MySQL 介绍 1. 概述 MySQL 是一个开源的关系型数据库管理系统,由瑞典公司 MySQL AB 开发,现属于 Oracle 旗下。它基于 SQL(结构化查询语言)进行数据管理,支持多用户、多线程操作,广泛应用于 Web 应用、…...
鸿蒙ArkTS实战:从零打造智能表达式计算器(附状态管理+路由传参核心实现)
还在为组件状态混乱、页面跳转丢参数而头疼? 这篇博客将揭秘如何用鸿蒙ArkTS打造一个漂亮美观的智能计算器: ✅ 输入完整表达式,秒出结果——字符串切割简单计算 ✅ 状态管理黑科技——Provide/Consume 实现跨组件实时响应 ✅ 路由传参实战—…...
【58】编程技巧:单片机编程命名规范
【58】编程技巧:单片机编程命名规范 引言 在大型嵌入式项目开发中,变量和常量的命名混乱会导致代码难以维护。本文系统阐述变量、常量、指针、结构体等命名规范,通过统一规则提升代码可读性与协作效率。目标是帮助开发者建立清晰的命名习惯&…...
Windows 部署项目 apache + mod_wsgi,nginx + waitress
文章目录 1、apache mod_wsgi,nginx waitress两种部署方式的区别2、以nginx waitress为例 有些项目必须部署在windows上,有IIS wfastcgi、apache mod_wsgi,nginx waitress部署方式 1、apache mod_wsgi,nginx waitress两种…...
车辆视频检测器linux版对于密码中包含敏感字符的处理方法
由于密码中含有敏感字符,导致前端页面异常,图标变灰,坐标拾取打不开图像等,主要原因是:密码比较前后不一致,左边是Abc_110,右边是:Abc_110%2B,对于此问题,特别…...
