【基础篇】什么是SQL注入,如何防止?

ops/2025/1/22 17:18:53/

什么是 SQL 注入,如何防止?

SQL 注入(SQL Injection)是一种常见的网络安全漏洞,它发生在 Web 应用程序中,当恶意用户在输入数据时,将恶意的 SQL 代码插入到输入中,从而导致应用程序执行非预期的 SQL 查询。

攻击者通过 SQL 注入可以访问、修改或删除数据库中的数据,甚至完全控制数据库

SQL 注入的原因是:未经适当验证和处理的用户输入被直接拼接到 SQL 查询语句中,使得攻击者可以修改 SQL 查询的逻辑。例如,一个简单的登录查询可能是这样的:

sql">SELECT * FROM users WHERE username = '输入的用户名' AND password = '输入的密码';

如果应用程序未对用户输入进行适当的验证和处理,攻击者可以输入以下内容:

输入的用户名: ' OR '1'='1
输入的密码: ' OR '1'='1

那么构造出的 SQL 查询就变成了:

sql">SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '' OR '1'='1';

由于 '1'='1' 始终为真,上述查询将返回数据库中所有用户的信息,绕过了正常的身份验证。

为了防止 SQL 注入攻击,应该采取以下措施:

  1. 使用参数化查询(Prepared Statements): 参数化查询是一种预编译 SQL 语句,参数值与 SQL 语句分开,不会将用户输入直接拼接到 SQL 语句中,从而避免了 SQL 注入的风险。

    // 使用PreparedStatement预编译SQL查询语句,避免SQL注入的风险
    String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
    // 创建PreparedStatement对象,并将SQL语句传入
    PreparedStatement pstmt = connection.prepareStatement(sql);// 设置参数值,参数索引从1开始
    // 将用户输入的用户名设置到第一个参数位置(索引1)
    pstmt.setString(1, userInputUsername);
    // 将用户输入的密码设置到第二个参数位置(索引2)
    pstmt.setString(2, userInputPassword);// 执行查询,并将查询结果保存到ResultSet对象中
    ResultSet resultSet = pstmt.executeQuery();
    

    结果:

    sql">SELECT * FROM users WHERE username = '\' OR \'1\'=\'1\'' AND password = '\' OR \'1\'=\'1\'';
    

    ' OR '1'='1' 被当作字符串值,将 ' 转义为 \'

  2. 使用 ORM 框架: 对象关系映射(ORM)框架如 Hibernate、MyBatis 等,可以自动处理 SQL 查询,避免手动拼接 SQL 语句,从而减少了 SQL 注入的可能性。

    <!-- 示例:MyBatis映射配置文件 -->
    <!-- 在MyBatis的映射配置文件中,通过使用#{}语法来进行参数化查询,MyBatis会自动对参数值进行转义,以防止SQL注入。 -->
    <select id="getUserByUsernameAndPassword" resultType="User">SELECT * FROM users WHERE username = #{username} AND password = #{password}
    </select>
    

    在这个查询中,' OR '1'='1' 被当作字符串值,而不是 SQL 代码。

    输入

    输入的用户名: ' OR '1'='1
    输入的密码: ' OR '1'='1
    

    最终 sql 语句会变为:

    sql">SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '' OR '1'='1';
    
  3. 输入验证和过滤: 对于用户输入,要进行验证和过滤,确保只有合法的数据被用于数据库查询。

  4. 最小权限原则: 数据库用户应该具有最小的权限来执行必要的操作,这样即使发生 SQL 注入,攻击者也无法进行敏感的操作。

    sql">-- 示例:数据库用户只有查询权限,没有更新和删除权限
    GRANT SELECT ON users TO read_only_user;
    
  5. 错误处理: 在应用程序中不要直接返回数据库错误信息给用户,以免攻击者获得有关数据库结构的敏感信息。

  6. 定期更新和维护: 定期更新和维护数据库和应用程序,确保已知的漏洞得到修复。

何为预编译?

预编译(Prepared Statements)是一种数据库查询优化技术,在执行SQL查询之前,数据库管理系统会将SQL查询语句预先编译成一种内部表示形式,然后将参数值与预编译的查询计划进行绑定。


http://www.ppmy.cn/ops/152241.html

相关文章

C++ 中的最大值和最小值判断

1. 使用 std::numeric_limits<T>::max() 和 std::numeric_limits<T>::min() std::numeric_limits 是 C 标准库中的模板类&#xff0c;用于获取各种数据类型的最大值和最小值。它提供了一种通用的方式&#xff0c;适用于所有标准数据类型&#xff08;如 int、long、…

网创资源采集插件自动采集更新网站

现在的资源站越来越多人们对资源的需求也是越来越大但是对站长们来说对对资源的争议是比较耗时的比如大家想开一个网状的资源整合站又比较困难大家需要投入很多的人工经历但是我们如果使用插件自动化的采集发布实验全自动交易是一件非常理想的事情利用插件我们可以实现这一目的…

【算法笔记】力扣热题100(LeetCode hot-100)560. 和为 K 的子数组

力扣热题100&#xff08;LeetCode hot-100&#xff09;之 560. 和为 K 的子数组 本文主要记录算法思路&#xff0c;着急要答案的同学可以直接跳转到最后的代码。 题目 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。子数…

社区版Dify实现文生视频 LLM+ComfyUI+混元视频

社区版Dify实现文生视频 LLMComfyUI混元视频 一、 社区版Dify实现私有化混元视频效果二、为什么社区版Dify可以在对话框实现文生视频&#xff1f;LLMComfyUI混元视频 实现流程图&#xff08;重点&#xff09;1. 文生视频模型支持ComfyUI2. ComfyUI可以轻松导出API实现封装3. Di…

1.2.神经网络基础

目录 1.2.神经网络基础 1.2.1.Logistic回归 1.2.2 梯度下降算法 1.2.3 导数 1.2.4 向量化编程 1.2.5 正向传播与反向传播 1.2.6.练习 1.2.神经网络基础 1.2.1.Logistic回归 1.2.1.1.Logistic回归 逻辑回归是一个主要用于二分分类类的算法。那么逻辑回归是给定一个x ,…

金融波动率的多模型建模研究:GARCH族与HAR模型的Python实现与对比分析

金融资产波动率建模在现代金融工程中具有重要地位&#xff0c;其应用涵盖风险管理、衍生品定价和投资组合优化等核心领域。本文着重探讨三种主流波动率建模方法&#xff1a;广义自回归条件异方差模型(GARCH)、Glosten-Jagannathan-Runkle-GARCH模型(GJR-GARCH)以及异质自回归模…

mysql的mvcc

快速搞懂mvcc 全称 multi-version concurrency control 多版本并发控制。自动开启事务undo log读视图(read_view)结果过滤mvcc只在读已提交和可重复读隔离级别下运作读已提交隔离级别下&#xff0c;可重复读隔离级别下&#xff0c;总的来说mvcc是为了提高数据库并发性能而设计的…

springboot 配置多数据源以及动态切换数据源

场景 我们springboot项目&#xff0c;通常会有多个数据库&#xff0c;例如mysql,vertica,postgresql等等数据库&#xff0c;通常我们需要动态切换使用我们想要的数据库&#xff0c;这时候就需要配置多数据源了 多数据源特性 支持多数据库类型&#xff1a;例如&#xff0c;同…