了解SQL注入

简介: SQL注入是利用Web应用输入验证缺陷,将恶意SQL代码植入数据库查询的攻击方式。可导致身份绕过、数据泄露、篡改甚至系统沦陷。常见于登录框等动态SQL构造场景,攻击者通过特殊字符(如单引号、注释符)改变SQL逻辑。防御需结合输入验证、参数化查询及错误信息管控,从应用与网络层协同防护。

介绍
结构化查询语言 (SQL) 用于查询、操作和管理数据库系统,例如 Microsoft SQL Server、Oracle 或 MySQL。SQL 的一般用法在所有支持它的数据库系统中都是一致的;然而每个系统都有其特有的复杂性。
数据库系统通常用于为多种类型的 Web 应用程序提供后端功能。为了支持 Web 应用程序,用户提供的数据通常用于动态构建直接与数据库交互的 SQL 语句。SQL注入攻击是一种通过将攻击者提供的SQL语句直接提交到后端数据库来颠覆应用程序的初衷的攻击。根据 Web 应用程序以及它在构建 SQL 语句之前处理攻击者提供的数据的方式,成功的 SQL 注入攻击可能会产生深远的影响。可能的安全后果包括绕过身份验证、信息泄露以及向应用程序用户分发恶意代码。
SQL注入解释
SQL 注入攻击涉及通过使用攻击者提供的数据来更改 Web 应用程序中使用的 SQL 语句。Web 应用程序中输入验证不足和 SQL 语句构造不当可能会使它们遭受 SQL 注入攻击。SQL 注入是一种非常普遍且具有潜在破坏性的攻击,以至于 开放 Web 应用程序安全项目 (OWASP) 将其列为 Web 应用程序的头号威胁。
成功的 SQL 注入攻击的后果
尽管成功的 SQL 注入攻击的影响因目标应用程序以及该应用程序处理用户提供的数据的方式而异,但 SQL 注入通常可用于执行以下类型的攻击:
● 身份验证绕过: 此攻击允许攻击者在不提供有效用户名和密码的情况下,可能具有管理权限登录到应用程序。
● 信息泄露: 此攻击允许攻击者直接或间接获取数据库中的敏感信息。
● 数据完整性受损: 这种攻击涉及数据库内容的更改。攻击者可以使用此攻击来破坏网页,或更可能将恶意内容插入到其他无害的网页中。 该技术已通过SANS Internet Storm Center 的SQL 注入大规模攻击中描述的攻击得到证明 。
● 数据可用性受损: 此攻击允许攻击者删除信息,意图造成损害或删除数据库中的日志或审核信息。
● 远程命令执行: 通过数据库执行命令可能会让攻击者破坏主机操作系统。这些攻击通常利用现有的预定义存储过程来执行主机操作系统命令。这种攻击最常见的形式是使用 Microsoft SQL Server 安装中常见的 xp_cmdshell 存储过程,或者利用在 Oracle 数据库上创建外部过程调用的功能。
用于绕过身份验证的 SQL 注入示例
SQL 注入的多种可能用途之一涉及绕过应用程序登录过程。以下示例说明了 SQL 注入攻击的一般操作。以下 HTML 表单向应用程序用户请求登录信息。尽管此示例使用 HTTP POST 请求,但攻击者也可以使用使用 HTTP GET 方法的 HTML 表单。


用户名:<输入类型=文本名称=用户名>
密码:<输入类型=密码名称=密码>
<输入类型=提交值=登录>

