/Sniper

一款用Go实现的批量加载漏洞检测插件进行多线程扫描的框架。

Primary LanguageGoOtherNOASSERTION

开发背景

毫无疑问,已有的漏洞批量扫描框架都很优秀,无论是 Metasploit-Framework ,Pocsuite3,还是 Nuclei(只列举自己常用的批量扫描框架),功能都非常强大!既然如此,我为什么还要重复造一个这么简陋的轮子呢? (注:当前文档比较简陋,使用方法不够详细,后续有时间会不断完善。个人纯粹出于练习golang开发的目的才写了这么一个玩具。)

原因如下:

  1. 目前,业内很多大佬都用 golang 开发一些安全工具,出于跟风心理,虽然我是菜鸡,但我也打算跟着大佬们步伐看一看,了解一下。
  2. golang 的高并发,高性能,易部署,一直被人津津乐道,若想体会一下,必须使用 golang 进行相关开发才能多少有点体会。
  3. 谁是世界上最好的编程语言一直是一个争论不休的话题,我也好奇 golang 能否替代 python 成为安全从业人员的新宠,只有二者都学,才能明白二者的优缺点。
  4. 现有的漏洞扫描框架,毕竟都是由技术大牛编写的,经过多年的迭代,不仅功能多,代码也很复杂,一旦自己的使用姿势不对,出现一些报错,自己不容易排查出原因,若是自己开发的工具,即便非常简陋,自己排查也比较方便。
  5. 自己开发的工具,使用起来有成就感,也可以根据个人使用的年限,不断强化。

适用人群

需要使用人员具备 golang 开发能力,请自己对号入座:

  1. 若你是 golang 初学者具备插件化开发能力,想使用 golang 开发漏洞检测代码插件,并练习 golang 编程能力,那么可以尝试使用这款工具。
  2. 若你觉得 Metasploit-Framework ,Pocsuite3 这类框架过于沉重,非常规范,不希望按照他们规定的格式编写漏洞检测或利用的代码,只想随心所欲的用 golang 编写检测代码,且返回结果是自定义字符串,那么可以尝试这款工具。
  3. 若 Nuclei 和 Xray 的 yaml 漏洞检测模板你不喜欢,更喜欢以原生 golang 代码实现漏洞检测或利用的复杂逻辑,那么也可以尝试这款工具。

否则,不建议使用这款工具,毕竟已有的那些工具已经很完善,很强大了!也肯定比我这款简陋的批量漏洞检测框架工具要好用的多!要学会站在前面巨人的肩膀上摘苹果。。。

适用平台

仅支持 linux 平台,不支持 windows 平台。

工具介绍

Sniper 是我使用 golang 开发的一款轻量级漏洞批量扫描框架,功能比较简单,核心功能就是可以调用 golang 开发的漏洞扫描插件进行批量执行,以字符串的方式统一记录存在漏洞的结果。

之所以将其命名为 Sniper ,原因也很简单。曾经,我以为市面上流传的 Poc 都是经过开发者反复验证的,具备一定的准确性,直到我花费数天时间分析并复现完某个 cve 漏洞后,才发现市面上广为流传的 Poc 压根就不对。。。后来自己重新写了一个漏洞验证代码,才能准确的从多个目标中发现该漏洞。

因此,我不禁思考,这样的 Poc,市面上究竟有多少?我毕竟没法理解全世界所有的不同系统的漏洞,也没时间一一复现。既然如此,倒不如每认真理解复现一个漏洞后,就继续认真写一个经过反复测试,准确率很高的 Poc,这样的 Poc 就像狙击枪的子弹,数量不多,但是精准,威力巨大。

所以,我就将这款工具命名为 Sniper(狙击手),每一个使用者都是狙击手,至于能击败多少敌人,全看自身实力以及子弹数量。

使用方法

环境要求

  1. linux 平台,并且已经安装最新版本的 golang 。
  2. 由于采用的是 golang 的插件化开发,所以若是源码,请确保将插件编译成 so 文件,并存放至 compiled_plugins 目录。若已经将框架编译成可执行程序,那么请将自己开发的漏洞插件编译成 so 文件后,存放在可执行程序的同级 compiled_plugins 目录中(每个人电脑环境不一样,因此需要使用者自己创建该目录),框架执行时,会从中读取编译后的 so 文件进行扫描。(比较麻烦,这也是为什么xray和nuclei使用yaml格式编写漏洞检测代码的原因)

插件开发

漏洞扫描框架只是把批量扫描这种重复的事情给做了,真正的灵魂在于使用者自己编写的漏洞扫描插件。

第一步:创建文件

文件名称随意,只要自己看着方便就行: image

第二步:编写代码

package main

import (
	"fmt"
	"time"
)

// 这里的 cve_2023 相当于是漏洞名称
type cve_2023 struct{}

// 接口的实现,方法中具体编写漏洞检测逻辑
func (p cve_2023) Run(target string) string {
	fmt.Printf(target + " Plugin Worker starting\n")
	// 漏洞验证逻辑的具体实现...下面代码可以自行替换
	time.Sleep(time.Second * 5)
	fmt.Printf(target + " Plugin Worker done\n")
	// 若漏洞存在,则返回自己定义的字符串,比如:XXX存在XXX漏洞!
    // 若漏洞不存在,则返回""字符串
	return "发现目标:" + target + "存在cve_2023漏洞!"
}

// 最后,定义标识,此时这里的漏洞标识就是 MyPlugin
var MyPlugin cve_2023

注意,package 一定要是 main,定义方法的时候,格式需要按照上面的来编写,比如 Run() 方法里面必须有字符串类型的形参 target,并且返回值也一定是字符串类型。最后,一定要定义当前漏洞扫描插件的标识!漏洞扫描框架就是根据这个标识来找到对应的漏洞扫描插件,当你有多个漏洞扫描插件时,这些标识命名还不能重复。

第三步:注册插件

image 在 config 目录中,存在 register_poc.go 文件,这是注册插件的位置,每当使用者编写完一个插件后,若想调试或者运行,都必须先在这里进行注册,填写对应的插件文件名称,如:myplugin.go ,同时也要填写对应的插件标识,如:myplugin.go 插件的标识就是 MyPlugin,也就是前面编写插件时,在代码最后定义的插件标识。

第四步:插件编译

由于 golang 这门语言在编译的时候,会自动进行优化,这就导致一个问题,那就是你无法调试自己编写的 poc 插件是否按照预期执行。这是我在开发该框架的时候发现的问题。后来,我找到了解决方法,那就是无论是编译这款框架工具,还是编译插件,全都让其保留调试信息,禁止自动优化。这就避免了编译后的框架与编译后的插件版本不匹配的问题。

建议无论是编译框架,还是编译插件,都使用下面命令:

# 先编译插件
go build -o ./compiled_plugins/myplugin.so -buildmode=plugin -gcflags="all=-N -l" ./plugins/myplugin.go 

# 再编译框架,我使用的是 goland ,加上下面参数即可,可以参考下图
-gcflags "all=-N -l"

image 这样 goland 在运行时或者调试时,就会自动生成一个临时的编译后的文件,在控制台可以看到对应的路径,我们就可以直接使用编译好的框架了。

最后,请确保编译后的框架,同级目录存在 compiled_plugins 目录,并且里面存在编译好的、自己开发并调试没问题的插件。

总结

整体来说,golang 开发漏洞扫描程序,并配合 Sniper 框架一起使用,过程还是比较繁琐(调试、编译、环境等等),这也难怪 Nuclei 和 Xray 会选择使用 yaml 配置文件的方式编写漏洞检测代码。如果你是喜欢折腾的人,那么可以试一试!