SQL 注入系统学习(七):MySQL 高级边界与完整复盘
本文仅用于 CTF、靶场、本机实验和明确授权环境。文件写入、数据修改和高负载测试应限定在可恢复的专门环境中。
SQL 注入最终影响并不只由 Payload 决定。MySQL 版本、SQL mode、数据库驱动、账户权限、文件系统权限和应用反馈共同决定一条路线能否成立。
1. MySQL 文件读取
1 | LOAD_FILE('/path/to/file') |
能否读取通常取决于:
1 | 当前账户是否具备 FILE 权限 |
发现 SQL 注入并不等于能够读取任意文件。
2. 文件写出
1 | SELECT expression |
1 | SELECT expression |
区别:
1 | INTO OUTFILE 按字段和行格式输出 |
限制:
1 | FILE 权限 |
普通漏洞验证不应通过写入可执行文件证明影响。
3. secure_file_priv
1 | @@global.secure_file_priv |
常见状态:
1 | 指定目录 导入导出限制在该目录 |
如果没有直接回显,可依次判断:
1 | @@global.secure_file_priv IS NULL |
知道目录只满足一个条件,并不证明可读写。
4. LOAD DATA LOCAL 的边界
LOAD DATA LOCAL 中的文件位于客户端主机,而普通 LOAD DATA 的文件位于服务器主机。
在 Web 架构中:
1 | 浏览器 → Web 应用(MySQL 客户端)→ MySQL 服务器 |
此时 MySQL 所说的“客户端”是 Web 应用进程所在主机,不是浏览器用户的电脑。
风险是否成立取决于:
1 | 客户端库是否启用 LOCAL 能力 |
防御重点是默认关闭不需要的 LOCAL 能力、限制目录,并验证 MySQL 服务端身份。
5. SQL mode
5.1 ANSI_QUOTES
启用后双引号用于标识符,不能再简单当作字符串引号。
5.2 NO_BACKSLASH_ESCAPES
启用后,反斜杠不再作为字符串中的转义字符。
5.3 PIPES_AS_CONCAT
启用后,|| 可能从逻辑 OR 变为字符串拼接。
5.4 ONLY_FULL_GROUP_BY
影响聚合查询中非聚合列是否合法。旧教程中的某些 GROUP BY 写法在严格模式下会失败。
查看:
1 | SELECT @@sql_mode; |
6. MySQL、MariaDB 与版本差异
需要记录完整版本:
1 | SELECT VERSION(); |
版本差异可能影响:
1 | 函数是否存在 |
旧文章中的报错函数失效,不代表注入不存在,也可能只是版本不同。
7. 驱动差异
同一个 MySQL 后端,经由不同驱动可能表现不同:
1 | PHP mysqli |
需要检查:
1 | 是否使用服务端预处理 |
分析源码时,不能只看 SQL 字符串,也要看驱动调用方式。
8. 字符集与转义
风险受以下因素共同影响:
1 | 客户端输入编码 |
经典宽字节问题只在特定字符集与错误转义组合下成立,并非所有 MySQL 网站通用。
正确做法是使用真正的参数化查询,并明确设置连接字符集。
9. 参数化查询
数据值:
1 | $stmt = $conn->prepare( |
参数化适合:
1 | 字符串值 |
通常不能直接绑定:
1 | 表名 |
这些结构需要固定映射、安全查询构造器或白名单。
10. 最小权限
最小权限不能修复注入,但能降低后果:
1 | Web 应用使用独立账户 |
11. 错误与日志
生产页面不应显示:
1 | 完整 SQL |
详细错误应写入受保护的服务端日志,并进行访问控制和敏感信息脱敏。
12. 完整做题决策树
1 | 找到可控输入 |
13. 方法失败时
1 | 请求有没有到达应用? |
14. “函数不能用”的回答框架
1 | 1. 说明函数承担的能力 |
15. 源码审计清单
1 | [ ] 是否通过拼接或模板字符串构造 SQL |
16. CTF 复盘模板
1 | 题目与授权环境: |
17. 系列总结
真正需要记住的不是一条 Payload,而是:
1 | 输入在哪里? |
这七篇构成当前阶段的 MySQL SQL 注入知识骨架。后续遇到新的 CTF 题、函数限制或数据库差异,再把经过验证的内容补成单独文章。