当用户在此表单中输入信息并单击 “登录”时,浏览器会向 Web 服务器提交一个包含用户凭据的字符串。此字符串在 HTTP 或 HTTPS POST 请求的正文中显示为:
用户名=提交用户 & 密码=提交密码
具有易受攻击的登录过程的应用程序可能会接受提交的信息并将其用作以下 SQL 语句的一部分,该语句查找包含提交的用户名和密码的用户配置文件:
select from Users
where (用户名 = ' subscribedUser ' AND 密码 = 'subscribedPassword ');
除非应用程序使用严格的输入验证,否则它可能容易受到 SQL 注入攻击。例如,如果应用程序在没有任何验证的情况下接受并处理用户提供的数据,则攻击者可能会提交恶意制作的用户名和密码。考虑攻击者发送的以下字符串:
用户名=admin%27%29+--+&密码=+
一旦接收到该字符串并对其进行 URL 解码,应用程序将尝试使用用户名 admin') 以及由单个空格组成的密码来构建 SQL 语句。将这些项目放入前面的 SQL 语句中会产生:
select
from Users where (用户名 = ' admin ') -- 密码 = ' ');
正如前面的示例所示,攻击者制作的用户名会更改 SQL 语句的逻辑,以有效地删除密码检查。在上面的示例中,攻击者可以使用管理员帐户成功登录应用程序,而无需知道该帐户的密码。
精心设计的输入中出现的两个破折号字符 (--) 的字符串非常重要;它向数据库服务器指示 SQL 语句中的其余字符是注释,应被忽略。此功能是攻击者可以使用的最重要的工具之一,如果没有它,就很难确保恶意 SQL 语句在语法上正确。
尽管精心设计的字段(即上一个示例中的用户名字段)必须针对易受攻击的应用程序进行定制,但事实证明,Internet 上随时可用的大量记录字符串可以成功启用 SQL 注入攻击。前面的示例可能很简单,但它说明了 SQL 注入攻击技术的有效性。
盲注和二阶 SQL 注入
在后端 SQL 数据库的数据不直接返回给用户或攻击者的情况下,攻击者可能需要使用 SQL 盲注技术。通过这种技术,攻击者可以确定 SQL 语句是否是通过直接呈现数据以外的方式执行的。使用 SQL 盲注,攻击者可以执行侦察、获取敏感信息或更改数据库内容,包括身份验证凭据。
SQL 盲注技术的一个示例是在恶意 SQL 语句中引入延迟。根据所使用的数据库软件,攻击者可以构建旨在使数据库服务器执行耗时操作的 SQL 语句。使用 MySQL 数据库软件,可以使用以下命令编写 SQL 语句:sleep() 函数。例如,将 sleep(10)合并 到恶意查询中将产生 10 秒的延迟。 攻击者可以通过执行操作系统命令或耗时的子查询或尝试建立出站 HTTP 连接,在不包含 sleep()函数的数据库服务器上引起可识别的延迟。如果执行耗时的 SQL 语句,Web 应用程序的响应时间可能会比通常情况要长得多。此方法允许攻击者确定他们的 SQL 语句是否正在以某种程度的确定性执行。
二阶 SQL 注入攻击涉及用户提交的数据,这些数据首先存储在数据库中,然后检索并用作易受攻击的 SQL 语句的一部分。此类漏洞更难定位和利用,但二阶 SQL 注入攻击证明在应用程序中执行所有 SQL 语句以及综合使用参数化查询之前进行数据验证是合理的。
防御 SQL 注入攻击
SQL 注入攻击可以在应用程序流量中的两个位置被检测到并可能被阻止:应用程序中和网络中。
应用中的防御
应用程序可以通过多种方式防御 SQL 注入攻击。主要方法包括以白名单或黑名单的形式验证用户提供的数据,以及构建 SQL 语句以使用户提供的数据不会影响语句的逻辑。
黑名单和白名单
在应用程序本身中,有两种输入验证方法可以防御 SQL 注入攻击:黑名单和白名单。
通过黑名单,可以从用户输入中删除或替换特定的已知恶意字符。尽管这种方法经常被实施,主要是因为它很容易实现,但与白名单相比,它并不有效。黑名单可能无法正确处理复杂的混淆,这可能允许攻击者破坏过滤器并可能注入 SQL 语句。这种失败通常是由于不断发展的攻击技术和过滤器不全面或未正确实施而导致的。
或者,白名单根据允许的字符列表检查每条用户输入。这种方法可以更有效地降低 SQL 注入的风险,因为它对允许的输入类型有更多的限制。实施良好的白名单应根据预期的数据格式检查用户提供的每条数据。
无论采用哪种方法,很可能都需要根据输入字段类型或输入字段类别(例如文本或数字数据)来定制允许的字符。用于过滤 SQL 注入启用字符的输入验证和清理功能可能会被泛化并用于过滤表明跨站点脚本攻击的字符。有关跨站点脚本的更多信息,请参阅应用智能白皮书 了解跨站点脚本 (XSS) 威胁向量。
当应用程序从用户接收到无效字符时,它必须确定性地采取行动。根据处理意外数据的情况及其可能产生的影响,不同级别的响应可能是适当的。例如,应用程序应明确拒绝提交两个破折号字符 (--) 或分号字符 (;) 作为登录名或密码一部分的用户,并且应向应用程序管理员发送高严重性警报。然而,当应用程序收到单个撇号字符作为由输入包裹运输信息的经过身份验证的用户提交的街道地址的一部分时,这种有点严厉的响应可能不合适。尽管如此,应用程序应该按预期运行,
输入验证和清理的实现应包含警报功能。当收到意外输入时,此功能应向应用程序管理或开发团队发出警报,因为它可能表明过滤器可能错误地阻止了有效但意外的数据,或者应用程序可能受到攻击。无论哪种情况,都可能需要更改应用程序的过滤功能。
乍一看,这些数据验证和清理技术似乎可以在客户端 JavaScript 中实现,并在用户的浏览器中运行。然而,从安全角度来看,必须假设任何和所有类型的数据都将源自用户的浏览器,无论客户端施加的保护措施如何。尽管如此,客户端数据验证技术可以增强应用程序的可用性。
强化 SQL 语句
除了严格的输入验证之外,还应综合使用 ASP.NET 中的参数化查询、Java 中的准备语句或其他语言中的类似技术。在将 SQL 语句传递到底层数据库系统之前,每种技术都会执行所有必需的危险字符转义。
以下示例描述了 Java 中准备好的语句的使用,并说明了如何在没有用户提供的数据的情况下构建 SQL 语句,然后以无法更改 SQL 语句的结构和意图的方式使用数据进行扩充:

