1. 项目概述为什么你需要掌握Nuclei如果你是一名安全工程师、渗透测试人员或者是一名负责应用安全的开发者那么“自动化漏洞扫描”这个词对你来说一定不陌生。在当今快节奏的开发和部署环境中手动测试早已无法覆盖海量的资产和层出不穷的漏洞。我们需要一个像瑞士军刀一样趁手、高效且精准的工具来帮助我们自动化地发现那些潜在的安全风险。这就是Nuclei诞生的背景也是它迅速成为安全圈内“顶流”的原因。简单来说Nuclei是一个基于YAML模板的现代化漏洞扫描器。它的核心思想非常巧妙将漏洞检测的逻辑比如发送什么请求、如何判断响应中存在漏洞封装在一个个独立的YAML文件中这些文件就是“模板”。社区里的安全研究员们不断贡献和维护着成千上万个模板覆盖了从最新的CVE到常见的配置错误等各种场景。你只需要告诉Nuclei“扫描谁”和“用什么模板”它就能自动完成所有检测工作。这听起来是不是有点像拥有了一个由全球安全专家组成的、不知疲倦的自动化团队但Nuclei的魅力远不止于此。它的真正威力在于“自定义”。当面对一个全新的、社区模板库中尚未覆盖的漏洞或内部特有的应用逻辑时你能自己动手编写模板将你的安全知识固化为可重复执行的自动化检测脚本。从“使用工具”到“创造工具”这中间的跨越正是从安全工具使用者进阶为安全能力构建者的关键一步。本指南的目的就是带你从零开始不仅学会如何运行Nuclei更要深入理解其模板引擎最终能够独立编写出高效、精准的自定义漏洞检测模板将自动化安全测试真正融入你的工作流。2. 环境搭建与核心概念解析在开始编写或运行任何模板之前我们需要一个稳固的“作战基地”。Nuclei的安装过程非常简单但其背后的一些核心概念和配置选项决定了你后续使用的效率和体验。2.1 安装Nuclei不止一种方式最推荐的方式是使用Go语言包管理器直接安装这能确保你获得最新的稳定版本go install -v github.com/projectdiscovery/nuclei/v3/cmd/nucleilatest安装完成后在终端输入nuclei -version来验证安装是否成功。你会看到类似v3.2.0的版本号输出。除了Go安装官方也提供了适用于Windows、macOS和Linux的预编译二进制包你可以直接从GitHub Releases页面下载解压使用。注意如果你身处网络环境受限的区域使用go install可能会因为无法访问github.com而失败。这时预编译二进制包是更稳妥的选择。下载后记得将其所在目录添加到系统的PATH环境变量中。安装只是第一步。Nuclei的强大功能依赖于其庞大的模板库。首次运行任何扫描命令时Nuclei会自动下载最新的社区模板到本地默认在~/.config/nuclei/templates目录下。你可以通过nuclei -update-templates命令手动更新模板库。理解这个目录结构很重要模板按协议HTTP、DNS、TCP等和类别CVE、漏洞、配置错误等组织。当你需要查找或参考某个特定漏洞的检测方法时直接翻阅这些YAML文件是最好的学习途径。2.2 理解Nuclei的“工作流”模板、目标与输出运行一个最基本的扫描命令例如nuclei -u https://example.com背后发生了什么呢目标解析Nuclei首先会解析你提供的目标-u或-l参数。对于URL它会自动进行标准化处理。模板加载与过滤接着它会加载本地的模板库。如果没有指定-t参数默认会运行所有符合条件的模板。你可以通过-tags、-severity、-author等参数进行精细过滤例如nuclei -u https://example.com -tags cve,apache -severity critical,high只运行标记为CVE、Apache相关且严重性为高危或严重的模板。并发执行Nuclei采用高度并发的设计。-c参数控制并行执行的模板数量-bs控制每个模板并行扫描的主机数量。合理调整这两个参数例如-c 50 -bs 25可以在不压垮目标服务的前提下极大提升扫描速度。请求与匹配对于每个模板Nuclei会按照其定义向目标发送HTTP、TCP、DNS等协议请求。然后使用模板中定义的“匹配器”matchers和“提取器”extractors来分析响应。结果输出一旦匹配成功Nuclei就会按照你指定的格式默认CLI输出或通过-json、-markdown-export指定文件报告漏洞。这里有一个非常关键的实操心得初次对一个生产环境目标进行全量扫描时务必使用-rate-limit参数限制请求速率并加上-headless参数如果目标有大量JavaScript渲染内容。一个激进的命令可能是nuclei -u https://prod-app.com -rate-limit 50。先以较低的速率进行试探性扫描观察目标服务的响应和负载情况再逐步调整并发参数。盲目进行高并发扫描不仅可能触发对方的WAFWeb应用防火墙封禁更有可能对线上服务造成拒绝服务DoS影响这是安全测试中的大忌。3. 初阶实战运行你的第一次扫描理论说得再多不如动手跑一遍。我们从最简单的场景开始逐步增加复杂度让你直观感受Nuclei的能力。3.1 单目标与多目标扫描对单个网站进行快速安全健康检查nuclei -u https://target-company.com -o initial_scan_results.txt这个命令会对target-company.com运行所有默认模板并将结果保存到initial_scan_results.txt文件中。-o参数用于指定输出文件。在实际工作中我们更常面对的是资产列表。假设你有一个subdomains.txt文件里面是子域名枚举的结果app.target-company.com api.target-company.com admin.target-company.com dev.target-company.com使用-l参数进行批量扫描nuclei -l subdomains.txt -o batch_scan_results.json -json这里我们使用了-json参数输出格式为JSONL每行一个JSON对象这种格式非常适合后续导入到SIEM安全信息与事件管理系统或用于自动化脚本处理。3.2 模板过滤精准打击提升效率运行所有模板虽然全面但耗时且会产生大量无关输出尤其是针对静态博客和简单页面的检测。模板过滤是提升效率的核心技能。按标签过滤这是最常用的方式。社区模板都打上了丰富的标签如cve、xss、rce、misconfig、wordpress、java等。# 只扫描与Apache Struts和Spring框架相关的漏洞 nuclei -l targets.txt -tags struts,spring -o framework_scan.txt按严重性过滤在时间有限的应急响应中优先关注高危漏洞。nuclei -l urls.txt -severity critical,high -silent-silent参数让Nuclei只输出找到的漏洞不显示进度条等其他信息使输出更干净。按作者过滤如果你信任某位社区专家的模板质量可以专门运行他的模板。nuclei -u https://target.com -author geeknik排除特定模板或类型有时你想排除一些已知不适用或会产生干扰的检测。# 排除所有技术指纹识别tech-detect和信息类info低危模板 nuclei -l targets.txt -exclude-tags tech,info -exclude-severity low,info3.3 理解输出与结果解读Nuclei的默认CLI输出颜色丰富信息清晰。一条典型的漏洞输出如下[Critical] [CVE-2021-44228] [http] https://log4j-vuln-app.com/api/users它依次显示了[严重等级][模板ID/名称][协议][目标URL]。但对于报告和归档结构化格式更好。-json输出包含了最完整的信息如请求、响应、匹配到的数据、模板详情等。-markdown-export参数则能生成一个包含漏洞详情、复现步骤和修复建议的完整Markdown报告目录非常适合直接用于编写渗透测试报告。注意事项Nuclei的扫描结果尤其是使用社区模板时可能存在误报。一个模板报告了漏洞绝不意味着百分百存在。安全工程师的核心价值之一就是“研判”。你需要手动验证关键漏洞根据模板ID找到对应的YAML文件理解其检测逻辑然后尝试用Burp Suite或浏览器手动复现请求分析响应。对于RCE远程代码执行、SQL注入等高危漏洞验证是必须的步骤。切勿将自动化工具的结果不经确认就直接上报。4. 中阶深入解剖Nuclei模板的YAML结构要真正驾驭Nuclei必须读懂并会写模板。一个Nuclei模板就是一个YAML文件其结构清晰主要包含以下几个部分。4.1 模板元信息ID、信息与分类这是模板的“身份证”和“说明书”。id: CVE-2021-44228-log4shell info: name: Apache Log4j2 Remote Code Injection (Log4Shell) author: pdteam severity: critical description: | Apache Log4j2 2.14.1 JNDI features used in configuration, log messages, and parameters do not protect against attacker controlled LDAP and other JNDI related endpoints. reference: - https://cve.mitre.org/cgi-bin/cvename.cgi?nameCVE-2021-44228 - https://nvd.nist.gov/vuln/detail/CVE-2021-44228 tags: cve,cve2021,log4j,rce,oast metadata: max-request: 2id: 模板的唯一标识符通常与CVE编号或漏洞特征相关。info: 包含漏洞名称、作者、严重性、描述、参考链接和标签。tags非常重要它决定了模板如何被过滤。metadata: 可包含一些控制信息比如max-request限制该模板最多发送的请求数。4.2 请求定义漏洞检测的“动作”这是模板的核心定义了要发送什么请求。http: - method: GET path: - {{BaseURL}}/api/actuator/gateway/routes headers: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 matchers-condition: and matchers: - type: word words: - route_id - Spring Cloud Gateway condition: andhttp: 表示这是一个HTTP协议模板。也可以是dns、tcp、file等。method: HTTP方法如 GET、POST、PUT。path: 请求路径。{{BaseURL}}是一个变量会被替换成实际的目标URL。headers: 可以自定义请求头用于绕过一些简单的WAF或匹配特定应用。matchers-condition和matchers: 定义如何判断响应中是否存在漏洞。上例中它检查响应体中是否同时包含“route_id”和“Spring Cloud Gateway”这两个关键词。4.3 匹配器与提取器判断与抓取匹配器Matchers用于判断请求是否成功即是否存在漏洞。提取器Extractors用于从响应中抓取有用的信息如版本号、令牌、内部路径。匹配器类型丰富word: 匹配关键词或短语。regex: 使用正则表达式匹配。status: 匹配HTTP状态码。size: 匹配响应体大小。dsl: 最强大的方式使用内置的DSL领域特定语言函数进行复杂判断如contains(body, “error”) status_code 500。一个复杂的匹配器示例matchers: - type: dsl dsl: - status_code 200 - contains(body, \password\) - !contains(body, \incorrect\) - len(body) 10000 condition: and这个匹配器要求状态码为200响应体包含“password”不包含“incorrect”且响应体长度小于10000字节。只有同时满足所有条件才判定为匹配成功。提取器示例extractors: - type: regex name: version part: body regex: - Version: (\\d\\.\\d\\.\\d) group: 1这个提取器会从响应体中通过正则表达式抓取类似“Version: 1.2.3”的字符串并将版本号“1.2.3”提取出来存储在变量version中可以在后续的请求或输出中使用。4.4 动态负载与变量让模板“活”起来静态的检测很容易被防御。Nuclei支持动态负载Payloads和变量Variables使得检测更具变化性和隐蔽性。负载Payloads常用于模糊测试Fuzzing或撞库。例如检测目录遍历时可以定义一个包含各种../组合的负载列表。http: - method: GET path: - {{BaseURL}}/download?file{{payload}} payloads: traversal: - ../../../etc/passwd - ....//....//....//etc/passwd - %2e%2e%2fetc%2fpasswd在请求中{{payload}}会被替换为payloads.traversal列表中的每一个值进行请求。变量Variables可以从先前的请求响应中提取值并用于后续请求实现链式检测。http: - method: GET path: - {{BaseURL}}/login extractors: - type: regex name: csrf_token part: body regex: - namecsrf_token value([^]) # 第一个请求获取CSRF令牌 - method: POST path: - {{BaseURL}}/login body: usernameadminpasswordadmincsrf_token{{csrf_token}} # 第二个请求使用提取到的令牌这种能力使得Nuclei可以处理需要多步骤交互的复杂漏洞检测场景如需要先登录再访问的管理后台漏洞。5. 高阶实战编写你的第一个自定义模板现在让我们动手为一个假设的漏洞编写一个检测模板。假设我们发现一个名为“SimpleCMS”的系统其/admin/export?type参数存在SQL注入当参数值为user时错误回显会暴露数据库路径。5.1 规划模板逻辑目标检测SimpleCMS /admin/export接口的SQL注入漏洞。检测方法发送一个带有恶意负载的GET请求触发数据库错误并在响应中寻找特征字符串。特征错误响应中可能包含“MySQL”和“near”等关键词。避免误报确保只在存在“SimpleCMS”标识的页面上进行检测。5.2 编写YAML模板我们将模板保存为simplecms-sqli.yaml。id: simplecms-admin-export-sqli info: name: SimpleCMS Admin Export SQL Injection author: your-name severity: high description: SQL Injection vulnerability in the export functionality of SimpleCMS admin panel. reference: - https://example.com/simplecms-advisory tags: sqli,simplecms,admin # 首先发送一个正常请求来确认目标是SimpleCMS http: - method: GET path: - {{BaseURL}}/admin/ # 第一个请求的匹配器确认是SimpleCMS后台 matchers-condition: and matchers: - type: word words: - SimpleCMS Admin Panel - Logout condition: and part: body # 只有第一个请求匹配成功即确认是目标系统才会发送第二个注入检测请求 - method: GET path: - {{BaseURL}}/admin/export?typeuser AND 11 UNION SELECT 1,2,3-- # 第二个请求的匹配器检测SQL错误回显 matchers-condition: and matchers: - type: word words: - MySQL - near - syntax condition: or part: body - type: status status: - 200 # 即使出错有些应用也返回200但body里有错误信息代码解读与实操要点分阶段检测模板包含了两个HTTP请求块。Nuclei会顺序执行它们并且第二个请求只有在第一个请求的所有匹配器都成功时才会发送。这是一种“预检测”机制能有效减少对非目标系统的无效请求提升扫描效率和隐蔽性。条件逻辑第一个匹配器使用condition: and要求页面必须同时包含“SimpleCMS Admin Panel”和“Logout”两个词。第二个匹配器使用condition: or只要响应体中出现“MySQL”、“near”、“syntax”中的任何一个词就认为可能触发了SQL错误。负载设计注入负载user AND 11 UNION SELECT 1,2,3--是一个经典的基于联合查询的探测载荷。在实际编写时你可能需要根据目标的数据库类型MySQL, PostgreSQL, SQL Server调整负载和匹配的关键词。5.3 测试与调试模板编写完成后不要直接用于大规模扫描。先在小范围测试。# 使用 -validate 参数验证模板语法 nuclei -validate -t simplecms-sqli.yaml # 对单个测试目标运行该模板 nuclei -u http://test-simplecms.local -t simplecms-sqli.yaml -debug # 使用 -debug 参数它会显示发送的请求和接收的响应这对于调试匹配逻辑至关重要。观察-debug的输出。检查请求的URL是否正确构建服务器的实际响应是什么你期望匹配的关键词是否出现在响应体的正确位置你可能需要反复调整匹配器的words、part可以是body、header、all和condition直到检测准确率达到满意水平。6. 工程化与高级技巧当你能熟练编写单个模板后下一步就是思考如何将Nuclei集成到更庞大的安全体系中并运用一些高级功能来应对复杂场景。6.1 工作流模板编排复杂的多步骤检测有些漏洞的检测需要多个步骤比如先爆破登录口再用获取到的Cookie访问敏感接口。单个HTTP请求块难以处理这种带状态的操作。这时就需要“工作流模板”。id: workflow-bruteforce-admin-then-dump info: name: Admin BruteForce and Data Dump Workflow severity: high # workflows 部分用于定义多个模板的执行顺序和逻辑 workflows: - template: /path/to/generic-login-bruteforce.yaml # 第一个模板爆破登录 matchers: - name: login-success type: word words: - Welcome, admin # 定义输出变量将爆破成功后的会话Cookie传递给下一个模板 outputs: session_cookie: {{cookie}} - template: /path/to/admin-data-dump.yaml # 第二个模板使用上一个模板输出的cookie来访问管理接口 # 条件只有第一个模板的 login-success 匹配器成功才会执行此模板 condition: {{login-success}} # 注入变量将 session_cookie 作为变量传递给第二个模板 variables: auth_cookie: {{session_cookie}}工作流模板通过condition和outputs/variables实现了模板间的数据传递和条件执行能够构建出非常复杂的攻击链模拟。6.2 集成与自动化融入CI/CD和安全流程Nuclei不是孤立的工具它可以成为你安全自动化流水线的一环。与Httpx联动ProjectDiscovery自家的httpx是一个优秀的HTTP探测工具。通常的流程是使用子域名枚举工具如subfinder、assetfinder获取目标列表然后用httpx进行存活探测和基础信息获取标题、状态码、技术栈最后将存活的URL喂给nuclei。subfinder -d target.com -silent | httpx -silent | nuclei -t exposures/ -o results.txtCI/CD集成你可以在GitLab CI、GitHub Actions或Jenkins的Pipeline中集成Nuclei扫描。例如在每次代码部署到测试环境后自动运行一组针对该应用技术栈如-tags wordpress的漏洞模板并将结果以注释形式提交到Merge Request中或发送到安全团队频道。# 示例 GitHub Actions 步骤 - name: Nuclei Security Scan uses: projectdiscovery/nuclei-actionmain with: target: ${{ env.STAGING_URL }} templates: cves/ severity: critical,high output: nuclei-results.json结果上报使用-json或-jsonl输出然后编写脚本将结果解析并导入到Jira、DefectDojo、Elasticsearch等系统中实现漏洞生命周期的闭环管理。6.3 性能调优与资源控制扫描大型资产时如上万个子域名性能配置不当会导致扫描时间过长或本地资源耗尽。速率限制-rate-limit和-bulk-size是保护目标服务的首要参数。对于外部目标建议从-rate-limit 30 -bs 10开始。并发控制-c控制模板并发数-bs控制主机并发数。如果你的机器CPU核心多、网络好可以适当调高如-c 100 -bs 50。但要注意过高的并发可能导致本地文件描述符耗尽或内存不足。使用-timeout和-retries处理网络超时。使用项目模式-project参数会让Nuclei在/tmp或-project-path指定路径下创建一个项目目录缓存已发送的请求。当针对同一目标运行多个模板或多个扫描任务时这可以避免重复发送相同的探测请求如对/robots.txt的请求显著提升效率。资源监控在长时间扫描时使用-stats和-stats-interval 10参数让Nuclei每隔10秒输出一次统计信息包括请求数、错误数、匹配数等方便你监控扫描状态。7. 常见问题排查与实战心得即使对工具很熟悉在实际操作中依然会遇到各种“坑”。这里记录一些典型问题和我的处理经验。7.1 扫描速度异常缓慢可能原因1DNS解析慢。特别是扫描大量域名时DNS查询会成为瓶颈。解决方案使用-r参数指定一个快速的DNS解析器列表文件如公共DNS8.8.8.8或启用-system-resolvers回退到系统DNS。更好的做法是提前用dnsx等工具解析好域名直接给Nuclei提供IP地址。可能原因2模板过多或存在“重型”模板。一些模板可能包含复杂的JavaScript解析或Headless浏览器操作极其耗时。解决方案使用-exclude-tags headless,js排除这些模板。或者先运行快速扫描-tags quick如果模板有该标签再针对性地运行深度扫描。可能原因3网络延迟或目标响应慢。解决方案适当增加-timeout如30秒减少-rate-limit和-c、-bs的值。7.2 误报率过高可能原因1模板匹配条件过于宽松。很多通用指纹识别或信息泄露模板可能匹配到一些相似但无关的页面。解决方案这是社区模板的固有特点。务必进行人工验证。对于内部使用你可以克隆社区模板库修改那些误报高的模板收紧其匹配条件例如增加matchers-condition: and的条目或使用更精确的dsl正则匹配。可能原因2目标应用返回了通用错误页面。许多应用在遇到不存在的路径或参数错误时会返回一个包含“error”、“not found”等词的定制化错误页这可能被一些模板误判为漏洞。解决方案编写模板时尽量使用组合条件避免仅靠单个关键词判断。可以利用dsl匹配器结合状态码、响应头、正文长度和特定关键词进行综合判断。7.3 漏报该发现的没发现可能原因1目标需要认证而模板未处理。大部分社区模板是针对未授权接口的。解决方案使用-H参数添加认证Cookie或Token头例如nuclei -u https://target.com -H “Cookie: sessionabc123”。对于复杂的OAuth或JWT流程可能需要先编写一个工作流模板来获取令牌。可能原因2目标使用了现代前端框架如React, Vue路径是动态的。传统的基于路径的模板可能无法触发。解决方案结合使用-headless参数运行浏览器渲染的模板或者使用katana、gau等工具先爬取目标的实际请求再将爬取到的URL列表交给Nuclei扫描。可能原因3WAF/IPS拦截了扫描请求。解决方案使用-rate-limit降低请求频率增加随机延迟目前Nuclei原生不支持但可通过外部脚本控制。修改-H中的User-Agent为更常见的浏览器标识。对于深度测试可能需要使用代理池。7.4 模板编写与调试心得从模仿开始不要从零开始写模板。在~/.config/nuclei/templates目录下找到与你目标漏洞类似的模板复制一份进行修改这是最快的学习路径。善用-debug和-store-resp-debug在终端输出请求响应适合快速调试。-store-resp会将所有请求和响应保存到文件默认output目录方便你仔细分析。测试环境是关键永远不要在未授权的情况下对生产系统测试新编写的模板。搭建一个与目标相似的测试环境例如用Docker快速拉起一个存在漏洞的旧版Web应用在测试环境验证模板的准确性和安全性。关注DSL函数Nuclei内置的DSL函数非常强大如contains、len、regex、to_number等。掌握它们可以写出逻辑更严谨的匹配条件。使用nuclei -list-dsl-function可以查看所有支持的函数。掌握Nuclei模板的编写本质上是在学习如何将安全测试人员的经验、对漏洞原理的理解转化为机器可读、可重复执行的规则。这个过程会不断加深你对漏洞本身、对HTTP协议、对Web应用行为的认知。它不再是一个“黑盒”工具而成为了你手臂的延伸。当你看到自己编写的模板在庞大的资产中精准地定位到一个深藏的安全隐患时那种成就感远非单纯运行一个扫描命令可比。安全之路始于工具终于能力。希望这篇指南能成为你从Nuclei使用者迈向安全自动化构建者的坚实一步。
从零掌握Nuclei:自动化漏洞扫描与自定义模板编写实战指南
1. 项目概述为什么你需要掌握Nuclei如果你是一名安全工程师、渗透测试人员或者是一名负责应用安全的开发者那么“自动化漏洞扫描”这个词对你来说一定不陌生。在当今快节奏的开发和部署环境中手动测试早已无法覆盖海量的资产和层出不穷的漏洞。我们需要一个像瑞士军刀一样趁手、高效且精准的工具来帮助我们自动化地发现那些潜在的安全风险。这就是Nuclei诞生的背景也是它迅速成为安全圈内“顶流”的原因。简单来说Nuclei是一个基于YAML模板的现代化漏洞扫描器。它的核心思想非常巧妙将漏洞检测的逻辑比如发送什么请求、如何判断响应中存在漏洞封装在一个个独立的YAML文件中这些文件就是“模板”。社区里的安全研究员们不断贡献和维护着成千上万个模板覆盖了从最新的CVE到常见的配置错误等各种场景。你只需要告诉Nuclei“扫描谁”和“用什么模板”它就能自动完成所有检测工作。这听起来是不是有点像拥有了一个由全球安全专家组成的、不知疲倦的自动化团队但Nuclei的魅力远不止于此。它的真正威力在于“自定义”。当面对一个全新的、社区模板库中尚未覆盖的漏洞或内部特有的应用逻辑时你能自己动手编写模板将你的安全知识固化为可重复执行的自动化检测脚本。从“使用工具”到“创造工具”这中间的跨越正是从安全工具使用者进阶为安全能力构建者的关键一步。本指南的目的就是带你从零开始不仅学会如何运行Nuclei更要深入理解其模板引擎最终能够独立编写出高效、精准的自定义漏洞检测模板将自动化安全测试真正融入你的工作流。2. 环境搭建与核心概念解析在开始编写或运行任何模板之前我们需要一个稳固的“作战基地”。Nuclei的安装过程非常简单但其背后的一些核心概念和配置选项决定了你后续使用的效率和体验。2.1 安装Nuclei不止一种方式最推荐的方式是使用Go语言包管理器直接安装这能确保你获得最新的稳定版本go install -v github.com/projectdiscovery/nuclei/v3/cmd/nucleilatest安装完成后在终端输入nuclei -version来验证安装是否成功。你会看到类似v3.2.0的版本号输出。除了Go安装官方也提供了适用于Windows、macOS和Linux的预编译二进制包你可以直接从GitHub Releases页面下载解压使用。注意如果你身处网络环境受限的区域使用go install可能会因为无法访问github.com而失败。这时预编译二进制包是更稳妥的选择。下载后记得将其所在目录添加到系统的PATH环境变量中。安装只是第一步。Nuclei的强大功能依赖于其庞大的模板库。首次运行任何扫描命令时Nuclei会自动下载最新的社区模板到本地默认在~/.config/nuclei/templates目录下。你可以通过nuclei -update-templates命令手动更新模板库。理解这个目录结构很重要模板按协议HTTP、DNS、TCP等和类别CVE、漏洞、配置错误等组织。当你需要查找或参考某个特定漏洞的检测方法时直接翻阅这些YAML文件是最好的学习途径。2.2 理解Nuclei的“工作流”模板、目标与输出运行一个最基本的扫描命令例如nuclei -u https://example.com背后发生了什么呢目标解析Nuclei首先会解析你提供的目标-u或-l参数。对于URL它会自动进行标准化处理。模板加载与过滤接着它会加载本地的模板库。如果没有指定-t参数默认会运行所有符合条件的模板。你可以通过-tags、-severity、-author等参数进行精细过滤例如nuclei -u https://example.com -tags cve,apache -severity critical,high只运行标记为CVE、Apache相关且严重性为高危或严重的模板。并发执行Nuclei采用高度并发的设计。-c参数控制并行执行的模板数量-bs控制每个模板并行扫描的主机数量。合理调整这两个参数例如-c 50 -bs 25可以在不压垮目标服务的前提下极大提升扫描速度。请求与匹配对于每个模板Nuclei会按照其定义向目标发送HTTP、TCP、DNS等协议请求。然后使用模板中定义的“匹配器”matchers和“提取器”extractors来分析响应。结果输出一旦匹配成功Nuclei就会按照你指定的格式默认CLI输出或通过-json、-markdown-export指定文件报告漏洞。这里有一个非常关键的实操心得初次对一个生产环境目标进行全量扫描时务必使用-rate-limit参数限制请求速率并加上-headless参数如果目标有大量JavaScript渲染内容。一个激进的命令可能是nuclei -u https://prod-app.com -rate-limit 50。先以较低的速率进行试探性扫描观察目标服务的响应和负载情况再逐步调整并发参数。盲目进行高并发扫描不仅可能触发对方的WAFWeb应用防火墙封禁更有可能对线上服务造成拒绝服务DoS影响这是安全测试中的大忌。3. 初阶实战运行你的第一次扫描理论说得再多不如动手跑一遍。我们从最简单的场景开始逐步增加复杂度让你直观感受Nuclei的能力。3.1 单目标与多目标扫描对单个网站进行快速安全健康检查nuclei -u https://target-company.com -o initial_scan_results.txt这个命令会对target-company.com运行所有默认模板并将结果保存到initial_scan_results.txt文件中。-o参数用于指定输出文件。在实际工作中我们更常面对的是资产列表。假设你有一个subdomains.txt文件里面是子域名枚举的结果app.target-company.com api.target-company.com admin.target-company.com dev.target-company.com使用-l参数进行批量扫描nuclei -l subdomains.txt -o batch_scan_results.json -json这里我们使用了-json参数输出格式为JSONL每行一个JSON对象这种格式非常适合后续导入到SIEM安全信息与事件管理系统或用于自动化脚本处理。3.2 模板过滤精准打击提升效率运行所有模板虽然全面但耗时且会产生大量无关输出尤其是针对静态博客和简单页面的检测。模板过滤是提升效率的核心技能。按标签过滤这是最常用的方式。社区模板都打上了丰富的标签如cve、xss、rce、misconfig、wordpress、java等。# 只扫描与Apache Struts和Spring框架相关的漏洞 nuclei -l targets.txt -tags struts,spring -o framework_scan.txt按严重性过滤在时间有限的应急响应中优先关注高危漏洞。nuclei -l urls.txt -severity critical,high -silent-silent参数让Nuclei只输出找到的漏洞不显示进度条等其他信息使输出更干净。按作者过滤如果你信任某位社区专家的模板质量可以专门运行他的模板。nuclei -u https://target.com -author geeknik排除特定模板或类型有时你想排除一些已知不适用或会产生干扰的检测。# 排除所有技术指纹识别tech-detect和信息类info低危模板 nuclei -l targets.txt -exclude-tags tech,info -exclude-severity low,info3.3 理解输出与结果解读Nuclei的默认CLI输出颜色丰富信息清晰。一条典型的漏洞输出如下[Critical] [CVE-2021-44228] [http] https://log4j-vuln-app.com/api/users它依次显示了[严重等级][模板ID/名称][协议][目标URL]。但对于报告和归档结构化格式更好。-json输出包含了最完整的信息如请求、响应、匹配到的数据、模板详情等。-markdown-export参数则能生成一个包含漏洞详情、复现步骤和修复建议的完整Markdown报告目录非常适合直接用于编写渗透测试报告。注意事项Nuclei的扫描结果尤其是使用社区模板时可能存在误报。一个模板报告了漏洞绝不意味着百分百存在。安全工程师的核心价值之一就是“研判”。你需要手动验证关键漏洞根据模板ID找到对应的YAML文件理解其检测逻辑然后尝试用Burp Suite或浏览器手动复现请求分析响应。对于RCE远程代码执行、SQL注入等高危漏洞验证是必须的步骤。切勿将自动化工具的结果不经确认就直接上报。4. 中阶深入解剖Nuclei模板的YAML结构要真正驾驭Nuclei必须读懂并会写模板。一个Nuclei模板就是一个YAML文件其结构清晰主要包含以下几个部分。4.1 模板元信息ID、信息与分类这是模板的“身份证”和“说明书”。id: CVE-2021-44228-log4shell info: name: Apache Log4j2 Remote Code Injection (Log4Shell) author: pdteam severity: critical description: | Apache Log4j2 2.14.1 JNDI features used in configuration, log messages, and parameters do not protect against attacker controlled LDAP and other JNDI related endpoints. reference: - https://cve.mitre.org/cgi-bin/cvename.cgi?nameCVE-2021-44228 - https://nvd.nist.gov/vuln/detail/CVE-2021-44228 tags: cve,cve2021,log4j,rce,oast metadata: max-request: 2id: 模板的唯一标识符通常与CVE编号或漏洞特征相关。info: 包含漏洞名称、作者、严重性、描述、参考链接和标签。tags非常重要它决定了模板如何被过滤。metadata: 可包含一些控制信息比如max-request限制该模板最多发送的请求数。4.2 请求定义漏洞检测的“动作”这是模板的核心定义了要发送什么请求。http: - method: GET path: - {{BaseURL}}/api/actuator/gateway/routes headers: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 matchers-condition: and matchers: - type: word words: - route_id - Spring Cloud Gateway condition: andhttp: 表示这是一个HTTP协议模板。也可以是dns、tcp、file等。method: HTTP方法如 GET、POST、PUT。path: 请求路径。{{BaseURL}}是一个变量会被替换成实际的目标URL。headers: 可以自定义请求头用于绕过一些简单的WAF或匹配特定应用。matchers-condition和matchers: 定义如何判断响应中是否存在漏洞。上例中它检查响应体中是否同时包含“route_id”和“Spring Cloud Gateway”这两个关键词。4.3 匹配器与提取器判断与抓取匹配器Matchers用于判断请求是否成功即是否存在漏洞。提取器Extractors用于从响应中抓取有用的信息如版本号、令牌、内部路径。匹配器类型丰富word: 匹配关键词或短语。regex: 使用正则表达式匹配。status: 匹配HTTP状态码。size: 匹配响应体大小。dsl: 最强大的方式使用内置的DSL领域特定语言函数进行复杂判断如contains(body, “error”) status_code 500。一个复杂的匹配器示例matchers: - type: dsl dsl: - status_code 200 - contains(body, \password\) - !contains(body, \incorrect\) - len(body) 10000 condition: and这个匹配器要求状态码为200响应体包含“password”不包含“incorrect”且响应体长度小于10000字节。只有同时满足所有条件才判定为匹配成功。提取器示例extractors: - type: regex name: version part: body regex: - Version: (\\d\\.\\d\\.\\d) group: 1这个提取器会从响应体中通过正则表达式抓取类似“Version: 1.2.3”的字符串并将版本号“1.2.3”提取出来存储在变量version中可以在后续的请求或输出中使用。4.4 动态负载与变量让模板“活”起来静态的检测很容易被防御。Nuclei支持动态负载Payloads和变量Variables使得检测更具变化性和隐蔽性。负载Payloads常用于模糊测试Fuzzing或撞库。例如检测目录遍历时可以定义一个包含各种../组合的负载列表。http: - method: GET path: - {{BaseURL}}/download?file{{payload}} payloads: traversal: - ../../../etc/passwd - ....//....//....//etc/passwd - %2e%2e%2fetc%2fpasswd在请求中{{payload}}会被替换为payloads.traversal列表中的每一个值进行请求。变量Variables可以从先前的请求响应中提取值并用于后续请求实现链式检测。http: - method: GET path: - {{BaseURL}}/login extractors: - type: regex name: csrf_token part: body regex: - namecsrf_token value([^]) # 第一个请求获取CSRF令牌 - method: POST path: - {{BaseURL}}/login body: usernameadminpasswordadmincsrf_token{{csrf_token}} # 第二个请求使用提取到的令牌这种能力使得Nuclei可以处理需要多步骤交互的复杂漏洞检测场景如需要先登录再访问的管理后台漏洞。5. 高阶实战编写你的第一个自定义模板现在让我们动手为一个假设的漏洞编写一个检测模板。假设我们发现一个名为“SimpleCMS”的系统其/admin/export?type参数存在SQL注入当参数值为user时错误回显会暴露数据库路径。5.1 规划模板逻辑目标检测SimpleCMS /admin/export接口的SQL注入漏洞。检测方法发送一个带有恶意负载的GET请求触发数据库错误并在响应中寻找特征字符串。特征错误响应中可能包含“MySQL”和“near”等关键词。避免误报确保只在存在“SimpleCMS”标识的页面上进行检测。5.2 编写YAML模板我们将模板保存为simplecms-sqli.yaml。id: simplecms-admin-export-sqli info: name: SimpleCMS Admin Export SQL Injection author: your-name severity: high description: SQL Injection vulnerability in the export functionality of SimpleCMS admin panel. reference: - https://example.com/simplecms-advisory tags: sqli,simplecms,admin # 首先发送一个正常请求来确认目标是SimpleCMS http: - method: GET path: - {{BaseURL}}/admin/ # 第一个请求的匹配器确认是SimpleCMS后台 matchers-condition: and matchers: - type: word words: - SimpleCMS Admin Panel - Logout condition: and part: body # 只有第一个请求匹配成功即确认是目标系统才会发送第二个注入检测请求 - method: GET path: - {{BaseURL}}/admin/export?typeuser AND 11 UNION SELECT 1,2,3-- # 第二个请求的匹配器检测SQL错误回显 matchers-condition: and matchers: - type: word words: - MySQL - near - syntax condition: or part: body - type: status status: - 200 # 即使出错有些应用也返回200但body里有错误信息代码解读与实操要点分阶段检测模板包含了两个HTTP请求块。Nuclei会顺序执行它们并且第二个请求只有在第一个请求的所有匹配器都成功时才会发送。这是一种“预检测”机制能有效减少对非目标系统的无效请求提升扫描效率和隐蔽性。条件逻辑第一个匹配器使用condition: and要求页面必须同时包含“SimpleCMS Admin Panel”和“Logout”两个词。第二个匹配器使用condition: or只要响应体中出现“MySQL”、“near”、“syntax”中的任何一个词就认为可能触发了SQL错误。负载设计注入负载user AND 11 UNION SELECT 1,2,3--是一个经典的基于联合查询的探测载荷。在实际编写时你可能需要根据目标的数据库类型MySQL, PostgreSQL, SQL Server调整负载和匹配的关键词。5.3 测试与调试模板编写完成后不要直接用于大规模扫描。先在小范围测试。# 使用 -validate 参数验证模板语法 nuclei -validate -t simplecms-sqli.yaml # 对单个测试目标运行该模板 nuclei -u http://test-simplecms.local -t simplecms-sqli.yaml -debug # 使用 -debug 参数它会显示发送的请求和接收的响应这对于调试匹配逻辑至关重要。观察-debug的输出。检查请求的URL是否正确构建服务器的实际响应是什么你期望匹配的关键词是否出现在响应体的正确位置你可能需要反复调整匹配器的words、part可以是body、header、all和condition直到检测准确率达到满意水平。6. 工程化与高级技巧当你能熟练编写单个模板后下一步就是思考如何将Nuclei集成到更庞大的安全体系中并运用一些高级功能来应对复杂场景。6.1 工作流模板编排复杂的多步骤检测有些漏洞的检测需要多个步骤比如先爆破登录口再用获取到的Cookie访问敏感接口。单个HTTP请求块难以处理这种带状态的操作。这时就需要“工作流模板”。id: workflow-bruteforce-admin-then-dump info: name: Admin BruteForce and Data Dump Workflow severity: high # workflows 部分用于定义多个模板的执行顺序和逻辑 workflows: - template: /path/to/generic-login-bruteforce.yaml # 第一个模板爆破登录 matchers: - name: login-success type: word words: - Welcome, admin # 定义输出变量将爆破成功后的会话Cookie传递给下一个模板 outputs: session_cookie: {{cookie}} - template: /path/to/admin-data-dump.yaml # 第二个模板使用上一个模板输出的cookie来访问管理接口 # 条件只有第一个模板的 login-success 匹配器成功才会执行此模板 condition: {{login-success}} # 注入变量将 session_cookie 作为变量传递给第二个模板 variables: auth_cookie: {{session_cookie}}工作流模板通过condition和outputs/variables实现了模板间的数据传递和条件执行能够构建出非常复杂的攻击链模拟。6.2 集成与自动化融入CI/CD和安全流程Nuclei不是孤立的工具它可以成为你安全自动化流水线的一环。与Httpx联动ProjectDiscovery自家的httpx是一个优秀的HTTP探测工具。通常的流程是使用子域名枚举工具如subfinder、assetfinder获取目标列表然后用httpx进行存活探测和基础信息获取标题、状态码、技术栈最后将存活的URL喂给nuclei。subfinder -d target.com -silent | httpx -silent | nuclei -t exposures/ -o results.txtCI/CD集成你可以在GitLab CI、GitHub Actions或Jenkins的Pipeline中集成Nuclei扫描。例如在每次代码部署到测试环境后自动运行一组针对该应用技术栈如-tags wordpress的漏洞模板并将结果以注释形式提交到Merge Request中或发送到安全团队频道。# 示例 GitHub Actions 步骤 - name: Nuclei Security Scan uses: projectdiscovery/nuclei-actionmain with: target: ${{ env.STAGING_URL }} templates: cves/ severity: critical,high output: nuclei-results.json结果上报使用-json或-jsonl输出然后编写脚本将结果解析并导入到Jira、DefectDojo、Elasticsearch等系统中实现漏洞生命周期的闭环管理。6.3 性能调优与资源控制扫描大型资产时如上万个子域名性能配置不当会导致扫描时间过长或本地资源耗尽。速率限制-rate-limit和-bulk-size是保护目标服务的首要参数。对于外部目标建议从-rate-limit 30 -bs 10开始。并发控制-c控制模板并发数-bs控制主机并发数。如果你的机器CPU核心多、网络好可以适当调高如-c 100 -bs 50。但要注意过高的并发可能导致本地文件描述符耗尽或内存不足。使用-timeout和-retries处理网络超时。使用项目模式-project参数会让Nuclei在/tmp或-project-path指定路径下创建一个项目目录缓存已发送的请求。当针对同一目标运行多个模板或多个扫描任务时这可以避免重复发送相同的探测请求如对/robots.txt的请求显著提升效率。资源监控在长时间扫描时使用-stats和-stats-interval 10参数让Nuclei每隔10秒输出一次统计信息包括请求数、错误数、匹配数等方便你监控扫描状态。7. 常见问题排查与实战心得即使对工具很熟悉在实际操作中依然会遇到各种“坑”。这里记录一些典型问题和我的处理经验。7.1 扫描速度异常缓慢可能原因1DNS解析慢。特别是扫描大量域名时DNS查询会成为瓶颈。解决方案使用-r参数指定一个快速的DNS解析器列表文件如公共DNS8.8.8.8或启用-system-resolvers回退到系统DNS。更好的做法是提前用dnsx等工具解析好域名直接给Nuclei提供IP地址。可能原因2模板过多或存在“重型”模板。一些模板可能包含复杂的JavaScript解析或Headless浏览器操作极其耗时。解决方案使用-exclude-tags headless,js排除这些模板。或者先运行快速扫描-tags quick如果模板有该标签再针对性地运行深度扫描。可能原因3网络延迟或目标响应慢。解决方案适当增加-timeout如30秒减少-rate-limit和-c、-bs的值。7.2 误报率过高可能原因1模板匹配条件过于宽松。很多通用指纹识别或信息泄露模板可能匹配到一些相似但无关的页面。解决方案这是社区模板的固有特点。务必进行人工验证。对于内部使用你可以克隆社区模板库修改那些误报高的模板收紧其匹配条件例如增加matchers-condition: and的条目或使用更精确的dsl正则匹配。可能原因2目标应用返回了通用错误页面。许多应用在遇到不存在的路径或参数错误时会返回一个包含“error”、“not found”等词的定制化错误页这可能被一些模板误判为漏洞。解决方案编写模板时尽量使用组合条件避免仅靠单个关键词判断。可以利用dsl匹配器结合状态码、响应头、正文长度和特定关键词进行综合判断。7.3 漏报该发现的没发现可能原因1目标需要认证而模板未处理。大部分社区模板是针对未授权接口的。解决方案使用-H参数添加认证Cookie或Token头例如nuclei -u https://target.com -H “Cookie: sessionabc123”。对于复杂的OAuth或JWT流程可能需要先编写一个工作流模板来获取令牌。可能原因2目标使用了现代前端框架如React, Vue路径是动态的。传统的基于路径的模板可能无法触发。解决方案结合使用-headless参数运行浏览器渲染的模板或者使用katana、gau等工具先爬取目标的实际请求再将爬取到的URL列表交给Nuclei扫描。可能原因3WAF/IPS拦截了扫描请求。解决方案使用-rate-limit降低请求频率增加随机延迟目前Nuclei原生不支持但可通过外部脚本控制。修改-H中的User-Agent为更常见的浏览器标识。对于深度测试可能需要使用代理池。7.4 模板编写与调试心得从模仿开始不要从零开始写模板。在~/.config/nuclei/templates目录下找到与你目标漏洞类似的模板复制一份进行修改这是最快的学习路径。善用-debug和-store-resp-debug在终端输出请求响应适合快速调试。-store-resp会将所有请求和响应保存到文件默认output目录方便你仔细分析。测试环境是关键永远不要在未授权的情况下对生产系统测试新编写的模板。搭建一个与目标相似的测试环境例如用Docker快速拉起一个存在漏洞的旧版Web应用在测试环境验证模板的准确性和安全性。关注DSL函数Nuclei内置的DSL函数非常强大如contains、len、regex、to_number等。掌握它们可以写出逻辑更严谨的匹配条件。使用nuclei -list-dsl-function可以查看所有支持的函数。掌握Nuclei模板的编写本质上是在学习如何将安全测试人员的经验、对漏洞原理的理解转化为机器可读、可重复执行的规则。这个过程会不断加深你对漏洞本身、对HTTP协议、对Web应用行为的认知。它不再是一个“黑盒”工具而成为了你手臂的延伸。当你看到自己编写的模板在庞大的资产中精准地定位到一个深藏的安全隐患时那种成就感远非单纯运行一个扫描命令可比。安全之路始于工具终于能力。希望这篇指南能成为你从Nuclei使用者迈向安全自动化构建者的坚实一步。