ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

Nuclei模板化扫描器实战:从POC编写到批量检测全流程

Nuclei模板化扫描器实战:从POC编写到批量检测全流程 很多做安全测试的朋友应该都有过这种经历甲方给了一个挺大的IP段说“帮忙看看有没有暴露的老设备”你总不能一台台手工登录去试。这时候有个趁手的批量检测工具就特别重要。Nuclei作为一款模板化的漏洞扫描器正好能解决这个痛点。这篇文章我就拿“天融信TOPSEC命令执行漏洞”这个具体场景完整走一遍从POC编写到批量检测的流程包括里面容易踩的坑和排查思路希望对刚接触Nuclei或者正在做类似工作的朋友有点帮助。1. 项目背景与检测思路拆解1.1 天融信TOPSEC设备为什么值得重点关注天融信的TOPSEC系列防火墙在国内政企内网里存量非常大不少单位用了很多年固件版本常年不更新。这类设备一旦爆出远程命令执行漏洞影响面通常很广而且因为设备本身就是为了“隔离内外网”而存在的被攻破后攻击者拿到的是内网的一个稳定跳板风险等级相当高。我平时做授权测试时遇到TOPSEC设备会格外留意几个点第一设备的Web管理面板是否直接暴露在非信任网络第二固件版本是否老旧是否已经出现在公开漏洞库中第三是否存在一些历史遗留的默认口令或调试接口。命令执行类漏洞是这里面最严重的一种它能直接让测试人员从“能访问管理页”变成“能执行系统命令”接下来无论是读取配置文件还是做内网跳板都变得十分顺滑。1.2 Nuclei这类模板化扫描器好在哪里Nuclei是ProjectDiscovery团队开源的漏洞扫描器核心设计思路是“用YAML模板描述漏洞检测逻辑”扫描引擎负责并发发起请求、匹配响应、提取结果。社区维护着非常庞大的模板库很多公开漏洞在PoC公布后几天内就会有对应的nuclei模板。相比直接用Python脚本或Burp Suite的IntruderNuclei有几个明显优势并发效率高默认就能跑几十上百个并发扫一个大网段不用等太久。模板可复用一个写好的模板之后遇到同类设备随时复用。结果结构化输出JSON、Markdown等格式方便后续对接工单或报告。内置多种协议支持除了HTTP还能写DNS、TCP等协议的检测逻辑。这次要做的TOPSEC命令执行检测本质上就是构造一个特殊的HTTP请求看设备是否会在响应中回显命令执行的结果。Nuclei的HTTP请求模板能力足够覆盖这个场景而且不需要额外写复杂的Python脚本。1.3 漏洞检测的整体流程拆解整个检测过程可以分成四步走确认目标设备确实是天融信TOPSEC避免误报。构造命令执行探测请求通过响应特征判断漏洞是否存在。用Nuclei模板批量跑目标IP段收集存活且存在漏洞的设备。对扫出来的结果做人工复核确认不是误报。这里我想强调一点批量扫描工具只是辅助最终确认漏洞可利用性还是得靠手工验证。Nuclei的职责是帮你把“可能有问题”的设备从成千上万个IP里筛出来而不是替你下结论。2. Nuclei与POC设计核心逻辑2.1 YAML模板的基础结构先看一个Nuclei模板最基础的结构长什么样后面写POC都是在这个框架上扩展的id: tosec-rce-check info: name: TianRong TOPSEC RCE Detection author: your-name severity: critical description: Detects command execution vulnerability in TOPSEC devices tags: tosec, rce, firewall requests: - method: GET path: - {{BaseURL}}/xxx matchers: - type: word words: - uidid字段是这个模板的唯一标识info区块存漏洞元数据requests区块定义具体的检测请求。模板写完后把文件放到nuclei的templates目录下的某个子目录里比如http/cves/执行扫描时用-tags参数就能筛出来。2.2 命令执行漏洞POC的常见设计思路命令执行类漏洞的POC设计核心是解决一个问题怎么在不直接进行破坏性操作的前提下可靠地判断命令确实被执行了。最常用的思路是让设备执行一个无害且结果可回显的命令比如id、whoami、cat /etc/passwd等。如果设备把命令输出直接拼在HTTP响应里那恭喜你这是一个教科书级的回显型命令执行。以TOPSEC的某类接口为例漏洞点常出现在一些调试用或维护用的功能参数上。比如某个参数会把用户输入直接拼进系统命令中执行检测时就能构造类似这样的请求GET /tosec/cmd.action?cmdid HTTP/1.1 Host: target如果响应体里出现了uid这样的字符串基本可以确定命令执行漏洞存在。当然实际代码中的参数名和路径需要根据具体固件版本调整我这里就不写具体设备的细节了避免被恶意利用。思路是通用的拿到一个命令执行漏洞第一步就是找能在响应中回显命令结果的最小验证请求。2.3 为什么选择Nuclei DSL而不是普通正则匹配Nuclei的DSL领域特定语言提供了比单纯正则匹配更灵活的响应判断能力。比如你可以用contains(body, uid)这样的表达式还能组合多个条件做AND/OR判断。写复杂检测逻辑时DSL的价值会体现得更明显。比如说你检测一个漏洞需要同时满足“响应状态码是200”和“响应体中包含特定字符串”用纯正则写起来比较绕但用Nuclei DSL就是matchers-condition: and matchers: - type: status status: - 200 - type: word words: - uid这样逻辑一目了然后续维护也方便。另外Nuclei的DSL还支持extractors能从响应中提取动态的内容比如提取命令执行的结果保存下来方便人工复核。3. 实操配置与POC编写详解3.1 环境准备与工具安装Nuclei的安装方式很简单有Go环境的话一行命令go install github.com/projectdiscovery/nuclei/v3/cmd/nucleilatest没有Go环境的话直接去GitHub的Releases页面下载编译好的二进制文件扔到/usr/local/bin下就行。Windows环境就用exe文件命令用法一样。装完之后更新一下模板库nuclei -update-templates这个是必须做的因为社区模板每天都在更新。当然我们这种自定义POC属于私有模板不会在社区模板库里需要单独管理。3.2 自定义POC模板的完整写法下面我给一个实际可用的模板框架假设检测路径是/tosec/cmd.action参数是cmd命令执行结果会直接回显到响应体中实际场景需根据目标版本调整但方法完全一致id: tosec-cmd-exec info: name: TianRong TOPSEC Command Execution author: security-researcher severity: critical description: Detects command execution vulnerability in TOPSEC devices by injecting id command tags: tosec,rce,firewall,cnvd requests: - method: GET path: - {{BaseURL}}/tosec/cmd.action?cmdid headers: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 matchers-condition: and matchers: - type: word part: body words: - uid - gid condition: and - type: status status: - 200 extractors: - type: regex part: body regex: - uid\\d\\([^)]\\)这个模板做的事情很简单发一个GET请求往cmd参数里塞入id命令然后匹配响应体里是否同时出现uid和gid。如果返回200同时包含这两个特征就认为存在命令执行漏洞。3.3 编写POC时容易忽略的细节写这个模板时有几个细节值得特别注意路径大小写某类设备的Web服务对路径大小写敏感最好在模板里明确写出实际测试过可用的路径。如果把/tosec/cmd.action写成/Tosec/Cmd.action遇到区分大小写的服务就直接404了。URL编码如果命令里有空格或特殊字符需要在请求里做URL编码。id命令本身不含空格但如果后续想执行cat /etc/passwd空格在URL里要么写成%20要么写成不同设备对这两种编码的接受程度不一样建议在手工验证时都试一遍。请求频率控制Nuclei默认并发不算低批量扫大量IP时如果目标设备性能较差很多老防火墙的CPU和内存都很感人容易把设备扫挂。后面会讲到怎么控制速率。指纹确认批量检测时大量非TOPSEC设备也会出现在目标列表里如果直接发送POC请求一方面会产生大量无意义的告警日志另一方面可能触发一些安全设备的封禁策略。建议先加一个指纹匹配步骤确认是TOPSEC设备再发命令执行探测请求。3.4 指纹预筛的设计方法想加指纹预筛最简单的方式是利用Nuclei的stop-at-first-match配合多级请求。或者更直接一点先做一次指纹请求用internal变量把结果传给后面的请求判断。Nuclei支持在同一个模板里写多个请求后面的请求可以引用前面请求的响应内容比如提取到的关键字符串。思路大概是这样的requests: - method: GET path: - {{BaseURL}}/ matchers: - type: word name: tosec_fingerprint words: - TOPSEC - 天融信 condition: or internal: true上面第一个请求先判断首页是否有TOPSEC相关指纹。如果匹配成功再走第二个请求做漏洞探测。不过实际写起来有一个坑Nuclei的internal变量和请求间数据传递在复杂模板中不太好维护新手容易写出“第一个请求的matcher没生效第二个请求照样发”的情况。这里我更推荐一个懒人做法分两步跑。第一步用指纹模板扫描目标列表筛出TOPSEC设备id: tosec-detect info: name: TOPSEC Device Fingerprint severity: info requests: - method: GET path: - {{BaseURL}}/ matchers: - type: word words: - TOPSEC - 天融信WebSec第二步把指纹命中的IP作为目标用命令执行检测模板再扫一遍。这样逻辑清楚排查问题也方便。4. 批量检测执行流程实录4.1 目标列表准备批量检测的第一步是准备目标列表。实际工作中目标来源一般有三种甲方给的一个网段、资产测绘平台导出的IP列表、或者子域解析出来的IP集合。无论来源是哪种建议先把列表做去重和存活探测。去重可以用sort -u存活探测可以用httpx这样的工具cat targets_raw.txt | sort -u | httpx -silent -status-code -title -tech-detect -o alive_targets.txt这个命令会探测每个IP的HTTP服务是否存活并输出状态码、页面标题和识别到的技术栈。这里有个小技巧别把所有IP都直接丢给nuclei扫先筛一次能节省大量时间也减少误报源。有些地址根本不开Web服务扫了也是白扫。4.2 指纹预筛的执行过程假设现在有一个存活目标文件alive_targets.txt内容是IP加端口格式大概是https://192.0.2.10:8443这种。先跑指纹模板nuclei -l alive_targets.txt -t tosec-detect.yaml -o tosec_ips.txt -jsonl -silent-jsonl参数会输出JSON格式的结果方便后续脚本提取命中的IP。执行完之后查看tosec_ips.txt里面应该有所有指纹命中的目标。这一步输出的是“疑似TOPSEC设备”数量通常不会太多。如果一下子命中几百上千个说明目标网段里这种设备确实多后面命令执行检测会很热闹。4.3 漏洞检测与结果输出接下来用命令执行模板扫指纹命中的目标nuclei -l tosec_ips.txt -t tosec-cmd-exec.yaml -o rce_results.txt -jsonl -rate-limit 10 -c 5这里两个参数要重点解释一下-rate-limit 10限制每秒最多发10个请求。这样设置是为了照顾老设备的承受能力。-c 5限制并发模板数也就是同时只有5个目标在处理。有朋友可能会觉得这个速率是不是太慢了。我实际测过一批设备很多是用了五年以上的老防火墙Web服务模块用的是很老的架构并发稍微一高就无响应了。与其扫崩了再重启再补扫不如一开始就悠着点慢工出细活。执行完之后屏幕上会高亮显示命中的目标同时结果写入rce_results.txt。每一行是一个JSON对象包含目标地址、模板ID、匹配到的详细信息等。4.4 结果的人工复核与利用验证这一步非常关键。Nuclei命中的结果不一定是真的漏洞有可能是某种特殊的页面刚好包含uid这样的字符串。所以需要拿命中的目标再做一次人工复核。我的标准操作是浏览器访问目标手工构造POC请求观察响应。如果条件允许用一个无害命令验证一下比如id或uname -a确认命令确实执行了。如果能够回显命令结果再截图留证。这里要特别提醒授权是硬前提。没有目标单位书面授权做任何扫描都是不合规的。别拿这个流程去扫不在授权范围内的目标这是底线问题。5. 常见问题与排查技巧实录5.1 模板不生效所有目标都显示未命中这种情况最常见的两个原因一是路径或参数名不对二是目标设备固件版本已经修复漏洞。排查路径很简单先手工发一个请求看看响应如果手工请求都拿不到预期的特征说明POC里的路径或者命令不对需要换一个接口或参数。如果是固件修复了那就是漏洞本身已不存在模板更新也没用。另外还有一种情况设备把带命令参数的请求交给WAF模块拦截了返回了一个拦截页面当然匹配不到特征。这种要看看响应头或响应体里是否有WAF的标识比如Powered by XXX之类的。5.2 误报率过高响应里到处都有uid如果命中的结果里有一堆明显不是TOPSEC的设备可能是指纹模板写得太宽泛了。比如匹配词里只写了TOPSEC结果有些第三方登录页也用这个词做了品牌展示。解决方法是增加指纹的权重比如同时匹配TOPSEC和页面标题中的特定关键字或者匹配特定的JS文件名、Logo路径等。多条件AND匹配能筛掉大部分误报。5.3 扫描过程中目标设备无响应批量扫TOPSEC设备时容易被扫挂的设备通常有这些特征老版本固件、开启了很多不必要的服务、内存较小。处理办法是先确认设备是彻底宕机还是只是Web服务无响应。如果只是Web服务重启等几分钟再补测即可。如果是整机宕机可能需要联系现场人员重启。所以前面强调的-rate-limit和-c参数真的别不放在心上。还有一个经验尽量避免在业务高峰期扫描这类老设备。老防火墙除了做安全隔离往往还承载着一些历史遗留的转发任务你把它的Web服务扫挂了整个办公网出口都可能受影响。5.4 Nuclei命令执行模板无法提取命令结果有些场景下命令执行漏洞确实存在但命令结果是异步返回的比如设备把命令放到后台执行结果写到某个临时文件里需要另一个接口去读。这种时候Nuclei的单请求模板就不够用了得用多请求模板。思路是第一个请求触发命令执行把输出重定向到一个可访问的静态文件路径下第二个请求去读取这个文件匹配内容。这类漏洞检测模板写起来复杂度高一些但也不是不能写。Nuclei支持同模板内定义多个requests按顺序执行前一个请求的输出可以作为后一个请求的输入。5.5 批量扫描结果如何高效整理扫出来的结果往往是纯文本或JSON直接贴给甲方肯定不行。我一般用一个小脚本把JSON结果转成表格cat rce_results.txt | jq -r [.host, .matched-at, .info.name] | tsv然后贴到表格软件里按漏洞等级、目标IP、URL、验证状态列成清单再补充修复建议。这个流程看起来很笨但确实是项目交付时最实用的做法。6. 经验总结与进一步扩展思路6.1 模板维护的小技巧Nuclei模板写多了建议按设备厂商或漏洞类型建好目录结构比如templates/tosec/下面放这类设备的全部模板templates/rce/放通用命令执行检测模板。每次扫描前用nuclei -update-templates更新社区库同时检查一下自己的私有模板是否需要修正路径或匹配词。我习惯给每个模板文件写清楚注释包括漏洞编号、影响版本、检测命令、验证方法。Nuclei的YAML支持#注释多写点说明后续自己回来看也能快速想起来当时为什么这么写。6.2 从单点检测到体系化复盘这次批量检测做完后我建议把整个流程沉淀下来模板文件、命令、结果、人工复核记录都整理成一套文档。下次遇到同类设备直接复用这套流程就行。同时也别只盯着一个漏洞点TOPSEC这种设备往往同时存在多个已知漏洞比如未授权访问、信息泄露等。把多个检测模板组合起来跑一次扫描就能对目标设备的安全状况有个比较全面的认识。6.3 实际工作里我个人的几个心得第一工具永远是辅助手工验证是必须项。再好的模板也有误报也有抓不到的绕过姿势。批量检测帮你圈定范围人工确认帮你下结论。第二速率控制是对目标最基本的尊重。有些设备承载着生产业务你扫挂了它影响的可能是一整片网络这个责任谁也担不起。宁可多花点时间也别图快。第三结果整理比扫描本身更花精力。真正靠谱的安全测试核心交付物是一份结论清晰、证据完整的报告。一个IP一个结论加截图比打印十页扫描原始输出有价值得多。第四POC不等于武器库。写命令执行检测模板的目的是帮助确认风险、推进修复而不是拿去做一些不该做的事情。合规这条线任何时候都不能松。这篇文章里写的检测方法在我自己处理过的不少授权测试项目中都验证过流程是可复用的。整体思路也不只适用于TOPSEC换一个设备型号本质上就是换一组指纹、换一条漏洞路径、换一组匹配特征方法骨架完全一致。希望这份从POC编写到批量落地的心得能帮你少走一些弯路。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表