String sql = "select * from Users where (用户名 = ? 和密码 = ?)";

// 准备语句
prepareStmt = connection.prepareStatement(sql);
preparedStmt.setString(1, 提交的用户名);
preparedStmt.setString(2, 提交密码);

// 结果
preparedStmt.executeQuery();
请注意,准备好的陈述和类似技术并不是万能药;如果在没有绑定变量的情况下错误地使用它们,它们并不比传统构造的动态查询更安全。以下示例说明了 Java 中预准备语句的错误使用:
String sql = "select * from Users where (用户名 = '" + SubmittedUsername +
"' 和密码 = '" + SubmittedPassword + "')"; 准备语句prepareStmt = connection.prepareStatement(sql); 结果 = preparedStmt.executeQuery();
除了确保 SQL 语句的意图不会被用户提供的数据更改之外,应用程序还应该在 SQL 生成的错误消息到达最终用户之前捕获并删除它们。尽管这种保护措施可能会妨碍开发人员排除应用程序错误的能力(可以通过额外的后端日志记录轻松克服这种错误),但 SQL 错误的呈现将极大地帮助攻击者成功利用 SQL 注入漏洞。以下示例是一个过于冗长的错误消息:
com.mysql.jdbc.DBException。MySQL SyntaxErrorException:table“ sqlInjectionTest .test” doesn't exists
at com.mysql.jdbc.SQLError.createSQLException( SQLError.java:936 )
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2985)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3277)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3206)
at com.mysql.jdbc.Statement.executeQuery(Statement.java:1232)
at sqlInjectionBefore.main(before.java:28)
此错误消息表明应用程序正在使用 Java 编程语言和 MySQL 数据库平台,并且查询的数据库名为“sqlInjectionTest”。每条信息都可以帮助攻击者制作他们的应用程序输入,这增加了他们成功的几率。
网络防御
尽管理想情况下每个应用程序都应该提供自己的输入验证,但这种情况并不总是可能的。在某些情况下,无法更新应用程序以安全地处理用户提供的数据。在这些情况下,管理员和开发人员可以利用网络技术(特别是入侵防御系统)为现有应用程序添加安全性。
入侵防御系统签名
在某些情况下,可以使用入侵防御系统 (IPS) 来检测和防止 SQL 注入攻击。为了使 IPS 发挥作用,它必须能够了解应用程序的流量。对于使用 HTTPS 端到端加密的应用程序(例如,使用 HTTPS 且无需在中间网络设备终止或加速的应用程序),IPS 无法识别具有 SQL 注入攻击特征的流量。

