Display exploit codes information for each detected CVE-IDs (#729)
* add exploit * bug fix while loading config in TUI, display in format-full-text * fix readme
This commit is contained in:
committed by
Kota Kanbe
parent
678e72a8b6
commit
9865eab2c0
@@ -9,13 +9,15 @@ import (
|
||||
gostdb "github.com/knqyf263/gost/db"
|
||||
cvedb "github.com/kotakanbe/go-cve-dictionary/db"
|
||||
ovaldb "github.com/kotakanbe/goval-dictionary/db"
|
||||
exploitdb "github.com/mozqnet/go-exploitdb/db"
|
||||
)
|
||||
|
||||
// DBClient is a dictionarie's db client for reporting
|
||||
type DBClient struct {
|
||||
CveDB cvedb.DB
|
||||
OvalDB ovaldb.DB
|
||||
GostDB gostdb.DB
|
||||
CveDB cvedb.DB
|
||||
OvalDB ovaldb.DB
|
||||
GostDB gostdb.DB
|
||||
ExploitDB exploitdb.DB
|
||||
}
|
||||
|
||||
// DBClientConf has a configuration of Vulnerability DBs
|
||||
@@ -23,6 +25,7 @@ type DBClientConf struct {
|
||||
CveDictCnf config.GoCveDictConf
|
||||
OvalDictCnf config.GovalDictConf
|
||||
GostCnf config.GostConf
|
||||
ExploitCnf config.ExploitConf
|
||||
DebugSQL bool
|
||||
}
|
||||
|
||||
@@ -38,6 +41,10 @@ func (c DBClientConf) isGostViaHTTP() bool {
|
||||
return c.GostCnf.URL != "" && c.GostCnf.Type == "sqlite3"
|
||||
}
|
||||
|
||||
func (c DBClientConf) isExploitViaHTTP() bool {
|
||||
return c.ExploitCnf.URL != "" && c.ExploitCnf.Type == "sqlite3"
|
||||
}
|
||||
|
||||
// NewDBClient returns db clients
|
||||
func NewDBClient(cnf DBClientConf) (dbclient *DBClient, locked bool, err error) {
|
||||
cveDriver, locked, err := NewCveDB(cnf)
|
||||
@@ -63,10 +70,20 @@ func NewDBClient(cnf DBClientConf) (dbclient *DBClient, locked bool, err error)
|
||||
cnf.GostCnf.SQLite3Path, err)
|
||||
}
|
||||
|
||||
exploitdb, locked, err := NewExploitDB(cnf)
|
||||
if locked {
|
||||
return nil, true, fmt.Errorf("exploitDB is locked: %s",
|
||||
cnf.ExploitCnf.SQLite3Path)
|
||||
} else if err != nil {
|
||||
util.Log.Warnf("Unable to use exploitDB: %s, err: %s",
|
||||
cnf.ExploitCnf.SQLite3Path, err)
|
||||
}
|
||||
|
||||
return &DBClient{
|
||||
CveDB: cveDriver,
|
||||
OvalDB: ovaldb,
|
||||
GostDB: gostdb,
|
||||
CveDB: cveDriver,
|
||||
OvalDB: ovaldb,
|
||||
GostDB: gostdb,
|
||||
ExploitDB: exploitdb,
|
||||
}, false, nil
|
||||
}
|
||||
|
||||
@@ -143,6 +160,32 @@ func NewGostDB(cnf DBClientConf) (driver gostdb.DB, locked bool, err error) {
|
||||
return driver, false, nil
|
||||
}
|
||||
|
||||
// NewExploitDB returns db client for Exploit
|
||||
func NewExploitDB(cnf DBClientConf) (driver exploitdb.DB, locked bool, err error) {
|
||||
if cnf.isExploitViaHTTP() {
|
||||
return nil, false, nil
|
||||
}
|
||||
path := cnf.ExploitCnf.URL
|
||||
if cnf.ExploitCnf.Type == "sqlite3" {
|
||||
path = cnf.ExploitCnf.SQLite3Path
|
||||
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
util.Log.Warnf("--exploitdb-path=%s is not found. It's recommended to use exploit to improve scanning accuracy. To use exploit db database, see https://github.com/mozqnet/go-exploitdb", path)
|
||||
return nil, false, nil
|
||||
}
|
||||
}
|
||||
|
||||
util.Log.Debugf("Open exploit db (%s): %s", cnf.ExploitCnf.Type, path)
|
||||
if driver, locked, err = exploitdb.NewDB(cnf.ExploitCnf.Type, path, cnf.DebugSQL); err != nil {
|
||||
if locked {
|
||||
util.Log.Errorf("exploitDB is locked: %s", err)
|
||||
return nil, true, err
|
||||
}
|
||||
return nil, false, err
|
||||
}
|
||||
return driver, false, nil
|
||||
}
|
||||
|
||||
// CloseDB close dbs
|
||||
func (d DBClient) CloseDB() {
|
||||
if d.CveDB != nil {
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
c "github.com/future-architect/vuls/config"
|
||||
"github.com/future-architect/vuls/contrib/owasp-dependency-check/parser"
|
||||
"github.com/future-architect/vuls/cwe"
|
||||
"github.com/future-architect/vuls/exploit"
|
||||
"github.com/future-architect/vuls/gost"
|
||||
"github.com/future-architect/vuls/models"
|
||||
"github.com/future-architect/vuls/oval"
|
||||
@@ -40,6 +41,7 @@ import (
|
||||
gostdb "github.com/knqyf263/gost/db"
|
||||
cvedb "github.com/kotakanbe/go-cve-dictionary/db"
|
||||
ovaldb "github.com/kotakanbe/goval-dictionary/db"
|
||||
exploitdb "github.com/mozqnet/go-exploitdb/db"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -176,6 +178,14 @@ func FillCveInfo(dbclient DBClient, r *models.ScanResult, cpeURIs []string) erro
|
||||
return fmt.Errorf("Failed to fill with CVE: %s", err)
|
||||
}
|
||||
|
||||
util.Log.Infof("Fill Exploit information with Exploit-DB")
|
||||
nExploitCve, err := FillWithExploit(dbclient.ExploitDB, r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to fill with exploit: %s", err)
|
||||
}
|
||||
util.Log.Infof("%s: %d Exploits are detected with exploit",
|
||||
r.FormatServerName(), nExploitCve)
|
||||
|
||||
fillCweDict(r)
|
||||
return nil
|
||||
}
|
||||
@@ -292,6 +302,14 @@ func FillWithGost(driver gostdb.DB, r *models.ScanResult) (nCVEs int, err error)
|
||||
return gostClient.FillWithGost(driver, r)
|
||||
}
|
||||
|
||||
// FillWithExploit fills Exploits with exploit dataabase
|
||||
// https://github.com/mozqnet/go-exploitdb
|
||||
func FillWithExploit(driver exploitdb.DB, r *models.ScanResult) (nExploitCve int, err error) {
|
||||
// TODO chekc if fetched
|
||||
// TODO chekc if fresh enough
|
||||
return exploit.FillWithExploit(driver, r)
|
||||
}
|
||||
|
||||
func fillVulnByCpeURIs(driver cvedb.DB, r *models.ScanResult, cpeURIs []string) (nCVEs int, err error) {
|
||||
for _, name := range cpeURIs {
|
||||
details, err := CveClient.FetchCveDetailsByCpeName(driver, name)
|
||||
@@ -454,6 +472,7 @@ func EnsureUUIDs(configPath string, results models.ScanResults) error {
|
||||
cveDict := &c.Conf.CveDict
|
||||
ovalDict := &c.Conf.OvalDict
|
||||
gost := &c.Conf.Gost
|
||||
exploit := &c.Conf.Exploit
|
||||
http := &c.Conf.HTTP
|
||||
if http.URL == "" {
|
||||
http = nil
|
||||
@@ -498,6 +517,7 @@ func EnsureUUIDs(configPath string, results models.ScanResults) error {
|
||||
CveDict *c.GoCveDictConf `toml:"cveDict"`
|
||||
OvalDict *c.GovalDictConf `toml:"ovalDict"`
|
||||
Gost *c.GostConf `toml:"gost"`
|
||||
Exploit *c.ExploitConf `toml:"exploit"`
|
||||
Slack *c.SlackConf `toml:"slack"`
|
||||
Email *c.SMTPConf `toml:"email"`
|
||||
HTTP *c.HTTPConf `toml:"http"`
|
||||
@@ -515,6 +535,7 @@ func EnsureUUIDs(configPath string, results models.ScanResults) error {
|
||||
CveDict: cveDict,
|
||||
OvalDict: ovalDict,
|
||||
Gost: gost,
|
||||
Exploit: exploit,
|
||||
Slack: slack,
|
||||
Email: email,
|
||||
HTTP: http,
|
||||
|
||||
@@ -743,6 +743,16 @@ func setChangelogLayout(g *gocui.Gui) error {
|
||||
lines = append(lines, adv.Format())
|
||||
}
|
||||
|
||||
if len(vinfo.Exploits) != 0 {
|
||||
lines = append(lines, "\n",
|
||||
"Exploit Codes",
|
||||
"=============",
|
||||
)
|
||||
for _, exploit := range vinfo.Exploits {
|
||||
lines = append(lines, fmt.Sprintf("* [%s](%s)", exploit.Description, exploit.URL))
|
||||
}
|
||||
}
|
||||
|
||||
if currentScanResult.IsDeepScanMode() {
|
||||
lines = append(lines, "\n",
|
||||
"ChangeLogs",
|
||||
@@ -770,6 +780,7 @@ func setChangelogLayout(g *gocui.Gui) error {
|
||||
type dataForTmpl struct {
|
||||
CveID string
|
||||
Cvsses string
|
||||
Exploits []models.Exploit
|
||||
Summary string
|
||||
Mitigation string
|
||||
Confidences models.Confidences
|
||||
@@ -877,6 +888,7 @@ const mdTemplate = `
|
||||
CVSS Scores
|
||||
-----------
|
||||
{{.Cvsses }}
|
||||
|
||||
Summary
|
||||
-----------
|
||||
{{.Summary }}
|
||||
|
||||
@@ -50,6 +50,7 @@ func formatScanSummary(rs ...models.ScanResult) string {
|
||||
r.FormatServerName(),
|
||||
fmt.Sprintf("%s%s", r.Family, r.Release),
|
||||
r.FormatUpdatablePacksSummary(),
|
||||
r.FormatExploitCveSummary(),
|
||||
}
|
||||
} else {
|
||||
cols = []interface{}{
|
||||
@@ -76,6 +77,7 @@ func formatOneLineSummary(rs ...models.ScanResult) string {
|
||||
r.ScannedCves.FormatCveSummary(),
|
||||
r.ScannedCves.FormatFixedStatus(r.Packages),
|
||||
r.FormatUpdatablePacksSummary(),
|
||||
r.FormatExploitCveSummary(),
|
||||
}
|
||||
} else {
|
||||
cols = []interface{}{
|
||||
@@ -123,6 +125,7 @@ No CVE-IDs are found in updatable packages.
|
||||
fmt.Sprintf("%7s", vinfo.PatchStatus(r.Packages)),
|
||||
// packname,
|
||||
fmt.Sprintf("https://nvd.nist.gov/vuln/detail/%s", vinfo.CveID),
|
||||
fmt.Sprintf("%t", 0 < len(vinfo.Exploits)),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -137,6 +140,7 @@ No CVE-IDs are found in updatable packages.
|
||||
"Fixed",
|
||||
// "Pkg",
|
||||
"NVD",
|
||||
"Exploit",
|
||||
})
|
||||
table.SetBorder(true)
|
||||
table.AppendBulk(data)
|
||||
@@ -250,6 +254,9 @@ No CVE-IDs are found in updatable packages.
|
||||
for _, url := range cweURLs {
|
||||
data = append(data, []string{"CWE", url})
|
||||
}
|
||||
for _, exploit := range vuln.Exploits {
|
||||
data = append(data, []string{string(exploit.ExploitType), exploit.URL})
|
||||
}
|
||||
for _, url := range top10URLs {
|
||||
data = append(data, []string{"OWASP Top10", url})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user