Skip to main content

lib_nuclei

[nuclei] 赋予 Yak 漏扫能力

本身 Yak 并不具备漏洞扫描能力,但是作为一门希望一站式解决安全研发需求的语言,如果能在语言/语言库层面集成某一些具有成熟生态的漏洞扫描能力其实是非常令人激动的。

res, err := nuclei.Scan(cli.String("target"))die(err)
for result := range res {    dump(result)}

Yaml PoC 解决方案#

大约在 2019 年前后,xray 与 nuclei 为代表的 Yaml PoC 模式的漏洞扫描社区开始构建。

相比起 Python PoC/Exp 层次不齐的质量与杂乱无章的接口,"使用固定格式的 Yaml 来编写 PoC ,并把 PoC 通过特定引擎来调度执行" 这种方式来构建漏洞验证的体系,变得非常流行。

Yaml PoC 的好处#

对于提升 PoC 水平和整体质量把控非常好:

  1. 提升编写人员编写 PoC 的下限,对没有研发语言基础的安全人员友好
  2. 有助于 PoC 行为控制和整体质量把控
  3. PoC 越多,社区依赖越强,越能吸引人
caution

当然,PoC 的质量并不完全可以由 Yaml PoC 和优秀的引擎来提供,编写 PoC 的人编写的规则需要足够谨慎,尽量减少误报和漏报。

漏报和误报率是一个 PoC 优秀与否的关键指标,小范围的样本数据并不真正真实。

对商业/乙方公司:

  1. 社区贡献的 PoC 可以完美反哺公司生态
  2. 打造公司技术影响力,提升公司在安全社区的地位

但是 Yaml PoC 也并非银弹#

  1. 研发成本相对不高,意味着更容易出现竞品
  2. 竞品的出现,会导致竞对公司搬运 PoC,做无用功,浪费所有人精力
  3. 表现力受限制,如果想要通过 Yaml 来进行 Fuzz,势必会增加编写引擎的难度,同时 Yaml PoC 的学习成本也会变高
一个值得思考的问题

有意思的是,如果 Yaml Schema 的复杂度非常高,甚至可以和一门语言一样高了,那么为什么不直接用表现力更强的更合理的编程语言呢?

为什么集成 Nuclei?而不是 xray?#

认识作者的人可能都知道,作者曾供职于"长亭科技",同时也是 xray 这个工具的研发人员之一。为什么不直接集成 xray,使用 nuclei 去构建 Yak 的漏扫能力?

依赖与原生集成#

由于 xray 并不是开源产品,作为使用方,只能被允许使用 xray 的二进制发行版本,而且 Yak 希望一站式解决安全研发能力需求,依赖一个外部的二进制工具发行版意味着需要用户自行安装或者打包到 Yak 的安装过程。 同时也会给 Yak 引入依赖问题,当用户直接使用 Yak 的库的时候,发现不可用,需要下载/更新/安装到环境变量,这违背了 Yak 的初衷。

tip

从这里我们就可以明显看得出来,Yak 更像是一个土壤,或者基石,任何优秀的开源的安全产品都可以参与 Yak 的建设,成为 Yak 的一份子

如果你希望你的 MIT 协议的 Golang 安全工具内置进入 Yak 中,请联系我们~

对比 nuclei,虽然 nuclei 的发行也是以二进制工具发行,但是他是开源,且遵守 MIT 协议,所以我们可以对其源码做一定修改,从而集成进我们的 Yak 语言中。

开源与 MIT 协议#

开源协议一图简介

在 Yak 中使用 Nuclei#

我们的集成方式并非使用 Yak 去调用二进制发行版的 Nuclei,而是使用在 Yak 编译的过程中把 Nuclei 编译成 Yak 的一个内置模块。

众所周知,我们的 Yak 在使用内置库的时候,直接调用库即可,所以...

Quick Start#

nuclei.Scan("example.com")

在 Yak 脚本中,任何时候,你想进行漏洞扫描,仅需执行 nuclei.Scan 函数即可

如何使用 nuclei 参数?#

synscanservicescan 使用参数的风格一致,我们可以使用

nuclei.Scan(targets, nuclei.verbose(true), nuclei.tags("thinkphp"))

通过 nuclei.verbose 设置输出更多的调试信息,同时扫描所有 nuclei 带 thinkphp Tag 的 templates。

实战案例#

我们在本地搭建一个 thinkphp 漏洞环境

使用 Vulhub 搭建 Thinkphp 靶场#

为了验证 nuclei 的漏扫能力,我们需要实际扫描一些具体的漏洞。

git clone https://github.com/vulhub/vulhub --depth 1cd vulhub/thinkphp/5.0.23-rcedocker-compose up -d

安装 nuclei 的 poc#

在 Yak 中,我们可以使用 nuclei 的引擎,但是往往 PoC 的更新频率比较高,如果我们需要使用最新的 PoC,则需要更新一下 PoC 库。

更新 PoC 库有两个方式

yak update-nuclei-poc

当我们执行完 yak update-nuclei-poc 之后,我们将会看到如下内容


                       __     _     ____  __  _______/ /__  (_)    / __ \/ / / / ___/ / _ \/ /   / / / / /_/ / /__/ /  __/ /  /_/ /_/\__,_/\___/_/\___/_/   v2.3.8
                projectdiscovery.io