相关文章
|
2月前
|
数据采集 人工智能 数据可视化
《基于 DeepSeek 百万token上下文的实证研究:全窗口真实工程压力测试与统计分析》
本项目基于 DeepSeek 于 2026 年 2 月推出的 “新长文本模型”(上下文窗口扩展至1,000,000 tokens,API 端仍保持 V3.2 版本),通过构建非AI/IT领域的完整项目流程,进行了全程、全负载实证工程测试。在单一连续上下文中实现了端到端的闭环。
|
3月前
|
人工智能 文字识别 物联网
ModelScope魔搭社区发布月报 -- 26年2月
临近年关,ModelScope迎来春节模型发布潮:Qwen3、GLM-4.7、MiniMax M2.1等大模型密集上新;AIGC生图、语音合成、具身智能全面突破;OpenAPI、OAuth、Gallery等生态基建同步升级,加速AI开源普惠。(239字)
717 7
|
5月前
|
存储 负载均衡 算法
负载均衡算法
本文介绍了多种负载均衡算法:随机、加权随机、轮询、加权轮询、最小活跃数、源地址哈希及一致性哈希。适用于不同场景,如性能均等或差异服务器、需保持会话一致等,提升系统稳定性与负载能力。
|
5月前
|
XML JSON Java
什么是RESTful
RESTful是一种基于资源的API设计规范,通过统一的HTTP方法(GET/POST/PUT/DELETE)对资源进行操作,提升接口的标准化与可维护性。它强调URI代表资源、使用名词而非动词、杜绝行为化路径,确保增删改查逻辑清晰、结构统一,便于理解和扩展,是现代Web API设计的最佳实践之一。
|
5月前
|
监控 Java 调度
定时任务概述
定时任务是基于时间表达式调度执行的任务,适用于对账、提醒、订单超时等场景。实现方式包括单体架构的轮询、Timer、ScheduledExecutorService、Quartz、SpringTask,以及分布式架构下的TBSchedule、Elastic-Job、XXL-JOB等方案,解决集群重复执行、动态调整、故障转移与监控问题。(238字)
|
3月前
|
存储 数据采集 人工智能
大模型微调常见术语解析:新手也能看懂的入门指南
本文通俗解析大模型微调核心术语:涵盖预训练模型、LoRA/QLoRA等轻量方法、学习率/批次大小等训练参数,以及过拟合、数据投毒等效果与安全要点,助新手快速入门并安全实践。(239字)
|
人工智能 自然语言处理 数据可视化
告别高成本定制:友盟U-AgentBox上线,开发者可一键集成行业模板,3天打造专属企业Agent
12月29日,蚂蚁百宝箱与友盟联合推出面向开发者的智能体产品U-AgentBox,聚焦低门槛、高效率集成专属智能体。通过模板化构建、可视化编辑与轻量级部署,助力开发者快速实现业务智能化升级。
417 0
告别高成本定制:友盟U-AgentBox上线,开发者可一键集成行业模板,3天打造专属企业Agent
|
5月前
|
SQL 存储 NoSQL
简述关系型与非关系型数据库的区别
关系型数据库基于表结构,支持SQL和事务,易于维护但读写性能差、灵活性不足;非关系型数据库格式灵活、速度快、成本低,适用于高并发场景,但缺乏SQL支持与事务机制,复杂查询较弱。
|
5月前
|
关系型数据库 应用服务中间件 Nacos
Nacos配置中心
本章介绍Nacos配置中心的实现,涵盖配置管理、热更新、共享配置及优先级规则,并演示Nacos集群搭建与高可用部署,帮助掌握微服务环境下配置统一管理的核心技能。
|
5月前
|
存储 关系型数据库 索引
聚簇索引及其优缺点
聚簇索引是一种数据存储方式,InnoDB通过主键构建B+树组织数据,叶子节点即数据页。若无主键,则选非空唯一索引或隐式创建主键。辅助索引(二级索引)需两次查找:先查主键值,再查数据行。优点是查询快,尤其主键排序与范围查询;缺点是插入依赖顺序,更新主键代价高,且易引发页分裂。

热门文章

最新文章