Display metasploit module information for each detected CVE-IDs (#1011)

* add metasploit

* fix go deps

* fix msf report

* fix msfdb server port number

* delete non-unique msfdb url from fulltext report

* fix(report): validate msfdb config on report (#1)

* fix(msfdb): update deps (go-msfdb)

* version up go-msfdb v0.1.0

Co-authored-by: Kota Kanbe <kotakanbe@gmail.com>
This commit is contained in:
takuzoo
2020-07-03 14:05:07 +09:00
committed by GitHub
parent 89f49b0e29
commit 11a7a0c934
15 changed files with 539 additions and 87 deletions

View File

@@ -9,24 +9,27 @@ import (
cvedb "github.com/kotakanbe/go-cve-dictionary/db"
ovaldb "github.com/kotakanbe/goval-dictionary/db"
exploitdb "github.com/mozqnet/go-exploitdb/db"
metasploitdb "github.com/takuzoo3868/go-msfdb/db"
"golang.org/x/xerrors"
)
// DBClient is a dictionarie's db client for reporting
type DBClient struct {
CveDB cvedb.DB
OvalDB ovaldb.DB
GostDB gostdb.DB
ExploitDB exploitdb.DB
CveDB cvedb.DB
OvalDB ovaldb.DB
GostDB gostdb.DB
ExploitDB exploitdb.DB
MetasploitDB metasploitdb.DB
}
// DBClientConf has a configuration of Vulnerability DBs
type DBClientConf struct {
CveDictCnf config.GoCveDictConf
OvalDictCnf config.GovalDictConf
GostCnf config.GostConf
ExploitCnf config.ExploitConf
DebugSQL bool
CveDictCnf config.GoCveDictConf
OvalDictCnf config.GovalDictConf
GostCnf config.GostConf
ExploitCnf config.ExploitConf
MetasploitCnf config.MetasploitConf
DebugSQL bool
}
// NewDBClient returns db clients
@@ -66,11 +69,21 @@ func NewDBClient(cnf DBClientConf) (dbclient *DBClient, locked bool, err error)
cnf.ExploitCnf.SQLite3Path, err)
}
metasploitdb, locked, err := NewMetasploitDB(cnf)
if locked {
return nil, true, xerrors.Errorf("metasploitDB is locked: %s",
cnf.MetasploitCnf.SQLite3Path)
} else if err != nil {
util.Log.Warnf("Unable to use metasploitDB: %s, err: %s",
cnf.MetasploitCnf.SQLite3Path, err)
}
return &DBClient{
CveDB: cveDriver,
OvalDB: ovaldb,
GostDB: gostdb,
ExploitDB: exploitdb,
CveDB: cveDriver,
OvalDB: ovaldb,
GostDB: gostdb,
ExploitDB: exploitdb,
MetasploitDB: metasploitdb,
}, false, nil
}
@@ -177,6 +190,32 @@ func NewExploitDB(cnf DBClientConf) (driver exploitdb.DB, locked bool, err error
return driver, false, nil
}
// NewMetasploitDB returns db client for Metasploit
func NewMetasploitDB(cnf DBClientConf) (driver metasploitdb.DB, locked bool, err error) {
if config.Conf.Metasploit.IsFetchViaHTTP() {
return nil, false, nil
}
path := cnf.MetasploitCnf.URL
if cnf.MetasploitCnf.Type == "sqlite3" {
path = cnf.MetasploitCnf.SQLite3Path
if _, err := os.Stat(path); os.IsNotExist(err) {
util.Log.Warnf("--msfdb-path=%s file not found. Fetch go-msfdb before reporting if you want to display metasploit modules of detected CVE-IDs. For details, see `https://github.com/takuzoo3868/go-msfdb`", path)
return nil, false, nil
}
}
util.Log.Debugf("Open metasploit db (%s): %s", cnf.MetasploitCnf.Type, path)
if driver, locked, err = metasploitdb.NewDB(cnf.MetasploitCnf.Type, path, cnf.DebugSQL, false); err != nil {
if locked {
util.Log.Errorf("metasploitDB is locked. err: %+v", err)
return nil, true, err
}
return nil, false, err
}
return driver, false, nil
}
// CloseDB close dbs
func (d DBClient) CloseDB() {
if d.CveDB != nil {

View File

@@ -22,6 +22,7 @@ import (
"github.com/future-architect/vuls/github"
"github.com/future-architect/vuls/gost"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/msf"
"github.com/future-architect/vuls/oval"
"github.com/future-architect/vuls/util"
"github.com/future-architect/vuls/wordpress"
@@ -31,6 +32,7 @@ import (
cvemodels "github.com/kotakanbe/go-cve-dictionary/models"
ovaldb "github.com/kotakanbe/goval-dictionary/db"
exploitdb "github.com/mozqnet/go-exploitdb/db"
metasploitdb "github.com/takuzoo3868/go-msfdb/db"
"golang.org/x/xerrors"
)
@@ -208,6 +210,14 @@ func FillCveInfo(dbclient DBClient, r *models.ScanResult, cpeURIs []string, igno
util.Log.Infof("%s: %d exploits are detected",
r.FormatServerName(), nExploitCve)
util.Log.Infof("Fill metasploit module information with Metasploit-DB")
nMetasploitCve, err := FillWithMetasploit(dbclient.MetasploitDB, r)
if err != nil {
return xerrors.Errorf("Failed to fill with metasploit: %w", err)
}
util.Log.Infof("%s: %d modules are detected",
r.FormatServerName(), nMetasploitCve)
fillCweDict(r)
return nil
}
@@ -358,6 +368,12 @@ func FillWithExploit(driver exploitdb.DB, r *models.ScanResult) (nExploitCve int
return exploit.FillWithExploit(driver, r)
}
// FillWithMetasploit fills metasploit modules with metasploit database
// https://github.com/takuzoo3868/go-msfdb
func FillWithMetasploit(driver metasploitdb.DB, r *models.ScanResult) (nMetasploitCve int, err error) {
return msf.FillWithMetasploit(driver, r)
}
func fillVulnByCpeURIs(driver cvedb.DB, r *models.ScanResult, cpeURIs []string) (nCVEs int, err error) {
if len(cpeURIs) != 0 && driver == nil && !config.Conf.CveDict.IsFetchViaHTTP() {
return 0, xerrors.Errorf("cpeURIs %s specified, but cve-dictionary DB not found. Fetch cve-dictionary beofre reporting. For details, see `https://github.com/kotakanbe/go-cve-dictionary#deploy-go-cve-dictionary`",
@@ -605,6 +621,7 @@ func EnsureUUIDs(configPath string, results models.ScanResults) (err error) {
ovalDict := &c.Conf.OvalDict
gost := &c.Conf.Gost
exploit := &c.Conf.Exploit
metasploit := &c.Conf.Metasploit
http := &c.Conf.HTTP
if http.URL == "" {
http = nil
@@ -646,38 +663,40 @@ func EnsureUUIDs(configPath string, results models.ScanResults) (err error) {
}
c := struct {
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"`
Syslog *c.SyslogConf `toml:"syslog"`
AWS *c.AWS `toml:"aws"`
Azure *c.Azure `toml:"azure"`
Stride *c.StrideConf `toml:"stride"`
HipChat *c.HipChatConf `toml:"hipChat"`
ChatWork *c.ChatWorkConf `toml:"chatWork"`
Saas *c.SaasConf `toml:"saas"`
CveDict *c.GoCveDictConf `toml:"cveDict"`
OvalDict *c.GovalDictConf `toml:"ovalDict"`
Gost *c.GostConf `toml:"gost"`
Exploit *c.ExploitConf `toml:"exploit"`
Metasploit *c.MetasploitConf `toml:"metasploit"`
Slack *c.SlackConf `toml:"slack"`
Email *c.SMTPConf `toml:"email"`
HTTP *c.HTTPConf `toml:"http"`
Syslog *c.SyslogConf `toml:"syslog"`
AWS *c.AWS `toml:"aws"`
Azure *c.Azure `toml:"azure"`
Stride *c.StrideConf `toml:"stride"`
HipChat *c.HipChatConf `toml:"hipChat"`
ChatWork *c.ChatWorkConf `toml:"chatWork"`
Saas *c.SaasConf `toml:"saas"`
Default c.ServerInfo `toml:"default"`
Servers map[string]c.ServerInfo `toml:"servers"`
}{
CveDict: cveDict,
OvalDict: ovalDict,
Gost: gost,
Exploit: exploit,
Slack: slack,
Email: email,
HTTP: http,
Syslog: syslog,
AWS: aws,
Azure: azure,
Stride: stride,
HipChat: hipChat,
ChatWork: chatWork,
Saas: saas,
CveDict: cveDict,
OvalDict: ovalDict,
Gost: gost,
Exploit: exploit,
Metasploit: metasploit,
Slack: slack,
Email: email,
HTTP: http,
Syslog: syslog,
AWS: aws,
Azure: azure,
Stride: stride,
HipChat: hipChat,
ChatWork: chatWork,
Saas: saas,
Default: c.Conf.Default,
Servers: c.Conf.Servers,

View File

@@ -618,7 +618,7 @@ func summaryLines(r models.ScanResult) string {
pkgNames = append(pkgNames, vinfo.LibraryFixedIns.Names()...)
exploits := ""
if 0 < len(vinfo.Exploits) {
if 0 < len(vinfo.Exploits) || 0 < len(vinfo.Metasploits) {
exploits = "POC"
}
@@ -770,6 +770,21 @@ func setChangelogLayout(g *gocui.Gui) error {
}
}
if len(vinfo.Metasploits) != 0 {
lines = append(lines, "\n",
"Metasploit Modules",
"==================",
)
for _, module := range vinfo.Metasploits {
lines = append(lines, fmt.Sprintf("* %s: %s", module.Name, module.Description))
if 0 < len(module.URLs) {
for _, u := range module.URLs {
lines = append(lines, fmt.Sprintf(" - %s", u))
}
}
}
}
if len(vinfo.AlertDict.En) > 0 {
lines = append(lines, "\n",
"USCERT Alert",
@@ -822,6 +837,7 @@ type dataForTmpl struct {
CveID string
Cvsses string
Exploits []models.Exploit
Metasploits []models.Metasploit
Summary string
Mitigation string
Confidences models.Confidences

View File

@@ -71,6 +71,7 @@ func formatOneLineSummary(rs ...models.ScanResult) string {
r.ScannedCves.FormatFixedStatus(r.Packages),
r.FormatUpdatablePacksSummary(),
r.FormatExploitCveSummary(),
r.FormatMetasploitCveSummary(),
r.FormatAlertSummary(),
}
} else {
@@ -126,7 +127,7 @@ No CVE-IDs are found in updatable packages.
// packname += strings.Join(vinfo.CpeURIs, ", ")
exploits := ""
if 0 < len(vinfo.Exploits) {
if 0 < len(vinfo.Exploits) || 0 < len(vinfo.Metasploits) {
exploits = "POC"
}