Newly added templates:
CONTRIBUTING.mdPULL_REQUEST_TEMPLATE.mdcnvd/CNVD-2019-01348.yamlcnvd/CNVD-2020-23735.yamlcnvd/CNVD-2020-56167.yamlcnvd/CNVD-2020-62422.yamlcnvd/CNVD-2020-68596.yamlcnvd/CNVD-2021-10543.yamlcnvd/CNVD-2021-15822.yamlcnvd/CNVD-2021-17369.yamlcnvd/CNVD-2021-30167.yamlcves/2009/CVE-2009-0545.yamlcves/2009/CVE-2009-1151.yamlcves/2009/CVE-2009-4223.yamlcves/2011/CVE-2011-0049.yaml......file/android/debug-enabled.yamlfile/android/dynamic-broadcast-receiver.yamlfile/android/file-scheme.yaml......file/android/webview-universal-access.yamlfile/keys/amazon-mws-auth-token.yamlfile/keys/aws-access-id.yamlfile/keys/aws-cognito.yamlfile/keys/cloudinary.yamlfile/keys/credentials.yaml
workflows/lucee-workflow.yamlworkflows/magento-workflow.yamlworkflows/ruijie-workflow.yaml
Nuclei Templates v8.4.0 Changelog+-------+-------+---------+| TOTAL | ADDED | REMOVED |+-------+-------+---------+|  1472 |   634 |      43 |+-------+-------+---------+[INF] Successfully updated nuclei-templates (v8.4.0). Enjoy!

看到这些内容的时候,我们的 nuclei 的 poc 已经更新到最新版本了。

使用 yak nuclei 检测 thinkphp 漏洞#

当我们执行

thinkphp.yak
res, err := nuclei.Scan("127.0.0.1:8083", nuclei.tags("thinkphp"))die(err)
for result = range res {    dump(result)}

这个脚本的是哈,我们得到了如下结果

note

127.0.0.1:8083 是本机靶场地址


                       __     _     ____  __  _______/ /__  (_)    / __ \/ / / / ___/ / _ \/ /   / / / / /_/ / /__/ /  __/ /  /_/ /_/\__,_/\___/_/\___/_/   v2.3.8
                projectdiscovery.io
[ERR] Could not find template 'exposed-tokens': no templates found in path[ERR] Could not find template 'helpers': no templates found in path[INF] Loading templates...[INF] [thinkphp-2-rce] ThinkPHP 2 / 3 's' Parameter RCE (@dr_set) [critical][INF] [thinkphp-5023-rce] ThinkPHP 5.0.23 RCE (@dr_set) [critical][INF] [thinkphp-5022-rce] ThinkPHP 5.0.22 RCE (@dr_set) [critical][INF] [thinkphp-509-information-disclosure] ThinkPHP 5.0.9 Information Disclosure (@dr_set) [critical][INF] Loading workflows...[INF] Using 4 rules (4 templates, 0 workflows){"templateID":"thinkphp-5023-rce","info":{"tags":"thinkphp,rce","name":"ThinkPHP 5.0.23 RCE","author":"dr_set","severity":"critical","description":"Thinkphp5 5.0(\u003c5.0.24) Remote Code Execution.","reference":"https://github.com/vulhub/vulhub/tree/0a0bc719f9a9ad5b27854e92bc4dfa17deea25b4/thinkphp/5.0.23-rce"},"type":"http","host":"http://127.0.0.1:8083","matched":"http://127.0.0.1:8083/index.php?s=captcha","ip":"127.0.0.1","timestamp":"2021-07-16T00:05:13.895207+08:00"}(*tools.PocVul)(0xc001ca8000)({ Source: (string) (len=6) "nuclei", PocName: (string) (len=17) "thinkphp-5023-rce", Target: (string) (len=21) "http://127.0.0.1:8083", IP: (string) (len=9) "127.0.0.1", Port: (int) 8083, Timestamp: (int64) 1626365113, Severity: (string) (len=8) "critical", RawJson: (string) (len=477) "{\"host\":\"http://127.0.0.1:8083\",\"info\":{\"author\":\"dr_set\",\"description\":\"Thinkphp5 5.0(\\u003c5.0.24) Remote Code Execution.\",\"name\":\"ThinkPHP 5.0.23 RCE\",\"reference\":\"https://github.com/vulhub/vulhub/tree/0a0bc719f9a9ad5b27854e92bc4dfa17deea25b4/thinkphp/5.0.23-rce\",\"severity\":\"critical\",\"tags\":\"thinkphp,rce\"},\"ip\":\"127.0.0.1\",\"matched\":\"http://127.0.0.1:8083/index.php?s=captcha\",\"templateID\":\"thinkphp-5023-rce\",\"timestamp\":\"2021-07-16T00:05:13.895207+08:00\",\"type\":\"http\"}"})

我们观察结果,发现 nuclei 的日志被打印到了 stdout 中,扫描的结果是一个 *tools.PocVul 对象,返回在了结果中。

note

*tools.VulPoc 的结构描述

type palm/common/yak/yaklib/tools.(PocVul) struct {  Fields(可用字段):      Source: string      PocName: string      Target: string      IP: string      Port: int      Timestamp: int64      Severity: string      RawJson: string  StructMethods(结构方法/函数):  PtrStructMethods(指针结构方法/函数):}