了解SQL注入

简介: SQL注入是一种常见且危险的Web安全漏洞,攻击者通过构造恶意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 表单。

<form action="/cgi-bin/login" method=post>  
  用户名:<输入类型=文本名称=用户名>  
  密码:<输入类型=密码名称=密码> 
<输入类型=提交值=登录>

当用户在此表单中输入信息并单击 “登录”时,浏览器会向 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 注入攻击特征的流量。

相关文章
|
11天前
|
安全 算法 网络协议
从明文到加密:HTTP与HTTPS核心知识全解析
本文深入解析HTTP与HTTPS的核心差异,揭示HTTPS如何通过SSL/TLS协议、CA证书和混合加密机制,解决HTTP的窃听、篡改与冒充三大安全问题,全面科普网络安全关键技术。
375 6
|
7天前
|
存储 弹性计算 安全
2026年阿里云便宜云服务器38元、99元、199元购买条件、各自性能优势与适用场景介绍
在阿里云2026年的活动中,推出了多款价格亲民的云服务器产品。轻量应用云服务器2核2G200M带宽 40G ESSD云盘 38元1年,经济型e实例2核2G3M带宽 40G ESSD Entry云盘特惠价99元1年,通用算力型u1实例2核4G5M带宽80G ESSD Entry云盘特惠价199元1年。本文将为大家介绍这三款热门低价云服务器的购买条件、性能优势与适用场景,以供用户了解他们之间的性能、使用场景区别及选择参考。
143 8
|
26天前
|
消息中间件 运维 监控
告警一响三小时:这单到底该谁接?
告警一响三小时:这单到底该谁接?
84 7
|
弹性计算 Ubuntu 网络安全
借助阿里云ECS实现本地电脑连接实验室内网服务器
在实验室的服务器上进行开发,往往只能通过内网电脑进行ssh连接。然而疫情当下,很多时候都要居家办公,或远程办公。借助阿里云ECS,我们可以搭建一个FRP服务,实现内网穿透,在家里的电脑也可以ssh连接内网服务器。
1776 1
借助阿里云ECS实现本地电脑连接实验室内网服务器
|
安全 Shell Linux
2022渗透测试-一次完整的渗透测试(DC-6靶场)
2022渗透测试-一次完整的渗透测试(DC-6靶场)
2022渗透测试-一次完整的渗透测试(DC-6靶场)
|
26天前
|
机器学习/深度学习 自然语言处理 机器人
阿里云百炼大模型赋能|打造企业级电话智能体与智能呼叫中心完整方案
畅信达基于阿里云百炼大模型推出MVB2000V5智能呼叫中心方案,融合LLM与MRCP+WebSocket技术,实现语音识别率超95%、低延迟交互。通过电话智能体与座席助手协同,自动化处理80%咨询,降本增效显著,适配金融、电商、医疗等多行业场景。
473 155
|
20天前
|
安全 Java 数据安全/隐私保护
2.OAuth2.0实战案例
本文介绍基于Spring Boot与Spring Cloud构建OAuth2授权服务的完整流程,涵盖父工程搭建、资源服务器与授权服务器配置,以及授权码、简化、密码和客户端四种模式的测试验证,实现安全的分布式权限管理。
 2.OAuth2.0实战案例
|
24天前
|
存储 弹性计算 安全
阿里云第九代云服务器g9a实例介绍,可适用于Web、数据库系统、区块链等相关应用
目前,阿里云第九代云服务器ECS g9a实例已正式商业化,且开启了首次活动,g9a实例基于阿里云自研 CIPU 架构,搭配 AMD Turin Classic 处理器,最高睿频 4.1 GHz;是专为数据库、区块链、金融量化以及其他对 CPU 高主频有要求的场景而打造的企业级实例产品。本文对g9a实例做个介绍。
114 3
阿里云第九代云服务器g9a实例介绍,可适用于Web、数据库系统、区块链等相关应用
|
19天前
|
机器学习/深度学习 人工智能 自然语言处理
AI群策群力术:让多个大模型一起干活不摸鱼
想让AI回答更准确?别指望一个模型包打天下!就像做菜找多个大厨试味,提示词集成(Prompting Ensembling)让多个提示词协同作战,通过民主投票选出最佳答案。从自一致性(Self-Consistency)到多样化推理(DiVeRSe),掌握这些技巧让你的AI应用准确率飙升!#人工智能 #提示词工程 #机器学习 #AI优化
145 3
|
19天前
|
人工智能 JSON 数据挖掘
大模型应用开发中MCP与Function Call的关系与区别
MCP与Function Call是大模型应用的两大关键技术。前者是跨模型的标准协议,实现多工具动态集成;后者是模型调用外部功能的机制。MCP构建通用连接桥梁,支持跨平台、热插拔与细粒度管控,适用于复杂企业场景;Function Call则轻量直接,适合单模型快速开发。二者可协同工作:模型通过Function Call解析意图,转为MCP标准请求调用工具,兼顾灵活性与扩展性。未来将趋向融合,形成“解析-传输-执行”分层架构,推动AI应用标准化发展。