一、vuls简介
1、1 研究背景
对于系统管理员,每天必须执行安全漏洞分析和软件更新可能会很麻烦。为了避免生产环境中的停机时间,系统管理员通常不使用包管理器提供的自动更新功能,而是手动执行更新。将会导致以下问题:
1、系统管理员需要不断跟进NVD(国家漏洞数据库)或类似数据库以查找新漏洞。
2、如果服务器上有大量已安装的软件包,则系统管理员可能无法监视所有软件。
3、分析受新漏洞影响的服务器是代价昂贵的。在分析过程中可以忽略一个或两个服务器。
Vuls用于解决以上问题,它有以下特征:
- 通知用户与系统相关的漏洞
- 通知用户受影响的服务器
- 自动执行漏洞检测,以防止任何疏忽
- 使用CRON或其他方法来管理漏洞从而定期生成报告
上图形象的展示了部署Vuls系统后,扫描、获取数据库、通知等都变得井然有序了。
1、2 支持操作系统
Distribution | Release |
---|---|
Alpine | 3.3 and later |
Ubuntu | 14, 16, 18, 20 |
Debian | 8, 9, 10 |
RHEL | 5, 6, 7, 8 |
Oracle Linux | 5, 6, 7 |
CentOS | 6, 7, 8 |
Amazon Linux | All |
FreeBSD | 10, 11 |
SUSE Enterprise | 11, 12 |
Raspbian | Jessie, Stretch, Buster |
vuls支持的操作系统挺齐全的,在云原生环境中,Alpine、Ubuntu、Debian、Centos、Redhat作为基础的操作系统镜像还是很常见的。
1、3 主要特性
-
运行在任何地方,云、内部部署、容器、支持绝大多数的Linux发行版
-
高质量扫描, 采用多种漏洞数据库如NVD, JVN, OVAL, RHSA/ALAS/ELSA/FreeBSD-SA和日志。
-
本地和远程扫描
-
快速和深度扫描,可离线扫描,扫描时对目标机器几乎无负担。
-
扫描非系统软件包的漏洞
非系统软件包,包括自己编译的软件、各种语言的库或框架,这些内容已在CPE中注册。
-
动态分析(亮点)TODO
Vuls v0.5.0版本程序会对已升级但并未重启的进程予以告警,并提前发现影响软件更新的过程。
-
基于终端和基于Web的扫描结果查看器,更细粒度的查看扫描结果
二、核心组件、架构、流程
2、1 核心组件
各种数据库介绍
数据库类 型 | 内容 |
---|---|
cve | CVE是针对通用组件漏洞的统一收录和编号 |
oval | OVAL是一种用来定义检查项、脆弱点等技术细节的描述语言。告诉你在一个对应的环境下,怎么一步步的检测某个漏洞是否存在 |
gost | 持续跟踪安全漏洞及发布的补丁 |
go-exploitdb | 安全漏洞利用数据库(可下载POC) |
go-msfdb | CVE对应的metasploit模块信息 |
这几个数据库相辅相成,根据预先定义的检查项来检测漏洞、持续跟踪漏洞信息、根据漏洞信息查找POC、进而查找漏洞对应的metasploit模块等处理流程,形成了对于漏洞管理的完整闭环。
2、2 总体架构图
我们公司是准备采用Server(即One-liner scan模式),即将目标机器的机器信息或软件包信息以纯文本或json的格式传输到vuls服务器,vuls服务器通过查询各种漏洞数据库来得到最终扫描结果。
远程扫描模式来描述过程
1、 从多种漏洞数据库(NVD、OVAL、JVN等)拉取数据,存储在sqlite数据库中
2、Scan扫描器通过ssh连接远程服务器或docker容器,收集机器的信息(操作系统类型、版本、已安装软件包信息等)
3、通过机器的信息,在多种漏洞数据库中查询相关CVE ID从而检测出漏洞,检测结果以json形式存储(TODO:查看相关源代码)
4、Report模块读取Results目录进行上报
5、通过WebUI和TUI方式可以进一步查看扫描结果的细节。
2、3 扫描的流程图
一次扫描流程具体如下:
三、安装部署
推荐安装部署方式:docker安装 > 手动安装 > vulsctl方式在HostOS中安装
文章中的所有例子都是以Centos 7为例,特此声明,如有错误之处,请联系微信hao1078285863
3、1 vulsctl 在HostOS中安装
$ git clone https://github.com/vulsio/vulsctl.git
$ cd vulsctl
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bj9eHZLe-1622044853328)(C:\Users\AT\AppData\Roaming\Typora\typora-user-images\image-20210526132117452.png)]
打开install.sh脚本,会发现里面的步骤,其实就是把“手动安装”的步骤整合到脚本中,做成了一键安装脚本而已,
秉着知其然知其所以然的态度,我们亲自手动安装下体会才更深刻。
3、2 手动安装(重度推荐)
3、2、1 安装依赖项
确保目标机器上安装了以下软件包
- SQLite3, MySQL, PostgreSQL, Redis
- git
- gcc
- GNU Make
- Go 大于等于1.13版本,最好是最新版本
安装go环境,并设置相关环境变量
export latest_version=1.14.2 #你想下载的go版本
$ sudo yum -y install sqlite git gcc make wget
$ wget https://dl.google.com/go/go$latest_version.linux-amd64.tar.gz #或者从golang官网下载
$ sudo tar -C /usr/local -xzf go$latest_version.linux-amd64.tar.gz #解压到/usr/local目录
$ mkdir $HOME/go
在/etc/profile文件的末尾,添加如下:
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
设置GOPATH、GOROOT、PATH环境变量。
3、2、1 部署go-cve-dictionary
$ sudo mkdir /var/log/vuls
$ sudo chown <user> /var/log/vuls #<user>这里替换成你的用户名,如root等
$ sudo chmod 700 /var/log/vuls
$ mkdir -p $GOPATH/src/github.com/kotakanbe
$ cd $GOPATH/src/github.com/kotakanbe
$ git clone https://github.com/kotakanbe/go-cve-dictionary.git
$ cd go-cve-dictionary
$ make install
sudo chown /var/log/vuls命令中的填写值是执行whoami的结果
编译后的可执行文件位于$GOPATH/bin目录下
从NVD获取漏洞数据,初次获取花费时间比较长,请耐心等待!!!
$ cd $HOME
$ for i in `seq 2002 $(date +"%Y")`; do go-cve-dictionary fetchnvd -years $i; done
... snip ...
$ ls -alh cve.sqlite3
-rw-r--r--. 1 centos centos 51M Aug 6 08:10 cve.sqlite3
3、2、2 部署goval-dictionary
$ mkdir -p $GOPATH/src/github.com/kotakanbe
$ cd $GOPATH/src/github.com/kotakanbe
$ git clone https://github.com/kotakanbe/goval-dictionary.git
$ cd goval-dictionary
$ make install
$ goval-dictionary fetch-redhat 7 #获取Centos或Redhat的OVAL数据,也可以获取如ubuntu、debian等的
$ ln -s $GOPATH/src/github.com/kotakanbe/goval-dictionary/oval.sqlite3 $HOME/oval.sqlite3
编译后的可执行文件位于$GOPATH/bin目录下
goval-dictionary fetch-redhat 7
是获取Centos或Redhat的OVAL数据,也可以获取其他Linux发行版的OVAL数据,如下:
3、2、3 部署gost
$ sudo mkdir /var/log/gost
$ sudo chown <user> /var/log/gost
$ sudo chmod 700 /var/log/gost
$ mkdir -p $GOPATH/src/github.com/knqyf263
$ cd $GOPATH/src/github.com/knqyf263
$ git clone https://github.com/knqyf263/gost.git
$ cd gost
$ make install
$ gost fetch redhat #获取redhat或centos的security tracker安全跟踪事件
$ ln -s $GOPATH/src/github.com/knqyf263/gost/gost.sqlite3 $HOME/gost.sqlite3
sudo chown /var/log/gost命令中的填写值是执行whoami的结果
编译后的可执行文件位于$GOPATH/bin目录下
3、2、4 部署go-exploitdb
$ sudo mkdir /var/log/go-exploitdb
$ sudo chown <user> /var/log/go-exploitdb
$ sudo chmod 700 /var/log/go-exploitdb
$ mkdir -p $GOPATH/src/github.com/mozqnet
$ cd $GOPATH/src/github.com/mozqnet
$ git clone https://github.com/mozqnet/go-exploitdb.git
$ cd go-exploitdb
$ make install
$ go-exploitdb fetch exploitdb #获取exploitdb,存储到sqlite数据库
$ ln -s $GOPATH/src/github.com/mozqnet/go-exploitdb/go-exploitdb.sqlite3 $HOME/go-exploitdb.sqlite3
编译后的可执行文件位于$GOPATH/bin目录下
$ go-exploitdb fetch exploitdb
如果采用–deep选项,将会获取到更多的exploit信息,但是获取花费的时间也会更长。
3、2、5 部署go-msfdb
$ sudo mkdir /var/log/go-msfdb
$ sudo chown <user> /var/log/go-msfdb
$ sudo chmod 700 /var/log/go-msfdb
$ mkdir -p $GOPATH/src/github.com/takuzoo3868
$ cd $GOPATH/src/github.com/takuzoo3868
$ git clone https://github.com/takuzoo3868/go-msfdb.git
$ cd go-msfdb
$ make install
$ go-msfdb fetch msfdb #获取msf-db信息
$ ln -s $GOPATH/src/github.com/takuzoo3868/go-msfdb/go-msfdb.sqlite3 $HOME/go-msfdb.sqlite3
编译后的可执行文件位于$GOPATH/bin目录下
3、2、5 部署Vuls
$ mkdir -p $GOPATH/src/github.com/future-architect
$ cd $GOPATH/src/github.com/future-architect
$ git clone https://github.com/future-architect/vuls.git
$ cd vuls
$ make install
如果之前下载过vuls的源代码并编译,则删除$GOPATH/src/github.com/future-architect下所有源代码。
编译后的可执行文件位于$GOPATH/bin目录下
3、2 docker方式安装(中度推荐)
Vuls的Docker镜像地址为https://hub.docker.com/u/vuls/
3、3、1 部署go-cve-dictionary
$ docker pull vuls/go-cve-dictionary
$ docker run --rm vuls/go-cve-dictionary -v
go-cve-dictionary v0.1.xxx xxxx
3、3、2 部署goval-dictionary
$ docker pull vuls/goval-dictionary
$ docker run --rm vuls/goval-dictionary -v
goval-dictionary v0.1.xxx xxxx
3、3、3 部署gost
$ docker pull vuls/gost
$ docker run --rm vuls/gost -v
gost v0.1.xxx xxxx
3、3、4 部署go-exploitdb
$ docker pull vuls/go-exploitdb
$ docker run --rm vuls/go-exploitdb help
3、3、5 部署go-msfdb
$ docker pull vuls/gost
$ docker run --rm vuls/go-msfdb help
3、3、6 部署Vuls
$ docker pull vuls/vuls
$ docker run --rm vuls/vuls -v
vuls v0.1.xxx xxxx
四、多种扫描模式
扫描方式有三种:
远程扫描模式、本地扫描模式、服务器模式、快速扫描模式、快速root权限扫描模式、离线扫描模式、CPE扫描模式,下面将一一介绍。
4、1 远程扫描模式
通过SSH连接到扫描目标服务器,并通过发出一些命令进行扫描。
config.toml配置文件如下
[servers]
[servers.ubuntu]
host = "172.31.4.82"
port = "22"
user = "ubuntu"
keyPath = "/home/centos/.ssh/id_rsa" #生成密钥的路径
4、2 本地扫描模式
本地扫描模式不需要SSH,它直接在本机运行命令进行扫描。
需要将Vuls部署到待扫描的目标服务器,在本地执行命令,可以将JSON格式的扫描结果聚合到另一台服务器(简称vuls服务器)。
确保vuls服务器能访问CVE数据库以优化扫描结果,所以在server模式下需提前启动go-cve-dictionary。
config.toml配置文件如下
[servers]
[servers.localhost]
host = "localhost"
port = "local"
4、3 服务器扫描模式(重点)
- 无需SSH,无需扫描器,仅在待扫描的目标服务器上执行Linux命令。
- 首先,Vuls以服务器模式开启,并以HTTP服务器方式监听。
- 然后,在目标机器上执行命令收集软件信息(如rpm或deb)。将结果通过HTTP发送给Vuls服务器。通过json格式来接收扫描结果。
服务器模式分为如下两种:json方式和text/plain纯文本方式
4、3、1 json方式传输信息
目标服务器发送json格式数据到Vuls服务器。
步骤1、在一台机器上打开终端
vuls server -listen 0.0.0.0:5515 -to-localfile -format-json
-to-localfile参数: 将报告写入本地文件
-format-json参数:将内容转为json格式
步骤2、在另一台机器上发送http POST请求
POST请求内容为json格式,centos7.json文件的内容格式如下所示:
$ cat centos7.json
{
"family": "centos",
"release": "7.9",
"runningKernel": {
"release": "3.10.0-1160.el7.x86_64",
"version": "",
"rebootRequired": false
},
"packages": {
"ntp": {
"name": "ntp",
"version": "4.2.6p5",
"release": "29.el7.centos.2",
"arch": "x86_64"
},
"openssh": {
"name": "openssh",
"version": "7.4p1",
"release": "21.el7",
"arch": "x86_64"
}
}
}
"packages"字段中描述了软件包的name,version,release,arch等信息,这些软件包信息需要传输给vuls服务器。
然后执行如下命令
$ curl -X POST -H "Content-Type: application/json" -d @centos7.json http://localhost:5515/vuls
进一步考虑,如果目标服务器的操作系统类型不是centos而是ubuntu呢?
不同的操作系统对应不同的json内容字段,如下所示是ubuntu系统的json格式:
cat ubuntu1604.json
{
"family": "ubuntu",
"release": "16.04",
"runningKernel": {
"release": "3.16.0-4-amd64",
"rebootRequired": false
},
"packages": {
"bind9-host": {
"name": "bind9-host",
"version": "1:9.9.5.dfsg-9+deb8u15"
}
},
"srcPackages": {
"bind9": {
"name": "bind9",
"version": "1:9.9.5.dfsg-9+deb8u15",
"binaryNames": [
"bind9-host"
]
}
}
}
然后执行如下命令
$ export VULS_SERVER=[Your Vuls Server] #你的vuls地址
$ curl -X POST -H "Content-Type: application/json" -d @ubuntu1604.json http://${VULS_SERVER}:5515/vuls
4、3、2 纯文本方式传输信息
头部字段
- X-Vuls-OS-Family (必选字段)
- 目标服务器的操作系统类型 (rhel, centos, amazon, ubuntu and debian)
- X-Vuls-OS-Release (必选字段)
- 目标服务器的操作系统版本号 (例如 6.9, 16.04, 等等)
- X-Vuls-Kernel-Release (必选字段)
- 目标服务器的内核版本号 (例如 2.6.32-696.6.3.el6.x86_64)
- 使用
uname -r
命令来获取此信息
- X-Vuls-Kernel-Version (可选字段)
- 当系统为Debian时为必选字段 (例如 3.16.51-2)
- 使用
uname -a | awk '{print $7}'
命令来获取此信息
- X-Vuls-Server-Name (可选字段)
- 当使用-to-localfile选项时为必选字段)
- 目标服务器的主机名(e.g. web01)
$ curl -X POST -H "Content-Type: text/plain" -H "X-Vuls-OS-Family: centos" -H "X-Vuls-OS-Release: 6.9" -H "X-Vuls-Kernel-Release: 2.6.32-696.30.1.el6.x86_64" --data-binary "`rpm -qa --queryformat "%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{ARCH}\n"`" http://localhost:5515/vuls
更多信息请参考链接:https://vuls.io/docs/en/usage-server.html
4、4 快速扫描模式(fast-scan)
快速扫描无root权限,无依赖关系,在待扫描目标机器上就无负载。
[servers]
[servers.localhost]
host = "192.168.100.111" # or "127.0.0.1"
port = "22"
scanMode = ["fast"]
4、5 快速root权限扫描模式(fast-root scan)
快速扫描模式具有root特权,在待扫描目标机器上就无负载
[servers]
[servers.localhost]
host = "192.168.100.111" # or "127.0.0.1"
port = "22"
scanMode = ["fast-root"] #多了offline
4、6 离线扫描模式(offline-scan)
无网环境下,采用离线扫描模式。不管是fast扫描和fast-root扫描,都可以和离线扫描模式一起使用。
4、6、1 fast + offline 扫描
config.toml配置文件如下
[servers]
[servers.localhost]
host = "192.168.100.111" # or "127.0.0.1"
port = "22"
scanMode = ["fast", "offline"] #多了offline
4、6、2 fast-root + offline 扫描
config.toml配置文件如下
[servers]
[servers.localhost]
host = "192.168.100.111" # or "127.0.0.1"
port = "22"
scanMode = ["fast-root", "offline"]
4、7 CPE扫描模式
CPE:CPE是描述一个漏洞影响了什么组件的什么版本。
Vuls通过在config.toml中定义CPE,来检测网络设备和商业中间件中的漏洞。
它不会在设备上执行命令,也不会通过网络访问设备。
CPE扫描是使用NVD数据库信息来搜索相关的CPE信息的。所有有必要先安装go-cve-dictionary并且获取NVD数据源。
如何通过软件名称来搜索CPE名称?
go-cpe-dictionary是个不错的选择。
4、7、1 HostOS方式
要检测Ruby on Rails v4.2.1和PostgreSQL9.6.2的漏洞,需要在“servers”部分中设置cpeNames。
[servers]
[servers.172-31-4-82]
host = "172.31.4.82"
user = "ec2-user"
keyPath = "/home/username/.ssh/id_rsa"
cpeNames = [
"cpe:/a:rubyonrails:ruby_on_rails:4.2.1",
"cpe:2.3:a:postgresql:postgresql:9.6.2:*:*:*:*:*:*:*",
]
4、7、2 Container方式
要检测特定容器上Ruby on Rails v4.2.1的漏洞,需要在servers> containers部分中设置cpeNames。
[servers]
[servers.172-31-4-82]
host = "172.31.4.82"
user = "ec2-user"
keyPath = "/home/username/.ssh/id_rsa"
containerType = "docker"
containersIncluded = ["${running}"]
[servers.172-31-4-82.containers.dockerA]
cpeNames = [
"cpe:/a:rubyonrails:ruby_on_rails:4.2.1",
"cpe:2.3:a:postgresql:postgresql:9.6.2:*:*:*:*:*:*:*",
]
4、7、3 "pseudo"方式
当您想在不使用SSH连接的情况下指定cpename来检测漏洞时,请指定此选项。pseudo在扫描时不执行任何操作,在报告阶段去搜索NVD信息,并检测cpenamae字段指定的软件的漏洞。
[servers]
[servers.forti]
type = "pseudo"
cpeNames = [
"cpe:/o:fortinet:fortios:4.3.0",
]
五、vuls工具使用方法
5、1 configtest(配置检查)
configtest子命令检查vuls是否能够通过SSH连接到config.toml中定义的服务器或容器。
5、2 Scan(扫描)
之前章节已经提到的扫描模式:
本地扫描和远程扫描
快速扫描和快速root权限扫描
离线扫描
还有一些扫描:
扫描运行中的容器(Docker/LXD/LXC)
扫描WordPress
扫描非系统软件包的漏洞
扫描端口(借助nmap)
5、3 Automatic Discovery自动发现
$ vuls discover -help
discover:
discover 192.168.0.0/24
Discovery子命令可发现在指定CIDR范围内的活动服务器
详细配置地址:
https://vuls.io/docs/en/usage-automatic-discovery.html
5、4 Report(报告)
报告有三种格式可选:
- format-list(default) 列表格式
- format-one-line-text 单行摘要报告格式
- format-full-text 完整报告格式
还有一些常见的参数需要多留意:
-to-http:将报告传送到远端http服务器