ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SRC漏洞挖掘入门:从资产收集到漏洞验证与提交完整流程

SRC漏洞挖掘入门:从资产收集到漏洞验证与提交完整流程 一、引言为什么挖不到洞往往不是技术问题大多数新手进入 SRCSecurity Response Center企业安全应急响应中心的第一周都会经历同一件事对着一个主域名翻来覆去看登录框、注册页、忘记密码试了几轮弱口令和 XSS payload然后一无所获最后得出结论——“这个厂商的洞被别人挖完了”。这个结论背后通常有两个认知偏差。第一把 SRC 等同于找注入、找 XSS以为漏洞是一串可以穷举的 payload第二把攻击面等同于首页和登录框忽略了企业资产在云、小程序、App、API 网关、测试环境里的真实分布。于是同样一天时间有人只测了一个站点有人已经把几千个子域名按优先级排好队差距从第一步就拉开了。真相通常不是这样。根据公开的 SRC 年报和众测平台数据头部厂商每年接收的有效漏洞中超过 60% 出现在主域名之外的资产上测试环境、历史遗留系统、收购来的子公司站点、小程序后端 API、CDN 回源 IP 暴露的源站、移动 App 里硬编码的接口地址。你盯着www.example.com而攻击面可能散落在几千个子域名、几十个 IP 段和若干个未被索引的 API 网关里。所以 SRC 挖洞的本质不是找漏洞而是先把攻击面画全再按性价比排序。本文按完整链路展开资产收集 → 存活与指纹 → 漏洞验证 → 报告提交并给出可直接复用的代码和踩坑清单。整条链路里资产收集决定你能看到多少目标存活指纹决定你一天能筛掉多少噪音漏洞验证决定你的报告能不能被认可提交细节则决定你会不会被判重复或越界。合规前提以下所有操作仅限目标 SRC 平台《测试范围与规则》明确授权的资产。越界测试不属于白帽属于违法行为。二、核心原理SRC 挖洞的三层漏斗把整个流程抽象成一个漏斗模型全量资产域名/IP/APP/小程序 ↓ 存活 指纹过滤 真实攻击面Web/API/中间件 ↓ 漏洞验证POC 手工确认 有效漏洞可复现、有危害、不重复这个漏斗的意义在于每一步都在做减法而不是一开始就做加法。新手常把精力花在我会哪些漏洞类型但真正决定效率的是我能不能把几千个资产压缩成几十个值得手工测的入口。下面把三层分别拆开。2.1 资产面你看到的不等于攻击面资产收集分被动和主动两类。被动收集不向目标发包风险最低证书透明日志CT Log、搜索引擎、GitHub 泄露、第三方 DNS 数据集、App 反编译。主动收集包括子域名爆破、端口扫描、目录扫描会产生流量容易被 WAF 封 IP也可能触碰 SRC 规则红线。一个常被忽略的点是证书透明日志。任何签发过公网证书的域名都会进入 CT Log而很多企业给内网系统、测试环境签证书时忘了这一点导致test-*.example.com、uat-*.example.com被完整暴露。这是性价比最高的被动收集手段。CT Log 的底层是一套公开可审计的证书日志CA 签发证书后会提交到多个日志服务器日志会记录证书中的 Common Name 和 Subject Alternative Name。也就是说只要某个子域名曾经出现在一张公网证书里它就有机会被crt.sh、certspotter等聚合服务检索到。很多企业的通配符证书会把*.example.com写进 SAN虽然不会直接列出所有子域名但一旦某个测试域名单独签过证书就会留下痕迹。被动收集的常见来源还包括SecurityTrails、VirusTotal、DNSDumpster、PassiveTotal、urlscan.io、Wayback Machine、Common Crawl。GitHub 泄露尤其值得重视因为开发人员可能把内部接口、测试账号、云存储地址写进代码、Issue、CI 配置或历史提交。常见搜索语法包括example.com password api.example.com token example.com AKID example.com oss-cn example.com jdbc主动收集则要更谨慎。子域名爆破、端口扫描、目录扫描都可能触发 WAF、IDS 或 SOC 告警。在 SRC 场景下先看规则里是否允许扫描、是否限制频率如果没有明确允许优先做被动收集和单点验证不要一上来就全端口nmap -sS -p-。主动收集的价值在于补齐被动日志的盲区比如没有证书的内部域名、只在内网 DNS 解析的测试系统、通过 CDN 隐藏的源站。但它的成本也更高流量特征明显、容易被封、可能越界。2.2 漏洞面按利用成本排序新手常犯的错是按漏洞类型清单逐个试。更高效的排序维度是利用成本优先级类型原因高未授权访问、越权IDOR、信息泄露无需交互、易复现、易证明危害高硬编码密钥、云存储配置错误危害直观SRC 认可度高中SSRF、任意文件读取、SQL 注入需构造但危害明确中存储型 XSS、CSRF需证明实际影响低反射型 XSS、无敏感信息的 CORS常被判低危或忽略如果再把利用成本拆细可以看四个维度请求复杂度一个 GET 就能证明还是要多步交互、账号需求是否必须注册两个账号、证据难度截图能否说清危害、修复成本厂商是否容易确认。越权、未授权、信息泄露通常四项都低所以优先级最高反射型 XSS 往往需要证明能打到谁、能干什么如果只是弹窗SRC 很容易判低危。同时新上线资产和边缘资产的漏洞密度远高于核心业务——核心业务经过多轮众测边缘资产可能从未被测试过。哪些信号说明资产可能是新的比如页面底部版权年份是今年、接口版本是/v2/或/v3/、Swagger 文档未关闭、返回头里有新框架特征、小程序刚更新、招聘 JD 里提到新业务线。把这些信号和资产列表关联起来就能找到没人测过的入口。2.3 验证面从疑似到确认漏洞验证的核心原则是最小化证明用最少的数据、最轻的操作证明危害存在。比如发现越权不要遍历全量用户数据取两个自己注册的账号交叉验证即可。这既符合 SRC 规则也让报告更可信。最小化证明还有三条隐形红线第一不修改、不删除目标数据第二不批量拉取、不遍历 ID第三不进行拒绝服务测试。很多新手在验证 SQL 注入时喜欢直接sqlmap -a拖库或者用load_file(/etc/passwd)证明文件读取这些操作在 SRC 里都属于高风险行为轻则判违规重则封号。正确的证据链应该包含三部分完整的 HTTP 请求包、关键响应片段、一句话影响说明。请求包让审核员能复现响应片段证明数据确实返回影响说明告诉厂商这为什么是漏洞。三、实战一次完整的资产收集到漏洞验证假设目标是某 SRC 授权范围内的example.com。3.1 第一步被动收集子域名CT Log#!/usr/bin/env python3# ct_subdomain.py —— 通过证书透明日志被动收集子域名importreimporttimeimportrequests CRT_SHhttps://crt.sh/?q%25.{domain}outputjsonHEADERS{User-Agent:Mozilla/5.0 (asset-recon; authorized-src-only)}deffetch_crtsh(domain:str,retry:int3):查询 crt.sh返回去重后的子域名集合urlCRT_SH.format(domaindomain)foriinrange(retry):try:rrequests.get(url,headersHEADERS,timeout40)r.raise_for_status()datar.json()subsset()forentryindata:# name_value 可能包含多个换行分隔的域名fornameinentry.get(name_value,).split(\n):namename.strip().lower().lstrip(*.)ifname.endswith(domain)and notinname:subs.add(name)returnsubsexceptExceptionase:print(f[!] 第{i1}次请求失败:{e})time.sleep(3*(i1))returnset()if__name____main__:domainexample.comsubsfetch_crtsh(domain)# 简单的泛解析过滤出现次数过多的通配结果先降权观察withopen(subs.txt,w)asf:f.write(\n.join(sorted(subs)))print(f[] 共获取{len(subs)}个子域名已写入 subs.txt)这段代码的价值在于零流量触达目标你查询的是第三方日志服务目标服务器完全感知不到。拿到结果后再和爆破结果、GitHub 泄露结果做并集。几个工程细节值得补充。第一crt.sh偶尔会超时或返回 HTML 错误页所以代码里做了重试和异常捕获第二name_value里可能出现*.example.com、www.example.com\napi.example.com这种多值必须按换行拆分第三结果里会混入example.com本身、其他域名、甚至包含空格或非法字符的记录需要过滤。如果不想写脚本也可以用一行命令快速拉取curl-shttps://crt.sh/?q%25.example.comoutputjson\|jq-r.[].name_value\|seds/\*\.//g\|sort-usubs_crt.txt但要注意crt.sh只覆盖签过公网证书的域名。对于没有证书的内部系统、只走 HTTP 的测试环境还需要结合 DNS 数据集、GitHub、JS 文件、App 反编译来补全。一个实用的顺序是先 CT Log 拿第一批再用subfinder -all聚合多个被动源最后从 JS 和 App 里提取接口域名做交集。3.2 第二步存活探测与指纹识别几千个子域名里真正存活的可能只有几百个。这一步用流水线处理#!/bin/bash# recon.sh —— 子域名存活探测 指纹识别 模板化扫描set-eDOMAINexample.com# 1. 合并多来源子域名subfinder 覆盖 CT、API、爆破字典subfinder-d$DOMAIN-all-silent|sort-usubs_all.txtcatsubs.txt subs_all.txt2/dev/null|sort-usubs_merged.txt# 2. 存活探测输出 状态码/标题/技术栈/CDN同时保存响应体httpx-lsubs_merged.txt\-silent-sc-title-tech-detect-cdn\-mc200,201,301,302,401,403,500\-oalive.txt# 3. 重点关注403/401 往往是存在但未授权的信号grep-E\s(401|403)\salive.txt|awk{print $1}forbidden.txt# 4. 模板化扫描nuclei 只跑低风险模板避免触发 WAF 封禁nuclei-lalive.txt\-texposures/-tmisconfiguration/-ttakeovers/\-severitymedium,high,critical\-rl30-c10\-onuclei_result.txt几个参数值得解释-rl 30限制每秒请求数-c 10限制并发都是为了降低被封 IP 的概率-mc里特意包含 401/403因为返回 403 的接口往往只需换一个路径或方法就能绕过是未授权访问的高发区。指纹识别阶段要重点关注五类信息框架与中间件Spring Boot、Django、ThinkPHP、Nginx、Tomcat、CMS 与 OAWordPress、致远、泛微、用友、云存储与 CDNOSS、S3、COS、CloudFront、API 文档Swagger、Knife4j、Actuator、GraphQL、认证方式JWT、Session、OAuth、AK/SK。这些信息决定了你接下来该试什么漏洞。比如看到/actuator/env就优先测 Spring Boot 未授权看到/swagger-ui.html就优先测接口越权看到*.oss-cn-*.aliyuncs.com就优先测 Bucket 权限。对于 403 页面可以按下面的清单做低成本绕过尝试1. 路径变形/admin - /admin/ - //admin - /./admin - /%2e/admin 2. 大小写/Admin - /ADMIN 3. 后缀/admin - /admin.json - /admin;.js - /admin%00 4. 方法GET - POST - PUT - OPTIONS - HEAD 5. 请求头X-Forwarded-For: 127.0.0.1、X-Real-IP、X-Original-URL 6. 代理路径/api/admin - /api/../admin这些尝试仍然要控制频率且只在授权范围内做。如果全部无效不要死磕换下一个资产。另外现代 Web 的接口越来越多地藏在 JS 文件里。可以用下面的脚本从存活站点的 JS 中提取 API 路径和域名#!/usr/bin/env python3# extract_js_api.py —— 从 JS 文件中提取接口路径与域名importreimportrequestsfromurllib.parseimporturljoin JS_URLS[https://www.example.com/static/js/app.js,https://www.example.com/static/js/main.js,]PATTERNS[re.compile(r[\](/api/[a-zA-Z0-9_\-/{}])[\]),re.compile(r[\](https?://[a-zA-Z0-9\.\-]/[a-zA-Z0-9_\-/{}]*)[\]),re.compile(r[\]([a-zA-Z0-9_\-/]\.(json|do|action))[\]),]forjsinJS_URLS:try:textrequests.get(js,timeout15).textexceptExceptionase:print(f[!] 拉取失败{js}:{e})continueforpinPATTERNS:forminp.findall(text):pathmifisinstance(m,str)elsem[0]print(urljoin(js,path))这类脚本能帮你发现未在导航栏暴露的接口、旧版本 API、内部域名。很多越权、未授权漏洞就是从 JS 里的一个fetch(/api/v1/user/info)开始的。3.3 第三步越权漏洞验证双账号交叉法假设指纹识别发现api.example.com是一个 JSON API 网关返回 401 的接口集中在/api/v1/orders/{id}。此时不要盲测用两个自己注册的账号做交叉验证——这是 IDORInsecure Direct Object Reference不安全的直接对象引用最规范的验证方式。#!/usr/bin/env python3# idor_check.py —— 双账号交叉验证水平越权importrequests BASEhttps://api.example.com# 账号 A 的资源 ID 用 my_oid账号 B 的 token 去请求它A_TOKENeyJhbGciOi...账号A的tokenB_TOKENeyJhbGciOi...账号B的tokenMY_ORDER_ID10000001# 账号 A 自己的订单号defget_order(token:str,oid:str):rrequests.get(f{BASE}/api/v1/orders/{oid},headers{Authorization:fBearer{token}},timeout10,)returnr.status_code,r.text[:300]defcheck_idor():# 基线 1A 用自己的 token 请求自己的订单 → 应返回 200s1,b1get_order(A_TOKEN,MY_ORDER_ID)print(f[基线] A 访问自己的订单:{s1})# 基线 2B 用自己的 token 请求 A 的订单 → 应返回 403s2,b2get_order(B_TOKEN,MY_ORDER_ID)print(f[测试] B 访问 A 的订单:{s2})ifs2200:# 只截取关键字段证明危害绝不批量拉取print([!] 存在水平越权响应片段)print(b2)returnTrueprint([-] 未发现越权)returnFalseif__name____main__:check_idor()这段脚本的设计哲学是克制只请求一条记录只打印 300 字符验证完立刻停止。很多新手在这里顺手写个 for 循环遍历 1 到 100000结果被 SRC 判为超出测试范围甚至封号。如果接口返回 200 但内容是 A 的订单说明后端只校验了 JWT 有效性、没校验资源归属这是一个标准的水平越权。再顺手测一下把GET换成PUT/DELETE如果也能成功危害等级直接从中危升到高危。越权一般分两类水平越权是同级用户之间互相访问资源比如 A 看 B 的订单垂直越权是低权限用户访问高权限功能比如普通用户调用管理员接口。验证时可以用下面的矩阵测试项账号 A普通账号 B普通管理员账号A 的订单应 200不应 200视业务B 的订单不应 200应 200视业务管理员接口不应 200不应 200应 200删除/修改接口不应成功不应成功视业务实际测试中越权经常出现在这些位置订单详情、地址管理、发票下载、文件预览、消息已读、导出接口、GraphQL 节点查询、userId参数、tenantId参数、orgId参数。尤其是多租户 SaaS只要请求里出现tenant_id、company_id就值得做交叉验证。验证时优先用自己注册的两个账号不要用真实用户数据。如果业务必须用手机号注册可以用自己控制的两个号码避免碰他人隐私。四、踩坑与优化建议1. 资产重复是最大的时间黑洞。提交前务必在 SRC 平台搜一遍关键词域名、接口路径、漏洞类型。同一个admin.example.com的弱口令可能已经被三个人提交过。用平台的已公开漏洞列表做差集能省掉 30% 的无用功。更细的做法是把已公开漏洞的域名、路径、参数提取出来和你的资产库做交集重复率高的资产直接降权。2. 别把低危当无危。一个看似无害的CORS: Access-Control-Allow-Origin: *配合Access-Control-Allow-Credentials: true就是可读取用户敏感数据的实锤。报告里要写清楚利用链而不是只丢一个响应头。比如要说明攻击者页面可以携带用户 Cookie 请求https://api.example.com/user/info读取返回中的手机号、邮箱、地址并外带到自己的服务器。3. 危害证明要可视化。审核员每天看几百份报告纯文字描述很容易被判无法复现。正确做法是完整的 HTTP 请求包 关键响应字段截图 一句话说明这会导致什么。比如任意用户可读取他人订单包含姓名、手机号、收货地址比存在越权漏洞有效十倍。如果有时间可以录一个 20 秒的复现 GIF但不要暴露真实用户数据。4. 不要碰破坏性操作。不删数据、不改配置、不上传 webshell、不遍历数据库。发现 SQL 注入用AND 11/AND 12证明即可别去load_file(/etc/passwd)。发现命令执行用sleep 5或ping自己的域名证明不要执行rm、curl | bash。发现 SSRF优先请求自己的可控服务器不要扫内网端口、不要读云元数据中的敏感凭据。SRC 的底线是证明危害但不扩大危害。5. 优化建立自己的资产库。把每次收集的子域名、IP、指纹存进本地数据库SQLite 足够标注已测/未测/已提交。长期看这套积累比任何工具都值钱——因为别人没测过的资产才是你的机会。表结构可以简单到asset、source、status、last_check、note。每次挖洞前先查库避免重复劳动。6. 关于 WAF 绕过。遇到 WAF 不要硬刚先判断拦截点是路径关键词、参数特征还是频率。优先尝试大小写变形、%00截断、分块传输无效就换资产。在 SRC 场景下换目标的收益远高于绕 WAF。另外WAF 拦截页本身也可能泄露信息比如厂商、规则 ID、回源 IP这些可以记录到资产库但不要为了绕过而使用攻击性 payload。7. 报告模板比 payload 更重要。一份合格的 SRC 报告通常包含漏洞标题、漏洞类型、危害等级、影响范围、复现步骤、请求响应、修复建议。标题要具体比如某 API 订单查询接口存在水平越权可读取他人订单信息不要写越权漏洞。复现步骤要编号每一步都让审核员能跟着做。修复建议不用写成长篇论文但要点出根因比如服务端未校验资源归属仅校验 JWT 有效性。8. 时间管理先广后深。新手容易在一个资产上耗一整天。更合理的节奏是上午做资产收集和存活指纹下午按优先级手工验证 3 到 5 个高价值入口晚上整理报告和资产库。一个资产测 30 分钟没有明确进展就标记后换下一个。SRC 是概率游戏广度往往比深度更早带来第一个有效漏洞。9. 常见问题 FAQ。Q1没有授权可以挖吗不可以。只有 SRC 平台明确列入测试范围的资产才能测。子域名、IP、App、小程序是否在范围内要以规则页为准。不确定时先提交工单向平台确认。Q2子域名爆破被 WAF 封了怎么办立即停止爆破换被动收集源。如果只是 IP 被封可以换出口 IP但不要用代理池高频轮换继续打这容易被判恶意扫描。优先用 CT Log、GitHub、JS 提取等零流量方式。Q3漏洞被重复提交怎么办提交前先搜平台已公开漏洞提交时在报告里说明你的验证时间、请求特征。如果已被提交可以补充新的利用链或影响范围但不要重复提交同一问题。很多平台允许补充说明但最终是否给奖励由厂商决定。Q4低危漏洞要不要提交看平台规则和漏洞本身。如果低危能组合成中高危或者能证明真实业务影响就提交如果只是无敏感信息的 CORS、无危害的反射型 XSS提交后可能被忽略反而浪费审核资源。可以先记录等找到组合链再一起提交。Q5如何证明越权而不碰真实用户数据用自己注册的两个账号交叉验证。A 的 token 请求 A 的资源应成功B 的 token 请求 A 的资源如果成功就证明越权。只请求一条记录只截取必要字段打码敏感信息。Q6工具推荐哪些被动收集subfinder、amass、crt.sh、gau、waybackurls。存活指纹httpx、nmap、whatweb、wappalyzer。扫描nuclei、ffuf、dirsearch。手工测试Burp Suite、Postman、浏览器开发者工具。工具不在多而在形成流水线。Q7挖不到洞怎么办先检查顺序是不是只盯着主站是不是没做资产去重是不是只试了常见 payload把资产列表拉出来按新上线、边缘、未测排序优先测 API、测试环境、小程序后端。很多时候不是技术不够而是目标选错了。Q8SRC 和众测有什么区别SRC 通常是厂商自建或委托运营的漏洞收集平台规则由厂商制定奖励以积分、Rank、现金为主众测是第三方平台组织的项目制测试时间、范围、奖励更明确。两者都要求合规但 SRC 更强调长期积累和资产熟悉度。五、总结与展望SRC 漏洞挖掘是一条完整的工程链路被动收集画全攻击面存活指纹做降维过滤模板扫描和手工验证确认危害最后用克制的证据写报告。新手最容易犯的错不是技术不够而是顺序错了——先想着打 payload而不是先想清楚打哪里。把顺序摆正你会发现很多挖不到的问题其实是没看到的问题。随着企业上云和 API 化攻击面正在从域名迁移到接口和供应链。未来的 SRC 挖洞会越来越依赖三样东西对业务逻辑的理解越权、支付、风控绕过、对云原生配置的敏感度OSS/S3 权限、K8s API、CI/CD 密钥以及自动化资产管理的工程能力。工具会越来越强但判断哪个资产值得花时间的眼光仍然只能靠一次次实战积累。从今天起别再盯着首页登录框了。更多硬核网安与AI工具包请扫码获取完整源码先去把子域名列表拉出来你会发现新世界。
返回列表