背景
SRC 挖洞的流程里,真正”动手打”的时间其实只占一小部分,大头全耗在信息收集上。以一次常规授权测试为例,标准套路是四步:
- 子域枚举 — 先拿到目标根域下的所有子域,挨个确认哪些还活着
- 资产测绘 — 用 FOFA / Hunter 这类测绘平台把存活资产捞一遍,看开放了哪些端口、跑了什么服务
- 指纹识别 — 判断每个资产是什么框架(ThinkPHP、Shiro、Spring 全家桶……),决定后面打什么
- 敏感路径探测 — 对重点资产扫
.git、.env、swagger、actuator 这类敏感路径
手动做这套流程,四步来回切工具、复制粘贴结果、手工整理去重,一次下来 2 小时起步。而且每一步都高度重复——换个目标,流程一模一样。
于是我用 Python 写了一个信息收集自动化工具 src-recon-tool,把这条流水线固化下来:一次命令跑完四步,单次全流程压缩到 30 分钟以内。
架构设计
工具入口是一个 recon.py CLI,按子命令组织四个核心模块,外加一个 YAML POC 模板引擎和可选的 LLM 辅助:
target → recon.py → subdomain / asset / fingerprint / paths → out/<target>/
↓
poc_engine(YAML 模板)
↓
llm_assist(总结报告)
几个关键设计决策:
- 模块化 + 可单独调用:每个模块都是独立子命令,既能
all一把梭,也能只跑其中一步,方便调试和复用 - 无 key 自动降级:这是整个工具最实用的设计——没有 FOFA/Hunter/LLM 的 key 时,相关模块自动降级或跳过,流水线永远能跑通
- 输出统一落盘:所有结果都写到
out/<target>/目录,去重、合并、归档一步到位 - 模板化 POC:不把检测逻辑写死在代码里,而是做成 nuclei 风格的 YAML 模板,加检测点只改 YAML
子域枚举模块
子域枚举首选接入 OneForAll,它的数据源多(证书透明日志、DNS 爬虫、搜索引擎、测绘平台聚合),覆盖面比单一数据源好很多。OneForAll 是独立部署的,通过环境变量 ONEFORALL_HOME 指定它的安装路径即可。
但 OneForAll 部署需要 Python 环境和一堆依赖,不是每台机器都方便。所以做了降级设计:没配置 OneForAll 时,自动改用 crt.sh 证书透明日志查询——https://crt.sh/?q=%25.example.com&output=json 这个接口不需要任何 key,直接拉 JSON 解析出子域列表。覆盖面差一些,但胜在零依赖、开箱即用。
python src/recon.py subdomain -d example.com
输出示例:
[+] 子域枚举完成: example.com
共发现 128 个子域(OneForAll: 96 / crt.sh: 89 / 去重后: 128)
结果已保存: out/example.com/subdomains.txt
资产测绘模块
拿到子域列表后,下一步是把它们映射成实际资产——IP、端口、服务。这里接了两家测绘平台:
- FOFA:
https://fofa.info/api/v1/search/all,需要FOFA_EMAIL+FOFA_KEY - Hunter:
https://hunter.qianxin.com/openApi/search,需要HUNTER_KEY
key 一律走环境变量管理,不写进代码、不进 git。Windows 上可以用 setx 持久化:
export FOFA_EMAIL=xxx FOFA_KEY=xxx HUNTER_KEY=xxx # Linux / macOS
setx FOFA_EMAIL xxx && setx FOFA_KEY xxx # Windows
核心逻辑是拼查询语句、翻页拉取、字段清洗:
def query_fofa(domain: str) -> list[dict]:
q = f'domain="{domain}"'
# FOFA API v1: /api/v1/search/all?email=&key=&qbase64=&size=&fields=
params = {
"email": os.environ["FOFA_EMAIL"],
"key": os.environ["FOFA_KEY"],
"qbase64": base64.b64encode(q.encode()).decode(),
"size": 100,
"fields": "host,ip,port,protocol,title,server",
}
resp = requests.get("https://fofa.info/api/v1/search/all", params=params, timeout=30)
resp.raise_for_status()
return resp.json().get("results", [])
注意 FOFA 免费账号有查询积分限制,翻页太狠会被限流,所以加了超时和错误重试,单源失败不影响其他源。没有配置 key 时这个模块直接跳过,并在日志里提示。
指纹识别与敏感路径
指纹识别不依赖外部指纹库,内置了一批常用规则,覆盖 ThinkPHP、Shiro、Spring、WordPress、Nginx 等常见目标。每条规则是”特征 → 指纹名”的映射,检测时走 headers + body 双通道:
- headers:
X-Powered-By、Server、Set-Cookie(比如 Shiro 的rememberMe=deleteMe) - body:页面里特定的 meta、JS 路径、报错特征(比如 ThinkPHP 报错页的
ThinkPHP字样)
FINGERPRINTS = [
{"name": "Shiro", "headers": ["rememberMe=deleteMe"]},
{"name": "ThinkPHP", "body": ["ThinkPHP", "tp5"]},
{"name": "Spring", "headers": ["X-Application-Context"], "body": ["Whitelabel Error Page"]},
{"name": "Nginx", "headers": ["nginx"]},
{"name": "WordPress", "body": ["wp-content", "wp-includes"]},
# ...
]
敏感路径探测内置了一个路径字典,对重点资产逐个探测:
python src/recon.py paths -u https://example.com
字典里是些”看到就该警惕”的路径:
/.git/config
/.env
/swagger-ui.html
/actuator
/druid/index.html
/actuator/env
/actuator/heapdump
探测逻辑很简单——发 GET 请求,状态码 200 且 body 长度符合预期就算命中,写入 out/<target>/sensitive_paths.txt,作为后续人工测试的候选清单。
YAML POC 模板引擎
指纹识别之后,很多检测动作是固定的:知道是 Shiro 就测 rememberMe 反序列化,知道是 Spring 就测 actuator 泄露。这类”固定检测点”写死在 Python 代码里很笨重——加一个检测点就得改代码、跑测试、发版。
所以做了个 nuclei 风格的 YAML POC 模板引擎:检测逻辑全部外置成模板文件,放到 pocs/ 目录,加检测点只加一个 YAML。引擎实现了 nuclei 模板的一个子集:info 元信息、requests 请求定义、status / contains 两类 matcher、and / or 条件组合。
id: example-admin-detect
info:
name: Admin Panel Detect
severity: info
requests:
- method: GET
path: "/admin"
matchers:
- type: status
status: [200, 401, 403]
这个模板的意思是:对目标发 GET /admin,如果返回 200/401/403 任意一个状态码,就判定为命中(说明存在管理后台入口,值得人工去看)。再复杂一点的,可以用 contains 匹配响应体关键词,多个 matcher 之间用 condition: and 组合:
id: spring-actuator-env
info:
name: Spring Actuator Env Exposed
severity: medium
requests:
- method: GET
path: "/actuator/env"
matchers:
- type: status
status: [200]
- type: contains
words: ["spring", "java.version"]
condition: and
调用方式:
python src/recon.py poc -t https://example.com -p pocs/example-http-detect.yaml
跑完会输出命中/未命中结论,命中的自动进入高优先级清单。因为模板引擎是通用的,这套东西不仅能用于信息收集阶段的探测,也能直接复用公开的 nuclei 模板做漏洞验证,只是目前只实现了子集,复杂模板(多请求、变量、raw 请求)还在路上。
LLM 辅助
信息收集的结果是一堆原始资产列表,直接看容易漏重点。工具里加了一个可选的 LLM 辅助模块,做两件事:
- 资产分级:把收集到的资产列表 + 指纹信息打包,让 LLM 按”攻击价值”分级——比如”直接暴露的管理后台 > 带指纹的框架资产 > 纯静态页面”
- 攻击面总结:输出一份
out/<target>/llm_summary.md,列出值得优先测试的点
配置方式是标准 OpenAI 兼容接口:
export LLM_API_KEY=xxx
export LLM_BASE_URL=https://api.openai.com/v1 # 可配其他兼容端点
export LLM_MODEL=gpt-4o-mini
同样遵循无 key 自动降级原则:没配 key 时模块直接跳过,不影响主流程。LLM 输出只当参考——它给的结论不直接进报告,人工复核一遍才采信,避免幻觉污染结果。
效果对比
同一目标、同一批资产,手动 vs 工具化的耗时对比:
| 步骤 | 手动(工具来回切) | src-recon-tool |
|---|---|---|
| 子域枚举 | 30–40 分钟(开 OneForAll、等跑完、复制结果) | 3–5 分钟(一条命令) |
| 资产测绘 | 20–30 分钟(FOFA/Hunter 网页端手动翻页、复制) | 3–5 分钟(API 自动分页) |
| 指纹识别 | 15–20 分钟(逐个资产肉眼判断或开工具) | 2–3 分钟(批量规则匹配) |
| 敏感路径探测 | 20–30 分钟(手工构造请求逐条试) | 3–5 分钟(字典批量探测) |
| 结果整理去重 | 20–30 分钟(Excel/记事本手工整理) | 自动落盘 out/<target>/ |
| 合计 | 约 2 小时+ | 30 分钟内 |
时间主要省在三处:并行(各模块互不依赖,可流水线串联)、免手工搬运(结果自动落盘去重)、可复用(同一套流水线换个 -d 参数就是新目标)。
实战应用
这套工具已经用于 EDUSRC 授权范围内的实战挖洞,作为每次测试的”开场动作”。实际使用中几个心得:
- 先全流程,再重点深入:
recon.py all跑完拿到资产清单后,挑指纹命中、敏感路径命中的资产做人工测试,命中率比无差别扫高很多 - POC 模板沉淀是复利:每次实战发现一个新的可检测特征,就固化成一个 YAML 模板,下次自动就能扫到,检测能力是持续增长的
- 降级设计救了场:有几次在临时环境没有 key,全流程依然能跑通(子域走 crt.sh),不至于卡在第一步
- LLM 分级只能当参谋:AI 给的优先级参考价值不错,但关键决策(打不打、怎么打)还是人工判断
再强调一次红线:这套工具只用于授权范围内的安全测试,未授权目标一律不碰。工具本身只是把重复劳动自动化,不代表可以降低合规要求。
开源地址
项目已开源(MIT License):
https://github.com/xiaoyang-xyc/src-recon-tool
目录结构:
src/recon.py CLI 入口
src/modules/ 各功能模块
pocs/ YAML POC 模板
tests/ 单元测试
out/ 输出目录(gitignore)
如果你也在做 SRC 挖洞,欢迎拿去用,或者提 issue/PR 补充指纹规则和 POC 模板。下一步计划:支持更多 matcher 类型(regex、dsl)、多请求链式 POC、以及把结果直接导出成报告格式。