type
status
date
slug
summary
tags
category
icon
password
SQL 注入(SQL Injection,SQLi)是一种利用 Web 应用程序中输入验证漏洞的攻击方法。攻击者通过在输入字段(如登录框、搜索栏或 URL 参数)中构造恶意 SQL 语句,导致应用程序生成意外的 SQL 查询,从而获得非授权访问数据库的权限,进而获取敏感数据、篡改数据或破坏数据库。
SQL 注入攻击类型多样,常见类型及其攻击原理、检测方法和防御措施如下:
1. SQL 注入的基本原理
SQL 注入攻击通过篡改应用程序原本预期的 SQL 查询,将恶意代码注入到数据库操作中。例如,在身份验证场景中,典型的 SQL 查询为:
攻击者可以输入
username
为 admin' --
,将 password
留空。此时查询将被更改为:由于
--
为注释符,password
条件被忽略,SQL 查询实际上变为:从而绕过了身份验证,直接登录
admin
账户。2. 常见的 SQL 注入类型
2.1 基于联合(Union-based)注入
目的:通过
UNION
操作符将两个或多个查询结果合并,强制返回额外的数据。- 攻击示例:
' UNION SELECT null, user(), database(), version() --
- 此注入通过联合查询,返回数据库当前用户(
user()
)、数据库名称(database()
)和版本(version()
)。
- 适用场景:适用于有可见查询结果的页面(如搜索结果页面)。
2.2 基于错误(Error-based)注入
目的:利用 SQL 错误信息获取数据库结构和内容。
- 攻击示例:
' AND 1=1; DROP TABLE users; --
- 此语句通过添加错误操作(如删除表),引发 SQL 错误,从而在错误提示信息中暴露数据库细节。
- 适用场景:适用于返回详细 SQL 错误信息的页面。
- 例子:假设一个简单的登录验证查询语句是SELECT * FROM users WHERE username = '$input_username' AND password = '$input_password',攻击者在$input_username字段输入admin' AND 1 = 1;--(这里的;--用于注释掉原查询语句中后面可能存在的部分)。如果应用程序没有对输入进行安全处理,数据库可能会执行SELECT * FROM users WHERE username = 'admin' AND 1 = 1;--' AND password = '$input_password',由于AND 1 = 1恒为真,数据库可能会返回admin用户的信息,而不管密码是否正确,这就初步验证了可能存在注入点。
2.3 基于布尔(Boolean-based)盲注
目的:在无回显结果的情况下,通过判断查询的布尔值,逐步提取数据。
- 攻击示例:
' AND 1=1--
和' AND 1=0--
- 攻击者可以使用判断条件,例如
1=1
和1=0
,观察响应差异。例如,通过构造判断条件username='admin' AND SUBSTRING(password,1,1)='a'--
逐字符获取密码。
- 适用场景:适用于无回显的页面,如密码验证页面。
2.4 基于时间(Time-based)盲注
目的:通过注入 SQL 函数(如
SLEEP()
),利用页面响应延迟判断查询条件。- 攻击示例:
' AND IF(1=1, SLEEP(5), 0)--
- 如果条件为真(如
1=1
),SQL 语句延迟执行 5 秒,攻击者可以通过响应时间判断条件是否成立。
- 适用场景:适用于无可见回显且不显示错误的页面。
- 例子:
目标网站有一个登录页面,用户输入用户名和密码后,后台通过SQL查询验证用户身份。假设后端执行的查询语句大致形式为:
SELECT * FROM users WHERE username = '$input_username' AND password = '$input_password'
,这里$input_username
和$input_password
是用户在登录页面输入的内容,并且该网站存在SQL注入漏洞,即没有对用户输入进行充分的安全处理,允许恶意构造的SQL语句部分混入到正常查询中。 同时,该登录页面在验证用户输入后,无论登录成功与否,都不会显示任何错误提示信息,也不会返回任何与数据库查询结果相关的可见回显,只是简单地显示一个通用的“登录中,请稍等”的提示信息,直到验证完成后根据结果显示“登录成功”或“登录失败”。这种情况就非常适合基于时间的盲注攻击。
攻击过程示例
第一步:确定注入点
攻击者首先尝试在用户名输入框输入一个简单的测试语句,比如
admin' AND 1=1;--
,密码框随意输入内容。如果提交后,页面显示“登录中,请稍等”的时间与正常登录时差不多,说明可能存在注入点,因为添加的AND 1=1
这个恒为真的条件没有导致查询出错。然后再输入admin' AND 1=0;--
,密码框同样随意输入内容,如果这次显示“登录中,请稍等”的时间明显比正常登录时短(因为AND 1=0
条件为假,可能导致查询很快返回结果),那么就进一步确认了存在注入点。第二步:获取密码长度(示例)
- 假设数据库是MySQL,攻击者开始通过基于时间的盲注来获取
admin
用户的密码长度。
- 构造如下注入语句系列,从密码长度可能的最小值(比如假设密码最短为1个字符)开始尝试:
- 输入用户名:
admin' AND IF((SELECT LENGTH(password) FROM users WHERE username = 'admin') = 1, SLEEP(5), 0);--
- 这里的
IF
函数是SQL中的条件判断函数,它会根据第一个条件表达式的值来决定执行第二个表达式还是第三个表达式。在这个语句中,(SELECT LENGTH(password) FROM users WHERE username = 'admin') = 1
是在判断admin
用户的密码长度是否等于1。如果这个条件为真,那么就会执行SLEEP(5)
,导致整个查询语句延迟执行5秒;如果这个条件为假,就会执行0
,查询语句会正常快速执行。 - 密码框随意输入内容,然后提交登录请求。
- 如果提交后,页面显示“登录中,请稍等”的提示信息持续了大约5秒,那么就说明
admin
用户的密码长度是1个字符。 - 如果没有延迟,说明密码长度不是1个字符,接下来就继续尝试:
- 输入用户名:
admin' AND IF((SELECT LENGTH(password) FROM users WHERE username = 'admin') = 2, SLEEP(5), 0);--
- 按照同样的流程进行测试,不断增加猜测的密码长度值,直到发现页面出现5秒延迟,此时就确定了
admin
用户的密码长度。
第三步:进一步获取密码字符(可扩展步骤)
- 在确定了密码长度之后,攻击者可以进一步通过基于时间的盲注来获取密码的具体字符。
- 例如,已经确定
admin
用户的密码长度为5个字符,现在要获取第一个字符。
- 构造如下注入语句系列:
- 输入用户名:
admin' AND IF((SELECT SUBSTRING(password, 1, 1) FROM users WHERE username = 'admin') = 'a', SLEEP(5), 0);--
- 这里的
SUBSTRING(password, 1, 1)
是在获取admin
用户密码的第一个字符,然后通过IF
函数判断这个字符是否等于'a'
,如果等于就执行SLEEP(5)
,否则执行0
。 - 密码框随意输入内容,然后提交登录请求。
- 如果页面显示“登录中,请稍等”的提示信息持续了大约5秒,那么就说明
admin
用户的密码的第一个字符是'a'
。
- 如果没有延迟,说明不是
'a'
,接下来就继续尝试不同的字符,如'b'
、'c'
等,按照同样的流程,依次获取密码的其他字符,直到获取完整的密码字符串。
通过这样一系列基于时间的盲注操作,攻击者可以在无可见回显且不显示错误的页面情况下,逐步获取到数据库中的敏感信息,如用户的密码等。不过需要注意的是,这种攻击方式相对比较耗时,尤其是在获取较长的密码或其他复杂信息时。
3. SQL 注入检测方法
SQL 注入的检测方法包括:
- 手动检测:通过输入常见的 SQL 注入符号(如
‘ OR 1=1--
),观察页面是否返回预期之外的结果。
- 自动化扫描工具:使用工具如 SQLMap、Burp Suite 等,扫描 Web 应用中的 SQL 注入漏洞。
- 代码审查:通过代码分析,检查用户输入的拼接位置,特别是字符串拼接到 SQL 查询的地方。
4. 案例分析
假设存在一个用户登录页面,通过以下查询验证用户身份:
攻击者输入
username
为 admin' --
时,将导致 SQL 查询被注释掉一部分,系统直接返回 admin
用户的记录。如果使用参数化查询或预编译语句,查询语句如下:
无论攻击者输入如何恶意构造,
username
和 password
只能被视为普通参数,不会影响 SQL 语句结构,确保了系统的安全性。总结
SQL 注入是一种具有极高危害性的攻击方式,掌握不同类型 SQL 注入的工作原理及防御措施至关重要。通过严格的输入验证、参数化查询、最小化权限和使用 WAF,可以有效防止 SQL 注入攻击,保障系统数据安全。
- Author:Gweek
- URL:https://www.myla.eu.org/article/sql-zr
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!