因为它不是在理解:
- SQL 方言
- 函数语义
- 语法树结构
- 数据库能力边界
它只是拿一段字符串做边界猜测。
所以这种设计最容易出现的情况就是:
text
你以为自己拦的是危险能力,
实际上你拦住的只是"某个单词长得像危险能力的写法"。
3.4 风险落点:文件读取能力
如果后端数据库支持对应文件读取函数,并且数据库账号权限没有收住,风险就可能进一步落到文件读取。
但这个地方也不能写飘。
是否能真正读到文件,至少还要看:
| 条件 | 影响 |
|---|---|
| 数据库类型 | 是否支持相应文件读取函数 |
| 账号权限 | 当前数据库账号是否具备相应能力 |
| 文件可读性 | 目标路径是否对数据库进程可读 |
| 接口可达性 | SQL 预览能力是否对当前用户开放 |
所以更稳妥的表达是:
这条链说明系统试图用关键字黑名单限制高危 SQL 能力,但边界规则本身存在缺口;在满足数据库能力和权限条件时,风险可以进一步落到文件读取。
3.5 修这类问题,别再只修正则
如果这里只是继续补黑名单,很大概率还会被别的写法绕过去。
更稳的方向是:
| 方向 | 建议 |
|---|---|
| 能力限制 | 针对具体数据库类型做能力级限制 |
| 权限最小化 | 预览 SQL 使用单独的低权限账号 |
| 白名单 | 能白名单就不要继续赌黑名单 |
| 结构化解析 | 能做 AST、模板化或结构化约束就不要只做字符串匹配 |
| 审计 | 对 SQL 预览、查询测试、导出等能力做单独高风险日志 |
4. 把两条链放在一起看
如果把这次记的两条链放在一起,其实就是两类典型后台风险:
第一类
text
上传 / 驱动 / 插件 / 模板
->
最终进入解释器、类加载器或执行链
第二类
text
校验看起来做了很多
->
但本质只是字符串黑名单
->
稍微换个写法就能从边上绕过去
这两类点在后台系统里都很常见,而且都特别容易被埋在"辅助能力"里:
- 测试连接
- SQL 预览
- 导入导出
- 驱动管理
- 模板预览
- 调试接口
名字都很日常,链路往下一跟,碰到的却是类加载、文件读取、命令执行、外联能力这些真正的安全边界。
5. 如果我是防守方,我会先翻什么
如果后面真要收这两个点,我会优先检查这些问题。
5.1 对 driver 这条线
- 上传的 jar 最终是不是直接进了可加载路径?
driver上传和普通数据源管理是不是混在一套权限里?testConnection是否在主应用上下文里直接完成类加载?- 是否存在 driver 上传、driver 变更、测试连接的单独审计日志?
- 历史上有没有异常 jar 上传或异常驱动变更?
5.2 对 SQL 预览这条线
- 现在是不是还在用关键字黑名单硬拦?
- 数据库类型是否做了分开能力限制?
- 预览 SQL 用的数据库账号是不是单独降权过?
- 文件读取、命令执行、外联这类能力是不是默认就在?
- 预览 / 测试 / 查询类接口有没有高风险审计?
很多时候,问题不在系统"看起来危险",而在这些地方根本长期没人翻。
6. 结论
这次先记两条:
- 一条是
driver上传最后接到了类加载边界 - 一条是 SQL 黑名单被函数名边界绕过去,风险能继续落到文件读取
我更想强调的,不是"哪一个点单独看起来很吓人",而是:
后台系统里很多真正危险的能力,并不挂在"执行命令"这种显眼名字上,而是挂在"测试连接""SQL预览""兼容更多数据库""方便管理员操作"这类日常功能里。
如果后面继续翻这类平台,我自己会持续优先看两件事:
- 外部对象最后会不会进入解释器、类加载器或执行链
- 安全校验到底是在理解能力边界,还是只是在做字符串猜测
这两类问题,往往比一个单点漏洞编号更能决定系统后面的真实风险。
备注
这篇记录不包含 weaponized 利用代码,也不对真实环境可利用性作过度结论。
如果团队正在使用类似后台平台,可以先做三件实事:
- 清点谁能上传 driver、谁能测试连接、谁能执行 SQL 预览
- 回看日志里是否有异常 jar 变更、异常连接测试、异常 SQL 预览
- 检查这类管理面能力是不是已经很久没有被单独做过安全审计