mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 17:05:18 +00:00
Add filter software by CVE and make osquery-perf also push vulnerable software (#3902)
* Add filter software by CVE and make osquery-perf also push vulnerable software * Update based on review comments
This commit is contained in:
parent
99468ff477
commit
e956b0ba04
1
changes/issue-2998-software-cve-search
Normal file
1
changes/issue-2998-software-cve-search
Normal file
@ -0,0 +1 @@
|
|||||||
|
* Add filter software by CVE
|
@ -26,6 +26,32 @@ import (
|
|||||||
//go:embed *.tmpl
|
//go:embed *.tmpl
|
||||||
var templatesFS embed.FS
|
var templatesFS embed.FS
|
||||||
|
|
||||||
|
//go:embed *.software
|
||||||
|
var softwareFS embed.FS
|
||||||
|
|
||||||
|
var vulnerableSoftware []fleet.Software
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
vulnerableSoftwareData, err := softwareFS.ReadFile("vulnerable.software")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("reading vulnerable software file: ", err)
|
||||||
|
}
|
||||||
|
lines := bytes.Split(vulnerableSoftwareData, []byte("\n"))
|
||||||
|
for _, line := range lines {
|
||||||
|
parts := bytes.Split(line, []byte("##"))
|
||||||
|
if len(parts) < 2 {
|
||||||
|
fmt.Println("skipping", string(line))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
vulnerableSoftware = append(vulnerableSoftware, fleet.Software{
|
||||||
|
Name: string(parts[0]),
|
||||||
|
Version: string(parts[1]),
|
||||||
|
Source: "apps",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
log.Printf("Loaded %d vulnerable software\n", len(vulnerableSoftware))
|
||||||
|
}
|
||||||
|
|
||||||
type Stats struct {
|
type Stats struct {
|
||||||
errors int
|
errors int
|
||||||
enrollments int
|
enrollments int
|
||||||
@ -120,7 +146,7 @@ func (n *nodeKeyManager) Add(nodekey string) {
|
|||||||
|
|
||||||
type agent struct {
|
type agent struct {
|
||||||
agentIndex int
|
agentIndex int
|
||||||
softwareCount entityCount
|
softwareCount softwareEntityCount
|
||||||
userCount entityCount
|
userCount entityCount
|
||||||
policyPassProb float64
|
policyPassProb float64
|
||||||
strings map[string]string
|
strings map[string]string
|
||||||
@ -146,10 +172,15 @@ type entityCount struct {
|
|||||||
unique int
|
unique int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type softwareEntityCount struct {
|
||||||
|
entityCount
|
||||||
|
vulnerable int
|
||||||
|
}
|
||||||
|
|
||||||
func newAgent(
|
func newAgent(
|
||||||
agentIndex int,
|
agentIndex int,
|
||||||
serverAddress, enrollSecret string, templates *template.Template,
|
serverAddress, enrollSecret string, templates *template.Template,
|
||||||
configInterval, queryInterval time.Duration, softwareCount, userCount entityCount,
|
configInterval, queryInterval time.Duration, softwareCount softwareEntityCount, userCount entityCount,
|
||||||
policyPassProb float64,
|
policyPassProb float64,
|
||||||
) *agent {
|
) *agent {
|
||||||
transport := http.DefaultTransport.(*http.Transport).Clone()
|
transport := http.DefaultTransport.(*http.Transport).Clone()
|
||||||
@ -386,7 +417,12 @@ func (a *agent) SoftwareMacOS() []fleet.Software {
|
|||||||
Source: "osquery-perf",
|
Source: "osquery-perf",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
randomVulnerableSoftware := make([]fleet.Software, a.softwareCount.vulnerable)
|
||||||
|
for i := 0; i < len(randomVulnerableSoftware); i++ {
|
||||||
|
randomVulnerableSoftware[i] = vulnerableSoftware[rand.Intn(len(vulnerableSoftware))]
|
||||||
|
}
|
||||||
software := append(commonSoftware, uniqueSoftware...)
|
software := append(commonSoftware, uniqueSoftware...)
|
||||||
|
software = append(software, randomVulnerableSoftware...)
|
||||||
rand.Shuffle(len(software), func(i, j int) {
|
rand.Shuffle(len(software), func(i, j int) {
|
||||||
software[i], software[j] = software[j], software[i]
|
software[i], software[j] = software[j], software[i]
|
||||||
})
|
})
|
||||||
@ -575,6 +611,7 @@ func main() {
|
|||||||
nodeKeyFile := flag.String("node_key_file", "", "File with node keys to use")
|
nodeKeyFile := flag.String("node_key_file", "", "File with node keys to use")
|
||||||
commonSoftwareCount := flag.Int("common_software_count", 10, "Number of common of installed applications reported to fleet")
|
commonSoftwareCount := flag.Int("common_software_count", 10, "Number of common of installed applications reported to fleet")
|
||||||
uniqueSoftwareCount := flag.Int("unique_software_count", 10, "Number of unique installed applications reported to fleet")
|
uniqueSoftwareCount := flag.Int("unique_software_count", 10, "Number of unique installed applications reported to fleet")
|
||||||
|
vulnerableSoftwareCount := flag.Int("vulnerable_software_count", 10, "Number of vulnerable installed applications reported to fleet")
|
||||||
commonUserCount := flag.Int("common_user_count", 10, "Number of common host users reported to fleet")
|
commonUserCount := flag.Int("common_user_count", 10, "Number of common host users reported to fleet")
|
||||||
uniqueUserCount := flag.Int("unique_user_count", 10, "Number of unique host users reported to fleet")
|
uniqueUserCount := flag.Int("unique_user_count", 10, "Number of unique host users reported to fleet")
|
||||||
policyPassProb := flag.Float64("policy_pass_prob", 1.0, "Probability of policies to pass [0, 1]")
|
policyPassProb := flag.Float64("policy_pass_prob", 1.0, "Probability of policies to pass [0, 1]")
|
||||||
@ -602,9 +639,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < *hostCount; i++ {
|
for i := 0; i < *hostCount; i++ {
|
||||||
a := newAgent(i+1, *serverURL, *enrollSecret, tmpl, *configInterval, *queryInterval, entityCount{
|
a := newAgent(i+1, *serverURL, *enrollSecret, tmpl, *configInterval, *queryInterval, softwareEntityCount{
|
||||||
|
entityCount: entityCount{
|
||||||
common: *commonSoftwareCount,
|
common: *commonSoftwareCount,
|
||||||
unique: *uniqueSoftwareCount,
|
unique: *uniqueSoftwareCount,
|
||||||
|
},
|
||||||
|
vulnerable: *vulnerableSoftwareCount,
|
||||||
}, entityCount{
|
}, entityCount{
|
||||||
common: *commonUserCount,
|
common: *commonUserCount,
|
||||||
unique: *uniqueUserCount,
|
unique: *uniqueUserCount,
|
||||||
|
108
cmd/osquery-perf/vulnerable.software
Normal file
108
cmd/osquery-perf/vulnerable.software
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
monal##4.9
|
||||||
|
flash_player##10.3.183.90
|
||||||
|
office##2021
|
||||||
|
meetings##5.8.0
|
||||||
|
kinza##5.0.1
|
||||||
|
insync##6.8.0
|
||||||
|
last.fm_desktop##2.1.39
|
||||||
|
ipvanish##3.0.11
|
||||||
|
galaxy##1.2.54
|
||||||
|
autocad##2022
|
||||||
|
globalprotect##5.1.2
|
||||||
|
malwarebytes##4.0
|
||||||
|
wing_ftp_server##6.2.3
|
||||||
|
wd_discovery##4.0.251.0
|
||||||
|
intercept_x##9.10.1
|
||||||
|
safe##17.7
|
||||||
|
edgerover##1.5.0-576
|
||||||
|
fusion##8.5
|
||||||
|
true_image##2021
|
||||||
|
internet_security##21.1
|
||||||
|
knox##2.2.0
|
||||||
|
remote_desktop##10.6.7
|
||||||
|
1password##7.2.3
|
||||||
|
canvas_draw##5.0.0
|
||||||
|
arq##5.9
|
||||||
|
parallels_desktop##16.5.0
|
||||||
|
windscribe##2.02.9
|
||||||
|
zoom##4.6.9
|
||||||
|
connect##3.2.7
|
||||||
|
armorlock##1.4.1
|
||||||
|
home##10.0.3
|
||||||
|
photoline##20.53
|
||||||
|
vpn_universal_secure_enterprise_client##2.02
|
||||||
|
nordvpn##3.3.10
|
||||||
|
wire##3.9.2943
|
||||||
|
proxifier##3.5
|
||||||
|
pulse_secure_desktop_client##9.0r1
|
||||||
|
liquidvpn##1.37
|
||||||
|
forticlient##7.0.1
|
||||||
|
endpoint_security##10.7.5
|
||||||
|
royal_tsx##3.3
|
||||||
|
realone_player##9.0.0.297
|
||||||
|
anyconnect_secure_mobility_client##4.9.03047
|
||||||
|
macos##9
|
||||||
|
office_long_term_servicing_channel##2021
|
||||||
|
remotepc##7.6.9
|
||||||
|
norton_security##13.0.1
|
||||||
|
macos_server##5.11
|
||||||
|
zoom_plugin_for_microsoft_outlook##5.7.6.76
|
||||||
|
rumpus##8.2.14
|
||||||
|
kanaka##2.8
|
||||||
|
dashlane##6.5.0
|
||||||
|
anti-virus_for_sophos_home##2.2.6
|
||||||
|
origin##10.5.86
|
||||||
|
outlook##2016
|
||||||
|
proxyman##1.9.3
|
||||||
|
forklift##3.4
|
||||||
|
vpn_universal_secure_entry_client##2.02
|
||||||
|
realplayer##12.0.1.1738
|
||||||
|
foxmail##1.2
|
||||||
|
purevpn##6.0.1
|
||||||
|
hipchat##4.30
|
||||||
|
jabber##12.9\(3\)
|
||||||
|
quicken_2018##5.2.2
|
||||||
|
shimo##4.1.5.1
|
||||||
|
evernote##8.3.2
|
||||||
|
vtune_profiler##2020
|
||||||
|
hide.me##3.3.0
|
||||||
|
visual_studio_2019##8.9
|
||||||
|
mcafee_agent##5.6.6
|
||||||
|
antivirus##9.0
|
||||||
|
maxthon_browser##5.1.46
|
||||||
|
renderman##22.3.0
|
||||||
|
install_norton_security##7.6
|
||||||
|
line##4.3.1
|
||||||
|
nextcloud##2.7.0
|
||||||
|
zenmate##1.5.4
|
||||||
|
anti-virus_for_sophos_central##9.9.6
|
||||||
|
ibackup##3.3.1.5
|
||||||
|
join.me##3.9.0.11823
|
||||||
|
ni-pal##20.0.1
|
||||||
|
privatevpn##2.0.31
|
||||||
|
cyber_security##6.8.300.0
|
||||||
|
malion##5.2.1
|
||||||
|
endpoint_protection##14
|
||||||
|
ubridge##0.9.9
|
||||||
|
vyprvpn##3.0
|
||||||
|
skype##8.59.0.77
|
||||||
|
sourcetree##3.1
|
||||||
|
hugo##0.9
|
||||||
|
excel##2019
|
||||||
|
password_manager##5.0.1073
|
||||||
|
cactusvpn##6.5.0
|
||||||
|
spectrum_protect_client##8.1.6
|
||||||
|
horizon##5.2.0
|
||||||
|
airmail_3##3.5.9
|
||||||
|
viscosity##1.4.1
|
||||||
|
switchvpn##2.1012.03
|
||||||
|
pcoip_soft_client##20.10.1
|
||||||
|
keybase##2.12.6
|
||||||
|
backblaze##7.0.1.434
|
||||||
|
hisuite##9.1.0.312
|
||||||
|
anydesk##6.1.0
|
||||||
|
swoole##1.6.7
|
||||||
|
stashcat##3.9.2
|
||||||
|
endpoint_antivirus##6.8.1.0
|
||||||
|
webex_meetings##40.1.8.5
|
||||||
|
autocad_lt##2022
|
@ -5947,7 +5947,7 @@ Transforms a host name into a host id. For example, the Fleet UI use this endpoi
|
|||||||
| per_page | integer | query | Results per page. |
|
| per_page | integer | query | Results per page. |
|
||||||
| order_key | string | query | What to order results by. Can be ordered by the following fields: `name`, `hosts_count`. Defaults to the hosts count, descending. |
|
| order_key | string | query | What to order results by. Can be ordered by the following fields: `name`, `hosts_count`. Defaults to the hosts count, descending. |
|
||||||
| order_direction | string | query | **Requires `order_key`**. The direction of the order given the order key. Options include `asc` and `desc`. Default if not provided is `asc`. |
|
| order_direction | string | query | **Requires `order_key`**. The direction of the order given the order key. Options include `asc` and `desc`. Default if not provided is `asc`. |
|
||||||
| query | string | query | Search query keywords. Searchable fields include `name`. |
|
| query | string | query | Search query keywords. Searchable fields include `name`, `version`, and `cve`. |
|
||||||
| team_id | integer | query | _Available in Fleet Premium_ Filters the software to only include the software installed on the hosts that are assigned to the specified team. |
|
| team_id | integer | query | _Available in Fleet Premium_ Filters the software to only include the software installed on the hosts that are assigned to the specified team. |
|
||||||
| vulnerable | bool | query | If true or 1, only list software that has detected vulnerabilities |
|
| vulnerable | bool | query | If true or 1, only list software that has detected vulnerabilities |
|
||||||
|
|
||||||
|
@ -267,16 +267,6 @@ func selectSoftwareSQL(hostID *uint, opts fleet.SoftwareListOptions) (string, []
|
|||||||
).Where(goqu.I("h.team_id").Eq(opts.TeamID))
|
).Where(goqu.I("h.team_id").Eq(opts.TeamID))
|
||||||
}
|
}
|
||||||
|
|
||||||
if match := opts.MatchQuery; match != "" {
|
|
||||||
match = likePattern(match)
|
|
||||||
ds = ds.Where(
|
|
||||||
goqu.Or(
|
|
||||||
goqu.I("s.name").ILike(match),
|
|
||||||
goqu.I("s.version").ILike(match),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
ds = ds.GroupBy(
|
ds = ds.GroupBy(
|
||||||
goqu.I("s.id"),
|
goqu.I("s.id"),
|
||||||
goqu.I("s.name"),
|
goqu.I("s.name"),
|
||||||
@ -304,6 +294,23 @@ func selectSoftwareSQL(hostID *uint, opts fleet.SoftwareListOptions) (string, []
|
|||||||
goqu.I("s.id").Eq(goqu.I("scp.software_id")),
|
goqu.I("s.id").Eq(goqu.I("scp.software_id")),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
if opts.MatchQuery != "" {
|
||||||
|
ds = ds.LeftJoin(
|
||||||
|
goqu.I("software_cve").As("scv"),
|
||||||
|
goqu.On(goqu.I("scp.id").Eq(goqu.I("scv.cpe_id"))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if match := opts.MatchQuery; match != "" {
|
||||||
|
match = likePattern(match)
|
||||||
|
ds = ds.Where(
|
||||||
|
goqu.Or(
|
||||||
|
goqu.I("s.name").ILike(match),
|
||||||
|
goqu.I("s.version").ILike(match),
|
||||||
|
goqu.I("scv.cve").ILike(match),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.WithHostCounts {
|
if opts.WithHostCounts {
|
||||||
|
@ -452,6 +452,24 @@ func testSoftwareList(t *testing.T, ds *Datastore) {
|
|||||||
test.ElementsMatchSkipID(t, software, expected)
|
test.ElementsMatchSkipID(t, software, expected)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("filters specific cves", func(t *testing.T) {
|
||||||
|
software := listSoftwareCheckCount(t, ds, 1, 1, fleet.SoftwareListOptions{ListOptions: fleet.ListOptions{MatchQuery: "cve-321-432-543"}}, true)
|
||||||
|
expected := []fleet.Software{foo001}
|
||||||
|
test.ElementsMatchSkipID(t, software, expected)
|
||||||
|
|
||||||
|
software = listSoftwareCheckCount(t, ds, 1, 1, fleet.SoftwareListOptions{ListOptions: fleet.ListOptions{MatchQuery: "cve-333-444-555"}}, true)
|
||||||
|
expected = []fleet.Software{foo001}
|
||||||
|
test.ElementsMatchSkipID(t, software, expected)
|
||||||
|
|
||||||
|
// partial cve
|
||||||
|
software = listSoftwareCheckCount(t, ds, 1, 1, fleet.SoftwareListOptions{ListOptions: fleet.ListOptions{MatchQuery: "333-444"}}, true)
|
||||||
|
expected = []fleet.Software{foo001}
|
||||||
|
test.ElementsMatchSkipID(t, software, expected)
|
||||||
|
|
||||||
|
// unknown CVE
|
||||||
|
listSoftwareCheckCount(t, ds, 0, 0, fleet.SoftwareListOptions{ListOptions: fleet.ListOptions{MatchQuery: "cve-000-000-000"}}, true)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("filters by query", func(t *testing.T) {
|
t.Run("filters by query", func(t *testing.T) {
|
||||||
// query by name (case insensitive)
|
// query by name (case insensitive)
|
||||||
software := listSoftwareCheckCount(t, ds, 1, 1, fleet.SoftwareListOptions{ListOptions: fleet.ListOptions{MatchQuery: "baR"}}, true)
|
software := listSoftwareCheckCount(t, ds, 1, 1, fleet.SoftwareListOptions{ListOptions: fleet.ListOptions{MatchQuery: "baR"}}, true)
|
||||||
|
Loading…
Reference in New Issue
Block a user