Nuclei 学习笔记

[!NOTE] 痛苦做毕设中

准备认真弄下毕设,马上要中期答辩了.之前只是假设假设,纸上谈兵还是不行啊

扫描器的漏扫部分准备用Nuclei v3的SDK,掉包小子YYDS

之前以为写起来应该很简单,缝合一下就是了,但事情远出乎我的想象,果然还是得动手实操才行

介绍

Nuclei是一款社区驱动的漏洞扫描器,使用Go语言开发,可以说开源社区维护了这么久,功能也越来越完善了,社区维护POC的速度,以及不断适配的新功能,孩子早就馋它的体量了.

Nuclei使用零误报的定制模板向目标发送请求,同时可以对主机进行批量快速扫描。Nuclei提供TCP、DNS、HTTP、FILE等各类协议的扫描,通过强大且灵活的模板,可以使用Nuclei模拟各种安全检查。

可以说缝合得好,辅以合理的工作流,想必这个东西还是很好用的.
有一个想法就是用机器人盯着社区公开的一些0day情报,当出来的时候用一个ai自己去写对应的POC然后去扫描一些符合特征的资产,一般0day的效果都会很好,如果出洞了那么意味着poc的可信度还是比较高的,就这样让ai一点点去调整直到模板通过验证,应该能提高安全运营的效率.

当然毕设只是用来做快速的漏洞检测的,过一遍社区的POC就好了.

SDK

开发者主推的还是cli模式,但无奈搞安全的都喜欢自动化扫扫扫,与上面我的想法一样的或许更优想法的师傅估计还有很多,于是乎社区维护了一个SDK,用于集成到自己的golang自动化漏扫中去.
Nuclei SDK地址开发文档然后就什么也没有了,自己摸索去吧哈哈哈哈…
文档这块还是比较欠缺的,只有一个Go-Doc,对于要了解项目的一些细节几乎没有帮助,只能帮帮你去看某个func有啥用,那我还不如直接看IDE的代码提示.

还有一点就是AI,好像几个平台的AI对于这个SDK的用法都是错的,经常出现一个莫须有的函数让你去使用,然后一通乱解释.最终的结果就是: 对不起这点需求无法满足,要你绕一圈去实现某个需求,显然这是因为社区的资料太少了,AI也没法学
我猜估计是开发者觉得这个项目还是不够完美,还在积极更新过程中,可能一些实现在经常变更,所以没空写文档?
那么就只好自己来学了咯哈哈哈哈,其实projectdiscovery里几个项目都还挺好的,算是编码实现质量很高的安全工具仓库了!

毕设中我是有以下几个需求的:

  1. 给个资产能快速扫描;

  2. 能够对POC进行分类,并且可随时自定义加载自己的POC;

  3. 能够对扫描器中的Client做一些参数修改,比如超时时间,代理,可自定义回调函数等等;

  4. 做一个扫描流量收集器,为后续的AI分析提供原始数据源(先这样存到数据库,要用的时候去查对应的流量,大不大先不管了!);

上述几个需求其实社区的SDK已经完美的帮我实现了,尤其是后面几个,可以说实现的还很不错.
捣鼓了几个小时的我,再也不能轻信AI的提示了,还不如自己老老实实去看作者在代码里的注释,虽然文档不行,但是代码里的注释还是有的,还比较详细.

Github仓库就给了两个示例:

大概能看出来提供了两个New方法,一个线程安全的,一个已经被弃用了QAQ,在新版应该是NewNucleiEngineCtx 带ctx上下文的初始化方法.
从这可以看出来文档写的真简陋吧…,除了codeql学的这么艰难外,就是这个玩意儿了,只能自己去啃文档.

然后下载好SDK的我是调试又是搜的,大致摸清了它的逻辑.
前几天补了以下Go的常见设计模式还是有用的,在这个项目里,作者用了比较多的设计模式,编码水平这块很高!
最常见的就是建造者模式和function option模式还有责任链模式了.

坑1

启动时老爱自己检查对于的POC文件,一般是放在家目录,当然这一坨很大,我想自定义它的位置,官方没提供Api去初始化因此翻了下对于的config结构体,直接给出如下代码

1
2
3
// 设置对应的nuclei扫描模板文件,建议自己下载  
os.Setenv("NUCLEI_TEMPLATES", "D:\\Sec\\source\\nuclei-templates")
nuclei.DefaultConfig.TemplatesDirectory = "D:\\Sec\\source\\nuclei-templates" // 指定为自己存放poc文件的位置,这样就不会出现启动前去家目录进行检查并拉取POC

坑2

小写处理! 最讨厌的就是这种默认处理但是又不写出来提示的,真的很烦!
在初始化扫描引擎的时候nuclei提供了一系列Withxxx函数供初始化.
其中就有一个链式过滤POC文件的选项,作用就是选择符合标签的POC去进行扫描比如下面的条件就是选择作者栏是"eviden"的poc进行扫描

1
2
3
nuclei.WithTemplateFilters(nuclei.TemplateFilters{ // 添加一些过滤器,可从多维度,在生成扫描任务时可以供选择  
Authors: []string{"eviden"}, // 会默认处理为小写,参考 tag_filter.go splitCommaTrim(value string) []string 的细节
}),

可以通过如下方式获取到加载的Templates信息

1
2
3
4
templates := nucleiEngine.GetTemplates()  

fmt.Printf("Loaded templates: %d\n", len(templates))
log.Info(templates[0].Info.Authors.String()) // 输出为小写

然后就发现默认处理居然是小写,跟进到tag_filter.go splitCommaTrim即可看到细节,就不多讲了.

好的地方

1
2
func (e *NucleiEngine) ExecuteCallbackWithCtx(ctx context.Context, callback ...func(event *output.ResultEvent))
func (e *NucleiEngine) ExecuteWithCallback(callback ...func(event *output.ResultEvent)) error

可以看到提供了一个带回调函数和带ctx上下文的执行器.
先用用只带回调函数的这个其中的ResultEvent结构体是什么都有了然后我们在这儿可以做流量信息收集,甚至还可以写个回调通知函数直接发到远程,反正自由度很高!

1
2
3
4
5
6
7
err = nucleiEngine.ExecuteWithCallback(func(event *output.ResultEvent) {  
log.Info("发送请求: ", event.Request, "收到响应: ", event.Response)
vulName := event.Info.Name
vulDescription := event.Info.Description
detectedURL := event.URL + event.Path
log.Logf(logger.INFO, fmt.Sprintf("在 %s 发现 %s 漏洞\n漏洞描述:%s", detectedURL, vulName, vulDescription))
})

参考

Slack/core/webscan/callnuclei.go at eecf6b4239037dea5edb38570522a8b7bcc226eb · only9464/Slack · GitHub