Skip to content
Kurisu
Go back

从指纹到 0day:反搜泄露源码的白盒审计工作流

认证前攻击面榨干、只剩登录态时,答案往往在源码里——国产二开系统的源码经常就躺在 GitHub 上。靠这套流程挖到过一个通用型 0day。

什么时候该转白盒

三条都中,别在黑盒上磨了。

Phase 0:指纹提取

第一步不是搜,是提取本地证据里的”独特串”(GitHub 搜约等于零才算独特)。五级:

级别类型举例(脱敏)
1自研 API 路径/api/folder/fwh/ 这种拼音缩写路径,别家不会有
2中英报错整句框架的中文报错原句,注意弯引号原样保留
3厂商/产品标识厂商名、SaaS 域名、客户子域模式
4技术栈组合框架+存储+服务器+响应封装格式
5chunk/组件命名webpack chunk hash、Vue 组件路径

从哪提:前端 bundle 正则抠 /api/...、报错堆栈包名、页面厂商标识(webpack bundle 一条正则抠全路由)。普通词(login、list、index)只作”星座组合”成员,多条 AND 并用。

Phase A:反搜与落地

反搜:独特串扔进 GitHub code search(带 text_matches 上下文)、Gitee、Sourcegraph 交叉;命中后至少 3 条指纹命中(单串 + 自定义响应封装 + 模型字段)才算同源。

批量落地:代理下 git clone 大仓库必断(fetch-pack early EOF),codeload 下 zip 也断,走 API:

  1. GET /repos/{owner}/{repo}/git/trees/{sha}?recursive=1 列出全文件清单
  2. raw.githubusercontent.com/{owner}/{repo}/{sha}/{path} 逐文件拉取

小文件走代理很稳(实测 127/127);ref 用 commit SHA。

版本锁定看部署配置:docker-compose 里的 jar 文件名给出基座版本(如 xxx-module-system-2.4.5.jar);接口行为 diff 也说明问题——仓库 POST 而部署只认 GET 则部署版更新,判定以线上为准。

Phase B:五路并行审计

源码到手后拆五路并行,每路一份独立报告:

  1. 鉴权矩阵:全 Controller 端点 × 鉴权注解 × anon 白名单对照
  2. SQLi 污点追踪:全部 Mapper XML 的 ${} 逐枚,Source→Sink 画链
  3. 文件链:上传白名单→落盘路径→webroot 可达→解析执行
  4. 业务逻辑:每个状态转移查三样(操作者身份/数据归属/状态前置)
  5. 基座与依赖:过滤链逐行读、pom 版本比对已知 CVE

拆路不为快,为的是每路有 checklist 和产出契约(证据必须 文件:行号、置信度分四级)。上一轮靠路 2 挖到框架自带接口的 SQLi。

Phase C:实例判定

白盒结论必须回线上实例判定——低频、只读、单发。JeecgBoot/Shiro 系这张响应矩阵直接判 anon 边界:

响应含义
参数校验错误 JSON(Required String parameter...)穿过过滤器到 Controller = anon 放行
500 + AuthenticationException: token为空被过滤器拦 = 不在 anon 清单
405 不支持GET请求方法到 handler = anon 放行(GET 打 POST 端点,零副作用判定法)
Tomcat 404无 handler,模块不存在
超时别急着判 WAF,拉长超时拿真实异常(可能是后端基建故障)

红线

小结

黑盒榨干之后,源码就是答案,而源码经常就在 GitHub 上。


Share this post:

Previous Post
安全知识工程:38 个仓库全量学习与笔记体系
Next Post
JeecgBoot 双防线 SQLi 绕过实战