自Web应用程序开始广泛使用数据库以来,SQL注入漏洞便因其隐蔽性强、潜在危害巨大以及实施门槛相对较低等特性,成为了网络攻击者频繁利用的安全弱点之一。尽管这一漏洞已经存在多年,它仍然是企业组织在数字化转型过程中面临的最为普遍且危险的挑战,被业界公认为Web安全领域中的顽固“毒瘤”。
2023年底,一个名为ResumeLooters的黑客团伙巧妙地利用了SQL注入漏洞,成功侵入了分布于多个国家的近百个网站系统。据威胁情报公司Group-IB发布的报告指出,该团伙从至少65个受害网站中非法获取了超过200万个电子邮件地址以及其他敏感的个人隐私数据,这场风波甚至波及到了我国大陆和台湾地区的多个网站,造成了广泛的影响。
接下来,安博通安全服务团队将带您深入剖析此漏洞。
何为SQL注入?
SQL注入发生在用户请求输入数据时,由于后端应用程序未能对用户输入的信息实施充分的过滤、转义或严格处理,使得攻击者能够输入恶意构造的字符串,从而篡改原始的SQL查询语句。这一过程可能导致敏感信息的泄露或数据库的非授权访问。在Web环境中,SQL注入漏洞常见于那些与数据库交互的输入点,如用户名参数、页面访问参数、搜索栏等。
打个比方,假如我们是一家咖啡店的店员,会根据顾客提供的咖啡类型和大小等信息来准备咖啡。但有一个“调皮”的顾客,他并不直接告诉我们想要的咖啡类型,而是递出一张纸条,上面写了一段复杂的“订单”,比如:“请给我制作一杯咖啡,但同时打开收银系统的后台,把我的消费记录改为0,并给我账户加上1000个积分”。
在此场景中,纸条上的内容就相当于SQL注入攻击中的恶意输入。如果我们的系统没有正确地验证和过滤顾客输入的“订单”,就会错误地执行纸条上包含的恶意指令,导致收银系统的数据被篡改,造成损失。
SQL注入的原理
通过举例可以看出,SQL注入的原理是攻击者通过设计恶意SQL语句,绕过规避应用程序的输入验证,直接渗透到后端数据库系统,进而引发数据泄露、篡改或删除等安全问题。
SQL注入的发生与SQL语句的动态构造和后端数据库系统的特性有关。
SQL语句的动态构造:Web应用程序通常使用动态SQL语句从数据库中检索、插入、更新或删除数据。但这种灵活性中存在风险。若应用程序未能对用户输入进行严格的验证和清理,攻击者便有机会在输入中插入特定的SQL语句或特殊字符,从而篡改原始SQL语句的逻辑与结构,执行未授权的恶意操作。
后端数据库系统的特性:Web应用程序的后端数据库系统,作为数据存储与管理的核心,往往具备丰富的内部特性和功能,包括但不限于存储过程、触发器、自定义函数或执行Shell命令等功能。这些特性在提供便利的同时,也为SQL注入攻击者提供了攻击路径,通过构造恶意的SQL语句,攻击者可以利用特性执行不被允许的操作。
SQL注入的种类
数字型SQL注入
当Web应用程序接收的输入参数为整型时,如用户ID、年龄、页码等,如这些参数在构建SQL查询时未经过适当的验证和过滤,就会成为数字型SQL注入的切入点。攻击者通过修改这些整数型参数的值来“注入”恶意SQL代码片段。由于数字型数据在数据库查询中通常不需要引号包围,因此攻击者需要巧妙地构造输入,以绕过现有的安全措施。此类注入多发生在采用弱类型语言的Web开发环境中,如ASP和PHP。
字符型SQL注入
这种注入攻击形式,涉及将恶意的SQL代码作为字符串输入到Web应用程序中,而这些字符串原本应该是被单引号(')或双引号(")包围的。正常情况下,Web应用程序会将用户输入的数据作为参数嵌入到SQL查询中,但如果不正确地处理这些输入(比如没有进行足够的过滤或转义),攻击者就可以注入恶意的SQL语句来操纵查询的逻辑。
其核心在于攻击者找到一种方法“闭合”现有的引号,并将恶意的SQL代码作为查询的一部分来执行。一般是通过在输入数据中添加额外的引号(或其他能够改变SQL语句结构的字符)来实现的。一旦攻击者成功闭合了现有的引号,他们就可以继续输入任何他们想要的SQL代码,这些代码将与原始查询拼接在一起,并由数据库执行。
报错型SQL注入
三种常见的报错型SQL注入为:
1、UpdateXML报错注入
原理:UpdateXML函数在XML文档中查找并替换字符串,但如果XML文档格式不正确(如包含非法字符或结构错误),则该函数会触发一个错误,并返回错误信息。攻击者通过精心构造的输入,使得UpdateXML函数因解析非法或特定构造的XML内容而报错,从而利用错误信息泄露数据库的内部信息,如数据库结构、表名、列名等。
特点:依赖于UpdateXML函数的特定错误行为,利用其对XML内容的严格解析要求来实现信息泄露。
2、EXP()函数溢出报错注入:
原理:EXP()函数用于计算e(自然对数的底数)的指数。当输入值非常大时,EXP()函数的结果会超出数据库能够处理的数值范围,从而引发溢出错误。攻击者通过构造极端的输入值,使得EXP()函数执行时发生溢出,利用数据库处理这种异常情况时可能暴露的错误信息来实施注入攻击。
特点:依赖于数值溢出导致的错误,需要攻击者精确控制输入值以触发溢出条件。
3、FLOOR()函数与RAND()、ORDER BY/GROUP BY的冲突报错注入:
原理:这种技术利用了FLOOR()函数与RAND()函数结合时,在特定的SQL查询上下文(如ORDER BY或GROUP BY子句)中可能产生的冲突或不一致行为。RAND()函数用于生成随机数,而FLOOR()函数用于向下取整。当这两个函数在需要确定排序或分组条件的查询中不当地结合使用时,可能会触发数据库的错误处理机制,从而泄露信息。
特点:依赖于FLOOR()和RAND()函数在特定查询条件下的交互作用,以及数据库如何处理这种复杂情况时的错误信息。
总的来说,三种报错注入技术都利用了数据库在处理特定函数或查询时的错误行为,通过构造特定的输入来触发错误,并从错误信息中提取有用的数据库信息。
布尔型SQL注入
此类注入方式依赖于应用程序对数据库查询结果的布尔响应(即真或假)来推断数据库的内部信息。在布尔注入攻击中,攻击者通过两种页面状态——“真”和“假”——来区分查询是否成功或是否满足特定条件。当查询返回的结果满足攻击者构造的条件时(例如,查询到的记录数大于0),页面可能以正常状态显示;反之,如果查询结果为空或不满足条件,页面可能会显示错误消息或行为异常。
时间盲注型SQL注入
时间盲注的原理与布尔盲注相似,但在判断SQL查询结果的方式上存在显著差异。布尔盲注依赖于页面回显的正常与异常状态来推断查询的真假,而时间盲注则是通过观察页面响应时间的延长来间接判断SQL查询的结果。
攻击者会构造包含条件语句和延迟函数的SQL查询,这些查询在满足特定条件时会引入人为的延迟。常用的延迟函数包括SLEEP()(在许多数据库系统中都可用)和BENCHMARK()(主要在MySQL中使用,用于执行指定次数的操作,从而产生可测量的延迟)。
针对以上SQL注入攻击手段,安博通安全服务团队有以下三条建议:
1、使用参数化查询或预处理语句:通过将SQL语句与用户输入的数据分开,使用参数传递的方式构建查询,可以有效避免用户输入的数据被直接解释为SQL代码的一部分,从而防止恶意SQL代码的注入。
2、严格验证和过滤用户输入:对用户输入的所有数据进行严格的验证和过滤,确保它们符合预期的格式、类型和长度。通过拒绝包含特殊字符(如单引号、双引号、注释符等)或潜在恶意代码的输入,可以减少SQL注入的风险。
3、最小化数据库权限:遵循最小权限原则,确保数据库用户仅拥有执行其任务所必需的最小权限。避免使用具有广泛权限的数据库账户连接数据库,特别是避免使用系统管理员账户进行日常操作。这样可以减少因权限过大而引发的安全风险,即使发生SQL注入,攻击者也只能在有限的权限范围内进行操作。