
网络安全应用安全漏洞扫描【免费下载链接】nucleiNuclei is a fast, customizable vulnerability scanner powered by the global security community and built on a simple YAML-based DSL, enabling collaboration to tackle trending vulnerabilities on the internet. It helps you find vulnerabilities in your applications, APIs, networks, DNS, and cloud configurations.项目地址https://gitcode.com/GitHub_Trending/nu/nuclei点击查看免费下载本篇技术指南以 pkg/tmplexec/multiproto/README.md 为骨架深入剖析 Nuclei 多协议模板的执行引擎 multiproto从模板解析时协议顺序的保留到各协议请求的排队执行、动态值在协议间的传递再到模板上下文TemplateCtx的共享机制最后给出为任意新协议接入多协议执行逻辑的三处关键语句。读完本文你将掌握 Nuclei 中「DNS → HTTP」「DNS → SSL → HTTP」这类多协议联动模板的底层工作原理并具备在自己的协议实现中接入该执行模型的能力。一、为什么需要 multiproto单协议引擎的局限Nuclei 模板可以同时声明多种协议请求如dns、http、ssl、network、whois、code、websocket等。单个协议各自的执行逻辑彼此独立但当一个模板的后续协议需要依赖前面协议提取出的响应数据时例如先做 DNS 解析拿到 CNAME再用 HTTP 请求验证就必须有一个「跨越协议边界」的执行引擎来统筹。从 pkg/tmplexec/exec.go 的引擎选择逻辑可以清晰看到这个分工// only use generic if there is only 1 protocol with only 1 section if len(requests) 1 { e.engine generic.NewGenericEngine(requests, options, e.results) } else { e.engine multiproto.NewMultiProtocol(requests, options, e.results) }generic 引擎只处理「单协议、单 section」的模板走各协议自身的直接执行路径multiproto 引擎一旦模板包含多个协议的请求队列Nuclei 就会切换到MultiProtocol执行引擎。README 中强调的「模板反序列化时协议顺序被保留并原样传给 Executor」正是这一分工的前提模板文件中先声明的协议会按顺序进入请求队列并依次执行。二、multiproto 的构成与编译阶段MultiProtocol引擎定义在 pkg/tmplexec/multiproto/multi.gotype MultiProtocol struct { requests []protocols.Request // 待执行的协议请求队列 options *protocols.ExecutorOptions results *atomic.Bool readOnlyArgs map[string]interface{} // 编译后即可用的只读参数 readOnlyVars map[string]interface{} // 模板自有的只读变量readOnlyArgs 的子集 }NewMultiProtocol(requests, options, results)负责创建引擎Compile()负责在编译阶段完成变量求值的预计算通过generators.BuildPayloadFromOptions收集 CLI/环境变量等 option 变量结合模板variables段的常量与变量构建变量求值作用域并求值把求值结果拆分为readOnlyArgs全部可用参数与readOnlyVars仅模板自有的变量子集剔除与常量、option 变量同名的 key。这部分逻辑在 multi_internal_test.go 中有对应的单测覆盖常量constant_key、选项option_key以及模板变量template_key的合并与遮蔽优先级均被断言验证。Compile()末尾的注释「no need to load files since they are done at template level」说明文件类资源在模板层已加载完毕此处无需重复处理。三、执行阶段协议队列的顺序执行与动态值注入README 的「Execution」一节指出多协议模板执行时队列中的全部协议请求按顺序执行且提取出的动态值会被加入模板上下文。这在ExecuteWithResults中体现为一段清晰的循环multi.go执行前把readOnlyArgs、readOnlyVars以及所有输入参数合并进模板上下文供队列中的每个协议读取逐协议执行为每个请求克隆输入ctx.Input.Clone()并按协议类型对输入做转换InputHelper.Transform保证同一目标对不同协议使用合适的输入形态如 DNS 用域名、SSL 用主机名收集动态值协议执行回调中若OperatorsResult.DynamicValues非空即模板中用internal: true提取器标记的值则将其写入模板上下文供后续协议使用变量重求值每个协议执行完毕后基于最新模板上下文重新求值变量保证下一轮协议能读到最新数据。3.1 internal 提取值的多值索引规则动态值写入模板上下文时有一条值得注意的索引规则multi.go若某动态值数组只有一个元素直接以原 key 写入若包含多个值如[]string{a,b,c}则第一个值写入dynamic其余依次写入dynamic1、dynamic2首个索引被有意留空以兼容「不确定提取数量」的场景。代码注释同时指出iterate-all能力目前只在http协议中支持其他协议要支持遍历多值动态变量需要额外扩展或采用模板上下文专用逻辑这是一个已知的能力边界。3.2 SSL 握手错误的特殊处理循环内还有一个协议相关的例外当req.Type() types.SSLProtocol且错误信息包含protocol version not supported或could not do tls handshake时不中断整条协议链multi.go因为 TLS 握手失败本身是 SSL 探测的合法观测结果而同样的错误在 flow 模板中则被视为致命错误。这说明多协议引擎在错误处理上会针对协议语义做差异化对待。四、模板上下文 TemplateCtx跨协议的响应共享仓库README 的「Protocol Responses」一节是全文核心除了internal:true提取值各协议的响应字段也会被写入模板上下文且所有响应字段都以协议类型作为前缀如ssl_subject_dn。这套机制由ExecutorOptions上的三个方法实现位于 pkg/protocols/protocols.go。4.1 GetTemplateCtx按「模板 ID 输入」隔离的上下文存储func (e *ExecutorOptions) GetTemplateCtx(input *contextargs.MetaInput) *contextargs.Context { scanId : input.GetScanHash(e.TemplateID) // ... 从 templateCtxStore 取/建上下文 }模板上下文存放在templateCtxStore中以input.GetScanHash(e.TemplateID)为 key天然按「当前模板 当前目标输入」隔离避免了多目标并行扫描时上下文互相污染也顺带处理了并发同步问题。README 所说的「takes care of sync and other issues」正是落到这里。4.2 AddTemplateVars带协议前缀的响应字段写入func (e *ExecutorOptions) AddTemplateVars(input *contextargs.MetaInput, reqType templateTypes.ProtocolType, reqID string, vars map[string]interface{}) { if !e.IsMultiProtocol e.Flow { return // 非多协议模板、非 flow 模板时为 no-op } for k, v : range vars { if stringsutil.HasPrefixAny(k, templateTypes.SupportedProtocolsStrings()...) { templateCtx.Set(k, v) // 已带协议前缀的 key 直接写入 continue } if !stringsutil.EqualFoldAny(k, template-id, template-info, template-path) { if reqID ! { k reqID _ k } else if reqType templateTypes.InvalidProtocol { k reqType.String() _ k } templateCtx.Set(k, v) } } }关键行为可归纳为三点no-op 保护只有IsMultiProtocol为 true或为 flow 模板时响应字段才会被暴露到全局上下文单协议模板完全不受影响这也是「multiproto 逻辑被抽象化」的体现前缀命名key 优先使用请求 ID 作为前缀reqID_k否则回退为协议类型前缀如ssl_subject_dn、http_body、dns_cname。这就是 README 中ssl_subject_dn这类「模板类型前缀」名称的来源保留既有前缀如果 key 本身已带协议前缀继承自前一协议则原样写入不做二次前缀避免http_http_body这类重复前缀。4.3 AddTemplateCtxToVariablesScope让变量求值可见模板上下文func (e *ExecutorOptions) AddTemplateCtxToVariablesScope(input *contextargs.MetaInput, scope *variables.Scope) { if input nil || scope nil || !e.HasTemplateCtx(input) { return } templateCtx : e.GetTemplateCtx(input) scope.AddData(templateCtx.GetAll()) scope.AddTemplate(templateCtx.GetTemplateVariables()) }该方法是「语句 1」的底层实现将模板上下文整体并入变量求值作用域使后续协议的变量解析包括 DSL 表达式能看到前面协议产生的响应字段。五、为新协议接入多协议执行三处关键语句README 明确给出了向新实现协议中接入多协议执行逻辑的三处语句并强调「加入这三条语句即可处理所有相关逻辑」。下面结合现有协议源码逐一展开。语句 1将模板上下文并入变量表在协议的ExecuteWithResults方法中request.options.Variables.Evaluate求值之前把模板上下文的全部值合并进variablesMap。以 pkg/protocols/dns/request.go 为实例vars : protocolutils.GenerateDNSVariables(domain) optionVars : generators.BuildPayloadFromOptions(request.options.Options) scope : request.options.NewVariablesScope(vars, metadata, optionVars) request.options.AddTemplateCtxToVariablesScope(input.MetaInput, scope) scope.AddData(request.options.Constants) variablesMap : request.options.Variables.EvaluateScope(scope).Values这样 DNS 请求在构建时就能引用前面协议如 SSL写入的变量。其他协议如 pkg/protocols/http/build_request.go、pkg/protocols/websocket/websocket.go、pkg/protocols/ssl/ssl.go、pkg/protocols/network/request.go 均遵循同一模式。语句 2将响应字段暴露到模板上下文在响应映射responseToDSLMap等可用之后、执行匹配/提取之前调用AddTemplateVars把响应字段写入模板上下文。以 pkg/protocols/dns/request.go 为例outputEvent : request.responseToDSLMap(compiledRequest, response, domain, question, traceData, duration) // expose response variables in proto_var format // this is no-op if the template is not a multi protocol template request.options.AddTemplateVars(input.MetaInput, request.Type(), request.ID, outputEvent)同样的调用模式出现在 pkg/protocols/http/request.go、pkg/protocols/javascript/js.go、pkg/protocols/headless/request.go、pkg/protocols/network/request.go、pkg/protocols/whois/whois.go、pkg/protocols/offlinehttp/request.go 以及 pkg/protocols/code/code.go 中。语句 3把模板上下文合并回 outputEvent在匹配/提取之前把模板上下文的全部值合并进outputEvent使本协议的匹配器matchers与提取器extractors也能看到前面协议产生的字段// add variables from template context before matching/extraction if request.options.HasTemplateCtx(input.MetaInput) { outputEvent generators.MergeMaps(outputEvent, request.options.GetTemplateCtx(input.MetaInput).GetAll()) }在 pkg/protocols/dns/request.go 中该合并还会带上previous来自 workflow/前置模板的 internal 提取值与vars保证 DSL 匹配上下文完整。这一合并使用MergeMaps而非直接覆盖顺序上后写入的模板上下文会覆盖同名 key确保「前序协议数据优先」的语义。小结语句 1 解决「本协议发起请求前能读到前序数据」语句 2 解决「本协议响应数据能被后续协议读到」语句 3 解决「本协议匹配/提取阶段能引用前序数据」。三条语句组合起来就把任意协议无缝接入了多协议执行模型。六、实战示例DNS → HTTP 与 DNS → SSL → HTTP仓库自带的两个测试用例展示了多协议模板的真实写法它们也是 multi_test.go 中两个集成测试的直接素材。6.1 动态值联动DNS → HTTPtestcases/multiprotodynamic.yaml 演示了先发 DNS A 记录查询、再用 HTTP 请求校验并关联 DNS 结果的场景id: dns-http-dynamic-values info: name: multi protocol request with dynamic values author: pdteam severity: info dns: - name: {{FQDN}} # DNS Request type: a http: - method: GET # http request path: - {{BaseURL}} matchers: - type: dsl dsl: - body ok - dns_a 128.199.158.128 # check for A record (extracted information from dns response) condition: and注意 HTTP 协议的 DSL 匹配器中直接引用dns_a——这就是 DNS 响应字段经语句 2 写入模板上下文、又经语句 1/3 注入 HTTP 请求变量与匹配上下文后的结果。HTTP 匹配器把「HTTP body 为 ok」和「DNS A 记录等于目标 IP」两个条件用and组合实现跨协议联合判定。6.2 协议前缀联动DNS → SSL → HTTPtestcases/multiprotowithprefix.yaml 进一步演示了三种协议串联并验证了 README 所述的协议前缀命名规则id: dns-http-proto-prefix info: name: multi protocol request with dynamic values author: pdteam severity: info dns: - name: {{FQDN}} # DNS Request type: cname ssl: - address: {{Hostname}} # ssl request http: - method: GET # http request path: - {{BaseURL}} matchers: - type: dsl dsl: - contains(http_body, ProjectDiscovery) # check for http string - dns_cname cname.vercel-dns.com # check for cname (extracted information from dns response) - ssl_subject_cn cloud.projectdiscovery.io condition: and最终 HTTP 的匹配器同时引用了三个不同协议的字段http_bodyHTTP 自身响应、dns_cnameDNS CNAME 记录、ssl_subject_cnSSL 证书主题 CN。其中ssl_subject_cn正是 README 举例的「模板类型前缀」字段名——subject_cn加上ssl_前缀后存入模板上下文再被 HTTP 协议读取。执行顺序上模板先解析 DNS、再解析 SSL、最后发起 HTTP三者按队列顺序依次执行。6.3 测试验证multi_test.go 中TestMultiProtoWithDynamicExtractor解析multiprotodynamic.yaml断言Template.RequestsQueue长度为 2DNS HTTP编译并执行后结果为正TestMultiProtoWithProtoPrefix解析multiprotowithprefix.yaml断言请求队列长度为 3DNS SSL HTTP执行成功。这两个测试同时印证了「模板反序列化时多协议顺序被保留并进入RequestsQueue」这一 README 声明——测试直接检查Template.RequestsQueue的长度而ExecuteWithResults正是按该队列顺序逐协议执行的。七、例外与注意事项7.1 file 协议的例外设计README 明确指出file协议有意跳过语句 1 与语句 2原因有二file/dir 输入路径中目前不包含变量也未被用作路径变量因此无需从模板上下文读取数据来构建请求file 协议按行逐行扫描处理若执行语句 2把响应字段写入模板上下文会无意中把全部文件内容加载进上下文造成数据冗余。从当前仓库源码看pkg/protocols/file/request.go 在生成行数据后仍会调用AddTemplateVars与模板上下文合并语句 2、3 形态但file协议的核心边界——即不在变量求值阶段引入模板上下文语句 1——与 README 的例外说明一致。具体行为以你所用版本的实际代码为准。7.2 其他值得注意的边界模板上下文 store 的初始化GetTemplateCtx首次调用时若templateCtxStore为空会自动创建无需手动初始化只读参数的作用编译期readOnlyArgs/readOnlyVars在执行开始时整体合并进模板上下文随后各协议动态写入的字段在此基础上叠加flow 模板复用同一机制AddTemplateVars的 no-op 判断同时覆盖了IsMultiProtocol与Flow ! 两种情况说明 flow 模板同样受益于模板上下文机制前缀保留策略跨协议传递时已带协议前缀的 key 不会被二次加前缀避免命名膨胀。八、总结multiproto 是 Nuclei 多协议模板的执行后端它把模板中的协议请求按声明顺序排成队列逐项执行以模板上下文TemplateCtx为共享媒介让前序协议的响应字段dns_cname、ssl_subject_cn、http_body……可以被后续协议在请求构建、变量求值与匹配/提取阶段引用。对协议实现者而言只需在ExecuteWithResults中正确放置「读入模板上下文」「写入响应字段」「合并上下文回事件」三处语句即可让任意新协议无缝融入这套跨协议协作模型——这也是 README 所强调的「执行逻辑被抽象化」的核心设计。想要进一步深入可继续阅读 pkg/tmplexec/multiproto/multi.go、pkg/protocols/protocols.go 中的AddTemplateVars/GetTemplateCtx实现以及 pkg/tmplexec/multiproto/multi_test.go 与两个 testcases 中的真实多协议模板。赞分享网络安全应用安全漏洞扫描【免费下载链接】nucleiNuclei is a fast, customizable vulnerability scanner powered by the global security community and built on a simple YAML-based DSL, enabling collaboration to tackle trending vulnerabilities on the internet. It helps you find vulnerabilities in your applications, APIs, networks, DNS, and cloud configurations.项目地址https://gitcode.com/GitHub_Trending/nu/nuclei点击查看免费下载相关推荐Reachy Mini 开源机器人开发完整指南从零到一搭建你的桌面情感机器人Reachy Mini 开源机器人开发完整指南从零到一搭建你的桌面情感机器人 如果你正为开源机器人项目太多、文档太散、上手门槛高而头疼这篇 Reachy机器人人工智能语音计算机视觉智能硬件ComposeCharts企业级应用在大型项目中的架构设计与实践指南ComposeCharts企业级应用在大型项目中的架构设计与实践指南 ComposeCharts作为一款专为Jetpack Compose打造的动画化、高灵活nuclei模板类型多协议模板的自动识别与处理nuclei模板类型多协议模板的自动识别与处理 概述 在网络安全扫描领域nuclei作为一款基于YAML模板的高速漏洞扫描器其多协议模板功能代表了现代漏洞网络安全应用安全漏洞扫描上一篇终极Forge部署指南从本地开发到生产环境的完整路径下一篇yargs版本迁移终极指南从v16到v17的重大变更解析 创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考