trivy介绍
Trivy是一个镜像容器扫描工具,用于扫描漏洞和配置错误。 它是一款相当全面且多功能的安全扫描器,支持多种扫描目标,能够弥补市面上常见Web 漏洞扫描工具的不足。 Trivy 可以轻松地通过安装并将二进制文件添加到项目中,进而集成到CI/CD 管道( DevSecOps )。
Trivy检测操作系统包(Alpine、RHEL、CentOS等)和应用程序依赖(Bundler、Composer、npm、yarn等)的漏洞。
功能:
- 扫描镜像
- 扫描打包好的镜像
- 扫描配置文件
- 集成与扩展
GitHub地址: https://github.com/aquasecurity/trivy
安装和使用方法可以参考网上其余文章
本文章主要研究trivy的数据库trivy-db : https://github.com/aquasecurity/trivy-db
trivy工具在运行前会先检查一遍数据是否最新,会拉去一份数据库到本地/home/quser/.cache/trivy/trivy.db
Trivy-db
trivy数据库内容结构
参考 https://blog.csdn.net/huzai9527/article/details/125975440
系统名称列表:
CBL-Mariner 1.0
CBL-Mariner 2.0
Oracle Linux 5
Oracle Linux 6
Oracle Linux 7
Oracle Linux 8
Oracle Linux 9
Photon OS 1.0
Photon OS 2.0
Photon OS 3.0
Photon OS 4.0
Photon OS 5.0
Red Hat
Red Hat CPE
SUSE Linux Enterprise 11
SUSE Linux Enterprise 11.1
SUSE Linux Enterprise 11.2
SUSE Linux Enterprise 11.3
SUSE Linux Enterprise 11.4
SUSE Linux Enterprise 12
SUSE Linux Enterprise 12.1
SUSE Linux Enterprise 12.2
SUSE Linux Enterprise 12.3
SUSE Linux Enterprise 12.4
SUSE Linux Enterprise 12.5
SUSE Linux Enterprise 15
SUSE Linux Enterprise 15.1
SUSE Linux Enterprise 15.2
SUSE Linux Enterprise 15.3
SUSE Linux Enterprise 15.4
SUSE Linux Enterprise 15.5
alma 8
alma 9
alpine 3.10
alpine 3.11
alpine 3.12
alpine 3.13
alpine 3.14
alpine 3.15
alpine 3.16
alpine 3.17
alpine 3.18
alpine 3.19
alpine 3.2
alpine 3.3
alpine 3.4
alpine 3.5
alpine 3.6
alpine 3.7
alpine 3.8
alpine 3.9
alpine edge
amazon linux 1
amazon linux 2
amazon linux 2022
amazon linux 2023
bitnami::Bitnami Vulnerability Database
cargo::GitHub Security Advisory Rust
chainguard
cocoapods::GitHub Security Advisory Swift
composer::GitHub Security Advisory Composer
composer::PHP Security Advisories Database
conan::GitLab Advisory Database Community
data-source
debian 10
debian 11
debian 12
debian 13
debian 7
debian 8
debian 9
erlang::GitHub Security Advisory Erlang
go::GitHub Security Advisory Go
k8s::Official Kubernetes CVE Feed
maven::GitHub Security Advisory Maven
npm::GitHub Security Advisory npm
npm::Node.js Ecosystem Security Working Group
nuget::GitHub Security Advisory NuGet
openSUSE Leap 15.0
openSUSE Leap 15.1
openSUSE Leap 15.2
openSUSE Leap 15.3
openSUSE Leap 15.4
openSUSE Leap 15.5
openSUSE Leap 42.1
openSUSE Leap 42.2
openSUSE Leap 42.3
pip::GitHub Security Advisory pip
pub::GitHub Security Advisory Pub
rocky 8
rocky 9
rubygems::GitHub Security Advisory RubyGems
rubygems::Ruby Advisory Database
swift::GitHub Security Advisory Swift
ubuntu 12.04
ubuntu 12.04-ESM
ubuntu 12.10
ubuntu 13.04
ubuntu 13.10
ubuntu 14.04
ubuntu 14.04-ESM
ubuntu 14.10
ubuntu 15.04
ubuntu 15.10
ubuntu 16.04
ubuntu 16.04-ESM
ubuntu 16.10
ubuntu 17.04
ubuntu 17.10
ubuntu 18.04
ubuntu 18.10
ubuntu 19.04
ubuntu 19.10
ubuntu 20.04
ubuntu 20.10
ubuntu 21.04
ubuntu 21.10
ubuntu 22.04
ubuntu 22.10
ubuntu 23.04
ubuntu 23.10
vulnerability
wolfi
读取指定系统的value,go代码
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
bolt "go.etcd.io/bbolt"
"os"
"time"
)
func main() {
//连接trivy数据库
db, err := bolt.Open("trivy.db", 0600, &bolt.Options{Timeout: 1 * time.Second})
if err != nil {
panic("init trivydb failed")
}
file, err := os.Create("file.txt")
if err != nil {
fmt.Println(err)
}
defer file.Close()
// 连接mysql数据库
dbmysql, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/trivy-db")
if err != nil {
fmt.Println("Failed to connect to database:", err.Error())
return
}
defer db.Close()
whitelist := []string{"ubuntu 12.04", "ubuntu 12.10", "ubuntu 13.04",
"ubuntu 13.10", "ubuntu 14.04", "ubuntu 14.10", "ubuntu 15.04",
"ubuntu 15.10", "ubuntu 16.04", "ubuntu 16.10", "ubuntu 17.04",
"ubuntu 17.10", "ubuntu 18.04", "ubuntu 18.10", "ubuntu 19.04",
"ubuntu 19.10", "ubuntu 20.04", "ubuntu 20.10", "ubuntu 21.04",
"ubuntu 21.10", "ubuntu 22.04", "ubuntu 22.10", "ubuntu 23.04",
"ubuntu 23.10"}
//查询数据库中的数据
db.View(func(tx *bolt.Tx) error {
//遍历所有桶
tx.ForEach(func(osname []byte, b *bolt.Bucket) error {
if containsWhitelist(whitelist, string(osname)) {
b.ForEach(func(k, v []byte) error {
// 遍历嵌套桶
b.ForEachBucket(func(k []byte) error {
//k 桶名 (包名)
packageName := string(k)
nestedbucket := b.Bucket([]byte(string(k)))
nestedbucket.ForEach(func(k, v []byte) error {
fmt.Fprintln(file, string(osname))
fmt.Fprintln(file, packageName)
fmt.Fprintln(file, string(k))
fmt.Fprintln(file, string(v))
//chuli(dbmysql, string(osname), packageName, string(k), string(v))
fmt.Println(dbmysql, string(osname), packageName, string(k), string(v))
return nil
})
return nil
})
return nil
})
return nil
} else {
fmt.Println("不在白名单中")
}
return nil
})
return nil
})
}
func chuli(dbmysql *sql.DB, osname string, name string, s string, s2 string) {
// 插入数据
stmt, err := dbmysql.Prepare("INSERT INTO " + "`" + osname + "`" + "(Pname, CVE,value) VALUES(?,?,?)")
if err != nil {
fmt.Println("Failed to prepare statement:", err.Error())
return
}
defer stmt.Close()
_, err = stmt.Exec(name, s, s2)
if err != nil {
fmt.Println("Failed to execute statement:", err.Error())
return
}
}
// containsWhitelist 检查给定的OS是否在白名单中
func containsWhitelist(whitelist []string, name string) bool {
for _, whiteName := range whitelist {
if whiteName == name {
return true
}
}
return false
}
如果想转存到数据库中,需要新建系统表,表结构:
CREATE TABLE `ubuntu 12.04` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`Pname` VARCHAR(500) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`CVE` VARCHAR(5000) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`value` VARCHAR(5000) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
INDEX `id` (`id`) USING BTREE
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=427755
;
数据库效果:
从13点到17点15分处理了四个小时,一个系统的已经接近百万条了,还没处理完,按照CVE区分确实太冗余了。。。
终于找到问题了,代码有一点小bug,多了一层遍历,怪不得这么多,而且刚好重复的次数是443次,因为之前统计过软件报名有443个,应该是多遍历了一遍软件包的桶 删掉这一层遍历b.ForEach(func(k, v []byte)
下面是修改后的代码:
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
bolt "go.etcd.io/bbolt"
"os"
"time"
)
func main() {
//连接trivy数据库
db, err := bolt.Open("trivy.db", 0600, &bolt.Options{Timeout: 1 * time.Second})
if err != nil {
panic("init trivydb failed")
}
file, err := os.Create("file.txt")
if err != nil {
fmt.Println(err)
}
defer file.Close()
// 连接mysql数据库
dbmysql, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/trivy-db")
if err != nil {
fmt.Println("Failed to connect to database:", err.Error())
return
}
defer db.Close()
whitelist := []string{"ubuntu 12.04", "ubuntu 12.10", "ubuntu 13.04",
"ubuntu 13.10", "ubuntu 14.04", "ubuntu 14.10", "ubuntu 15.04",
"ubuntu 15.10", "ubuntu 16.04", "ubuntu 16.10", "ubuntu 17.04",
"ubuntu 17.10", "ubuntu 18.04", "ubuntu 18.10", "ubuntu 19.04",
"ubuntu 19.10", "ubuntu 20.04", "ubuntu 20.10", "ubuntu 21.04",
"ubuntu 21.10", "ubuntu 22.04", "ubuntu 22.10", "ubuntu 23.04",
"ubuntu 23.10"}
//查询数据库中的数据
db.View(func(tx *bolt.Tx) error {
//遍历所有桶
tx.ForEach(func(osname []byte, b *bolt.Bucket) error {
if containsWhitelist(whitelist, string(osname)) {
b.ForEachBucket(func(k []byte) error {
//k 桶名 (包名)
packageName := string(k)
nestedbucket := b.Bucket([]byte(string(k)))
nestedbucket.ForEach(func(k, v []byte) error {
fmt.Fprintln(file, string(osname))
fmt.Fprintln(file, packageName)
fmt.Fprintln(file, string(k))
fmt.Fprintln(file, string(v))
//chuli(dbmysql, string(osname), packageName, string(k), string(v))
fmt.Println(dbmysql, string(osname), packageName, string(k), string(v))
return nil
})
return nil
})
return nil
} else {
fmt.Println("不在白名单中")
}
return nil
})
return nil
})
}
func chuli(dbmysql *sql.DB, osname string, name string, s string, s2 string) {
// 插入数据
stmt, err := dbmysql.Prepare("INSERT INTO " + "`" + osname + "`" + "(Pname, CVE,value) VALUES(?,?,?)")
if err != nil {
fmt.Println("Failed to prepare statement:", err.Error())
return
}
defer stmt.Close()
_, err = stmt.Exec(name, s, s2)
if err != nil {
fmt.Println("Failed to execute statement:", err.Error())
return
}
}
// containsWhitelist 检查给定的OS是否在白名单中
func containsWhitelist(whitelist []string, name string) bool {
for _, whiteName := range whitelist {
if whiteName == name {
return true
}
}
return false
}
可以把id列删除之后,通过查询数据库判断重复信息,应该是不会重复了(但愿吧