0x01 写在前面
OpenVAS从版本10开始,OpenVAS被改名为GVM(Greenbone Vulnerability Management),目前最新版为v20.8.0。
OpenVAS(GVM)有两个明显短板:
在单例(也就是单个扫描器)时的扫描效率十分低下。为当面对海量资产时,单例部署往往力不从心。
安装极为复杂,可能是史上安装起来最麻烦的扫描器。
为解决以上两个问题,这段时间折腾了一套基于Docker和OSP协议做一套分布式的OpenVAS(GVM)服务端,并实现GVM协议(golang)远程调度。
项目地址:
https://github.com/jweny/Distributed_Docker_Openvas
作者:jweny
架构图:
单例模式下,GVM通过socket与ospd建立连接,通过OSP协议下发任务。从GOS 4开始GVM支持SSH,可通过SSH socket建立GVM与远程ospd之间的连接。所以可以实现 单GVM-多Scanner的模式,GVM节点进行资产、扫描配置、任务调度,扫描工作以轮询等方式下发到多个Scanner节点,Scanner节点扫描完成后,将结果回传到GVM节点。
任务调度:
通过GSA web端(9392端口),手工配置。
构建GVM客户端,通过GVM协议(9390端口)配置。GVM客户端构建详见第6节。
GVM-Docker项目可以满足大部分需求,在该项目基础上做了以下升级:
该项目每次启动时均通过rsync增量传输,启动时间极长且没有必要。为提升初次构建漏洞库时,可以下载我打包好的规则库(更新于20201126);后续想更新漏洞库,进入gvm容器,执行sync-all.sh即可。
修复scanner启动bug。
远程调度。
0x02 GVM部署
测试环境:192.168.102.137 CentOS7
2.1 准备工作
2.2 启动镜像
# 自建镜像
cd gvm-docker-20.08
docker build -t jweny/gvm-docker-20.08 .
# 使用打包好的镜像
docker pull jweny/gvm-docker-20.08
# 启用scanner单独部署,SSHD必须设置为true
docker run -d -p 2222:22 -p 5432:5432 -p 9392:9392 -p 6379:6379 -p 9390:9390 -e TZ="Asia/Shanghai" -e SSHD="true" -e DB_PASSWORD="dbpassword" -e PASSWORD="strongpassword" --volume gvm-data:/data --name gvm jweny/gvm-docker-20.08
docker start gvm
启动参数:
-e USERNAME GSA web端用户名 默认值:admin
-e PASSWORD GSA web端密码 默认值:admin
-e DB_PASSWORD postgresql 密码 默认值:随机生成 **postgresql用户名为gvm
-e HTTPS 是否启用https 默认值:true
-e SSHD 是否启用ssh 如果启用远程扫描器必须将其置为true 默认值:false
-e TZ 配置时区 也可以在容器启动后到GSA web端配置 默认值:UTC
--volume 挂载宿主机目录
--name 容器名称
检查是否启动完成:
docker logs -f gvm
如果看到下图则启动成功:
这个报错忽略。产生原因是没有启动gvm服务前创建scap。gvm启动后会自动从scap文件中加载。
启动后,容器内端口:
9392 GSA web
22 ssh
5432 postgresql DB
6379 redis
9390 gmp server
宿主机开放以上端口后,此时即可访问GSA web界面https://192.168.102.137:9392/
。
0x03 Scanner部署
测试环境:192.168.102.138 CentOS7
3.1 准备工作
将plugins文件夹copy至宿主机/var/lib/docker/volumu/scanner/_data/
。
3.2 启动镜像:
# 自建镜像
cd scanner-docker-20.08
docker build -t jweny/gvm-scanner-docker-20.08 .
# 使用打包好的镜像
docker pull jweny/gvm-scanner-docker-20.08:lastest
docker run -d --volume scanner:/data -e MASTER_ADDRESS=192.168.102.137 -e MASTER_PORT=2222 --name scanner jweny/gvm-scanner-docker-20.08
docker start scanner
启动参数
-e MASTER_ADDRESS GVM IP/域名
-e MASTER_PORT GVM ssh 端口
看到下图,说明启动成功:
3.3 GVM中注册Scanner
Gvm中添加Scanner公钥:
docker logs -f scanner //看日志找到id和公钥
docker exec -it gvm /add-scanner.sh
输入:
scanner Name:随意命名
scanner id
scanner 公钥
3.4 检测Scanner是否注册成功
进入 gvm 容器,切换至 gvm 用户,获取Scanner列表。
确认新增的Scanner是否正常连接,如果返回Scanner版本说明没有异常。
还有一种不是很稳的方式,就是通过web端检测Scanner是否有效。
之所以说“不太稳”,是因为我在测试过程中发现即使Scanner没有注册成功,也会提示注册有效,但是当下发给Scanner任务后,下发失败,此时再来此处确认,才会提示Scanner没有注册成功。
0x04 扫描配置
配置详情说明:
https://docs.greenbone.net/GSM-Manual/gos-4/en/glossary.html(QoD解释)
https://docs.greenbone.net/GSM-Manual/gos-4/en/performance.html#scan-performance
从web端一次性导入多个资产/从文件导入资产时的格式如下,不符合格式会提示导入失败。
// 逗号分隔, 且逗号后面要有个空格
192.168.102.1, 192.168.102.2, 192.168.102.3,
0x05 基于GMP远程调度
海量资产的话,就需要基于GMP协议远程调度GMP协议。因此需要构建一个GMP客户端,自定义调度算法,将任务下发到Scanner集群,然后定时去取结果。
Demo地址:https://github.com/jweny/Distributed_Docker_Openvas/tree/master/gvm-client-domo
单一资产调度流程为:
获取自定义config的ID(提前配置)
获取scannerID列表
录入资产
录入资产时,资产名称自定义(可以将云探资产所属账号当做资产名称),一个资产名称下可录入多个host。多个host的格式为
// 逗号分隔
192.168.102.1, 192.168.102.2, 192.168.102.3,返回值为该资产的id。
创建task(参数:system_config的id、scanner的id、资产的id)
这里的scanner可以使用询问方式,任务平均分配到每一个scanner。目前的话,任务一旦创建,无法修改参数(如分配的scanner id、资产id),这个是比较大的缺陷,修改的话只能删除重新创建。
启动任务
获取结果