Compare commits

...

16 Commits

Author SHA1 Message Date
Norihiro NAKAOKA
83bcca6e66 experimental: add smart(fast, minimum ports, silently) TCP port scanner (#1060)
* add struct ListenPorts

* change parse to models.ListenPorts from string

* change support models.ListenPorts in TUI

* add scanPort template , detectScanDest

* add Test_detectScanDest

* change impl scanPorts template

* fix build error

* change collect scan success address

* add Test_matchListenPorts

* add Test_updatePortStatus

* change display port scan result on tui

* change display scan emoji on report

* Revert "change display scan emoji on report"

This reverts commit e281882cc6.

* add continue

* change display format

* change no use loop label

* remove comment code

* change display

* fix padding

* change refactoring var , fn name

* fix var name

* fix var name

* change eye icon

* change icon

* delete unuse mod
2020-10-19 17:47:20 +09:00
Kota Kanbe
a124518d78 fix: hard-coded version #1057 (#1059) 2020-10-16 20:42:31 +09:00
Alexander Stein
94bf630e29 Expand negative grep match for any error for lib scans. (#1056)
Many thanks 👍 

Sure, that's better.

Note: FreeBSD
find: `find: /var/run/ppp: Permission denied`
2020-10-12 11:30:11 +09:00
shopper
31bb33fd90 ignore apk warning (#1052) 2020-10-12 10:40:01 +09:00
Kota Kanbe
4b680b9960 fix(scan-freebsd): also get installed with pkg info #1042 (#1051)
* fix(scan-freebsd): also get installed with `pkg info` #1042

* fix test
2020-09-12 05:08:41 +09:00
Kota Kanbe
8a8ab8cb18 feat(libscan): enable to scan vulns of libs with pseudo #1035 (#1050) 2020-09-11 13:09:59 +09:00
Kota Kanbe
8146f5fd1b update readme (#1049) 2020-09-11 10:26:57 +09:00
shopper
425c585e47 Support for smtp LOGIN authentication (#1048)
* finished to implement new mail client

* delete email_test.go
2020-09-04 15:45:29 +09:00
Kota Kanbe
4f1578b2d6 [WIP]fix(scan): collect a running version of kernel-devel (#1044)
* fix(scan): collect a running kernel-devel version

* refactor
2020-09-01 14:37:40 +09:00
Norihiro NAKAOKA
7969b343b0 Raspberry Pi OS(Raspbian) scanning using OVAL DB (#1019)
* change: never refer to ChangeLog

* change raspberry pi os use debian oval at report

* change do not use r.Family

* change gost do not use r.Family

* change use r.Family because family has a large impact

* change replace MaineK00n/goval-dictionary@raspberrypi-oval

* note Raspbian Scan Policy

* add Raspbian Changelog support policy

* change grep Package for Raspbian at fast-scan mode

* add changelog preprocessing for Raspbian

* add take note of TODO

* change Changelog fetch part to function

* change error handling

* change solve one TODO

* change make ChangelogDir once

* add comment

* fix oval support Amazon Linux :refs #824

* change to useScannedCves from ovalSupproted

* change confidence for Raspbian

* change skip package for raspbian in OVAL DB

* change separate raspbian implementation from util

* change error, log format

* change print format

* change log format(delete newline)

* change support changelog.(Debian.)gz

* Revert "change support changelog.(Debian.)gz"

This reverts commit 2265a72c67.

* change test chnage.(Debian.)gz

* change support raspbian package(*raspberry*)

* change error format

* fix regexp pattern

* fix typo

* fix changelog cache

* change rename function name

* add TestParseChangelog

* change changelog lenient match for raspbian

* fix test case

* change clog dir support symbolic link, clog save dir name append suffix

* change remove more package for raspberry pi

* fix error handling

* change module update

* change refactoring around identifying raspbian package

* update go module

* update scan image

* update scan image

* change clarify scan mode

* change raspiPackNamePattern and add test case
2020-08-25 14:11:34 +09:00
Kota Kanbe
58cf1f4c8e refactor(typo): fix typos (#1041) 2020-08-24 16:34:32 +09:00
Norihiro NAKAOKA
a5b87af862 delete unnecessary images (#1036)
* delete unnecessary images

* Revert "delete unnecessary images"

This reverts commit 0967e1c522.

* delete unnecessary images
2020-08-21 17:07:20 +09:00
Kota Kanbe
a0e592b934 fix(report): fix segfault while uploading to s3 (#1033) 2020-08-07 10:31:43 +09:00
Kota Kanbe
7eccc538bb fix(msfdb): udpate go-msfdb-deps (#1032) 2020-08-06 16:54:14 +09:00
Kota Kanbe
59daa8570a fix(gost): suppress err logging when unsupported debian (#1031) 2020-08-05 20:05:50 +09:00
Kota Kanbe
3f52d318bc fix(log): suppress err msg if no access priv to logfile (#1029) 2020-07-31 16:55:12 +09:00
62 changed files with 1309 additions and 5824 deletions

View File

@@ -9,7 +9,7 @@
![Vuls-logo](img/vuls_logo.png)
Vulnerability scanner for Linux/FreeBSD, agentless, written in golang.
Vulnerability scanner for Linux/FreeBSD, agent-less, written in Go.
We have a slack team. [Join slack team](http://goo.gl/forms/xm5KFo35tu)
Twitter: [@vuls_en](https://twitter.com/vuls_en)
@@ -23,20 +23,6 @@ Twitter: [@vuls_en](https://twitter.com/vuls_en)
----
## NEWS
| Version | Main Feature | Date |
|:------------|:---------------------------------|:--------------------|
| [v0.8.0](https://github.com/future-architect/vuls/releases/tag/v0.8.0) | secret | Coming soon |
| [v0.7.0](https://github.com/future-architect/vuls/releases/tag/v0.7.0) | WordPress Vulnerability Scan | 2019/Apr/8 |
| [v0.6.3](https://github.com/future-architect/vuls/releases/tag/v0.6.3) | GitHub Integration | 2019/Feb/20 |
| [v0.6.2](https://github.com/future-architect/vuls/releases/tag/v0.6.2) | Add US-CERT/JPCERT Alerts as VulnSrc | 2019/Jan/23 |
| [v0.6.1](https://github.com/future-architect/vuls/releases/tag/v0.6.1) | BugFix | 2018/Nov/16 |
| [v0.6.0](https://github.com/future-architect/vuls/releases/tag/v0.6.0) | Add ExploitDB as VulnSrc | 2018/Nov/3 |
| [v0.5.0](https://github.com/future-architect/vuls/releases/tag/v0.5.0) | Scan accuracy improvement | 2018/Aug/27 |
----
## Abstract
For a system administrator, having to perform security vulnerability analysis and software update on a daily basis can be a burden.
@@ -66,36 +52,47 @@ Vuls is a tool created to solve the problems listed above. It has the following
- Alpine, Amazon Linux, CentOS, Debian, Oracle Linux, Raspbian, RHEL, SUSE Enterprise Linux, and Ubuntu
- FreeBSD
- Cloud, on-premise, Docker Container and Docker Image
- Cloud, on-premise, Running Docker Container
### High-quality scan
Vuls uses multiple vulnerability databases
- Vulnerability Database
- [NVD](https://nvd.nist.gov/)
- [JVN(Japanese)](http://jvndb.jvn.jp/apis/myjvn/)
- [NVD](https://nvd.nist.gov/)
- [JVN(Japanese)](http://jvndb.jvn.jp/apis/myjvn/)
- OVAL
- [Red Hat](https://www.redhat.com/security/data/oval/)
- [Debian](https://www.debian.org/security/oval/)
- [Oracle Linux](https://linux.oracle.com/security/oval/)
- [RedHat](https://www.redhat.com/security/data/oval/)
- [SUSE](http://ftp.suse.com/pub/projects/security/oval/)
- [Ubuntu](https://people.canonical.com/~ubuntu-security/oval/)
- [SUSE](http://ftp.suse.com/pub/projects/security/oval/)
- [Oracle Linux](https://linux.oracle.com/security/oval/)
- [Alpine-secdb](https://git.alpinelinux.org/cgit/alpine-secdb/)
- [Debian Security Bug Tracker](https://security-tracker.debian.org/tracker/)
- [Red Hat Security Advisories](https://access.redhat.com/security/security-updates/)
- Commands (yum, zypper, and pkg-audit)
- RHSA/ALAS/ELSA/FreeBSD-SA
- [Exploit Database](https://www.exploit-db.com/)
- [US-CERT](https://www.us-cert.gov/ncas/alerts)
- [JPCERT](http://www.jpcert.or.jp/at/2019.html)
- [WPVulnDB](https://wpvulndb.com/api)
- [Node.js Security Working Group](https://github.com/nodejs/security-wg)
- [Ruby Advisory Database](https://github.com/rubysec/ruby-advisory-db)
- [Safety DB(Python)](https://github.com/pyupio/safety-db)
- [PHP Security Advisories Database](https://github.com/FriendsOfPHP/security-advisories)
- [RustSec Advisory Database](https://github.com/RustSec/advisory-db)
- Changelog
- Security Advisory
- [Alpine-secdb](https://git.alpinelinux.org/cgit/alpine-secdb/)
- [Red Hat Security Advisories](https://access.redhat.com/security/security-updates/)
- [Debian Security Bug Tracker](https://security-tracker.debian.org/tracker/)
- Commands(yum, zypper, pkg-audit)
- RHSA / ALAS / ELSA / FreeBSD-SA
- Changelog
- PoC, Exploit
- [Exploit Database](https://www.exploit-db.com/)
- [Metasploit-Framework modules](https://www.rapid7.com/db/?q=&type=metasploit)
- CERT
- [US-CERT](https://www.us-cert.gov/ncas/alerts)
- [JPCERT](http://www.jpcert.or.jp/at/2019.html)
- Libraries
- [Node.js Security Working Group](https://github.com/nodejs/security-wg)
- [Ruby Advisory Database](https://github.com/rubysec/ruby-advisory-db)
- [Safety DB(Python)](https://github.com/pyupio/safety-db)
- [PHP Security Advisories Database](https://github.com/FriendsOfPHP/security-advisories)
- [RustSec Advisory Database](https://github.com/RustSec/advisory-db)
- WordPress
- [WPVulnDB](https://wpvulndb.com/api)
### Scan mode
@@ -134,19 +131,6 @@ Vuls uses multiple vulnerability databases
- It is possible to acquire the state of the server by connecting via SSH and executing the command.
- Vuls warns when the scan target server was updated the kernel etc. but not restarting it.
### **Static** Analysis
**Image scan function is no longer supported from Vuls v0.9.5. Use Trivy directry**
~~Vuls v0.8.0 can scan Docker images using [knqyf263/trivy](https://github.com/knqyf263/trivy).
Following Registry supported.~~
- ~~ECR~~
- ~~GCR~~
- ~~Local Image~~
~~For details, see [Scan docker image](https://vuls.io/docs/en/tutorial-scan-docker-image.html)~~
### Scan vulnerabilities of non-OS-packages
- Libraries of programming language
@@ -184,7 +168,7 @@ Vuls has some options to detect the vulnerabilities
## Document
For more information such as Installation, Tutorial, Usage, visit [vuls.io](https://vuls.io/)
For more information such as Installation, Tutorial, Usage, visit [vuls.io](https://vuls.io/)
[日本語翻訳ドキュメント](https://vuls.io/ja/)
----
@@ -195,12 +179,6 @@ kotakanbe ([@kotakanbe](https://twitter.com/kotakanbe)) created vuls and [these
----
## Change Log
Please see [CHANGELOG](https://github.com/future-architect/vuls/blob/master/CHANGELOG.md).
----
## Stargazers over time
[![Stargazers over time](https://starcharts.herokuapp.com/future-architect/vuls.svg)](https://starcharts.herokuapp.com/future-architect/vuls)

2
cache/bolt.go vendored
View File

@@ -141,7 +141,7 @@ func (b Bolt) PrettyPrint(meta Meta) error {
})
}
// GetChangelog get the changelgo of specified packName from the Bucket
// GetChangelog get the changelog of specified packName from the Bucket
func (b Bolt) GetChangelog(servername, packName string) (changelog string, err error) {
err = b.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket([]byte(servername))

View File

@@ -79,7 +79,6 @@ func (p *ConfigtestCmd) SetFlags(f *flag.FlagSet) {
// Execute execute
func (p *ConfigtestCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
// Setup Logger
util.Log = util.NewCustomLogger(c.ServerInfo{})
if err := mkdirDotVuls(); err != nil {

View File

@@ -17,7 +17,6 @@ import (
"github.com/future-architect/vuls/util"
"github.com/google/subcommands"
"github.com/k0kubun/pp"
cvelog "github.com/kotakanbe/go-cve-dictionary/log"
)
// ReportCmd is subcommand for reporting
@@ -212,8 +211,6 @@ func (p *ReportCmd) SetFlags(f *flag.FlagSet) {
// Execute execute
func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
util.Log = util.NewCustomLogger(c.ServerInfo{})
cvelog.SetLogger(c.Conf.LogDir, false, c.Conf.Debug, false)
if err := c.Load(p.configPath, ""); err != nil {
util.Log.Errorf("Error loading %s, %+v", p.configPath, err)
return subcommands.ExitUsageError

View File

@@ -49,6 +49,7 @@ func (*ScanCmd) Usage() string {
[-timeout=300]
[-timeout-scan=7200]
[-debug]
[-quiet]
[-pipe]
[-vvv]
[-ips]
@@ -61,6 +62,7 @@ func (*ScanCmd) Usage() string {
// SetFlags set flag
func (p *ScanCmd) SetFlags(f *flag.FlagSet) {
f.BoolVar(&c.Conf.Debug, "debug", false, "debug mode")
f.BoolVar(&c.Conf.Quiet, "quiet", false, "Quiet mode. No output on stdout")
wd, _ := os.Getwd()
defaultConfPath := filepath.Join(wd, "config.toml")

View File

@@ -19,7 +19,6 @@ import (
"github.com/future-architect/vuls/server"
"github.com/future-architect/vuls/util"
"github.com/google/subcommands"
cvelog "github.com/kotakanbe/go-cve-dictionary/log"
)
// ServerCmd is subcommand for server
@@ -142,8 +141,6 @@ func (p *ServerCmd) SetFlags(f *flag.FlagSet) {
// Execute execute
func (p *ServerCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
util.Log = util.NewCustomLogger(c.ServerInfo{})
cvelog.SetLogger(c.Conf.LogDir, false, c.Conf.Debug, false)
if p.configPath != "" {
if err := c.Load(p.configPath, ""); err != nil {
util.Log.Errorf("Error loading %s. err: %+v", p.configPath, err)

View File

@@ -16,7 +16,6 @@ import (
"github.com/future-architect/vuls/report"
"github.com/future-architect/vuls/util"
"github.com/google/subcommands"
cvelog "github.com/kotakanbe/go-cve-dictionary/log"
)
// TuiCmd is Subcommand of host discovery mode
@@ -144,17 +143,13 @@ func (p *TuiCmd) SetFlags(f *flag.FlagSet) {
// Execute execute
func (p *TuiCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
c.Conf.Lang = "en"
// Setup Logger
util.Log = util.NewCustomLogger(c.ServerInfo{})
cvelog.SetLogger(c.Conf.LogDir, false, c.Conf.Debug, false)
if err := c.Load(p.configPath, ""); err != nil {
util.Log.Errorf("Error loading %s, err: %+v", p.configPath, err)
return subcommands.ExitUsageError
}
c.Conf.Lang = "en"
c.Conf.CveDict.Overwrite(p.cveDict)
c.Conf.OvalDict.Overwrite(p.ovalDict)
c.Conf.Gost.Overwrite(p.gostConf)

View File

@@ -16,7 +16,7 @@ import (
)
// Version of Vuls
var Version = "0.9.9"
var Version = "`make build` or `make install` will show the version"
// Revision of Git
var Revision string
@@ -522,11 +522,11 @@ func (c *HipChatConf) Validate() (errs []error) {
return
}
if len(c.Room) == 0 {
errs = append(errs, xerrors.New("hipcaht.room must not be empty"))
errs = append(errs, xerrors.New("hipchat.room must not be empty"))
}
if len(c.AuthToken) == 0 {
errs = append(errs, xerrors.New("hipcaht.AuthToken must not be empty"))
errs = append(errs, xerrors.New("hipchat.AuthToken must not be empty"))
}
_, err := valid.ValidateStruct(c)
@@ -548,11 +548,11 @@ func (c *ChatWorkConf) Validate() (errs []error) {
return
}
if len(c.Room) == 0 {
errs = append(errs, xerrors.New("chatworkcaht.room must not be empty"))
errs = append(errs, xerrors.New("chatWorkConf.room must not be empty"))
}
if len(c.APIToken) == 0 {
errs = append(errs, xerrors.New("chatworkcaht.ApiToken must not be empty"))
errs = append(errs, xerrors.New("chatWorkConf.ApiToken must not be empty"))
}
_, err := valid.ValidateStruct(c)
@@ -1231,7 +1231,7 @@ const (
)
// GetServerName returns ServerName if this serverInfo is about host.
// If this serverInfo is abount a container, returns containerID@ServerName
// If this serverInfo is about a container, returns containerID@ServerName
func (s ServerInfo) GetServerName() string {
if len(s.Container.ContainerID) == 0 {
return s.ServerName
@@ -1250,21 +1250,18 @@ func (l Distro) String() string {
}
// MajorVersion returns Major version
func (l Distro) MajorVersion() (ver int, err error) {
func (l Distro) MajorVersion() (int, error) {
if l.Family == Amazon {
ss := strings.Fields(l.Release)
if len(ss) == 1 {
return 1, nil
}
ver, err = strconv.Atoi(ss[0])
return
return strconv.Atoi(ss[0])
}
if 0 < len(l.Release) {
ver, err = strconv.Atoi(strings.Split(l.Release, ".")[0])
} else {
err = xerrors.New("Release is empty")
return strconv.Atoi(strings.Split(l.Release, ".")[0])
}
return
return 0, xerrors.New("Release is empty")
}
// IsContainer returns whether this ServerInfo is about container

View File

@@ -63,7 +63,7 @@ func TestSyslogConfValidate(t *testing.T) {
}
}
func TestMajorVersion(t *testing.T) {
func TestDistro_MajorVersion(t *testing.T) {
var tests = []struct {
in Distro
out int

View File

@@ -116,7 +116,7 @@ func (c TOMLLoader) Load(pathToToml, keyPass string) error {
case "offline":
s.Mode.Set(Offline)
default:
return xerrors.Errorf("scanMode: %s of %s is invalie. Specify -fast, -fast-root, -deep or offline", m, serverName)
return xerrors.Errorf("scanMode: %s of %s is invalid. Specify -fast, -fast-root, -deep or offline", m, serverName)
}
}
if err := s.Mode.validate(); err != nil {
@@ -208,14 +208,14 @@ func (c TOMLLoader) Load(pathToToml, keyPass string) error {
for _, reg := range s.IgnorePkgsRegexp {
_, err := regexp.Compile(reg)
if err != nil {
return xerrors.Errorf("Faild to parse %s in %s. err: %w", reg, serverName, err)
return xerrors.Errorf("Failed to parse %s in %s. err: %w", reg, serverName, err)
}
}
for contName, cont := range s.Containers {
for _, reg := range cont.IgnorePkgsRegexp {
_, err := regexp.Compile(reg)
if err != nil {
return xerrors.Errorf("Faild to parse %s in %s@%s. err: %w",
return xerrors.Errorf("Failed to parse %s in %s@%s. err: %w",
reg, contName, serverName, err)
}
}
@@ -291,5 +291,5 @@ func toCpeURI(cpename string) (string, error) {
}
return naming.BindToURI(wfn), nil
}
return "", xerrors.Errorf("Unknow CPE format: %s", cpename)
return "", xerrors.Errorf("Unknown CPE format: %s", cpename)
}

View File

@@ -15,7 +15,7 @@ import (
"golang.org/x/oauth2"
)
// FillGitHubSecurityAlerts access to owner/repo on GitHub and fetch scurity alerts of the repository via GitHub API v4 GraphQL and then set to the given ScanResult.
// FillGitHubSecurityAlerts access to owner/repo on GitHub and fetch security alerts of the repository via GitHub API v4 GraphQL and then set to the given ScanResult.
// https://help.github.com/articles/about-security-alerts-for-vulnerable-dependencies/
func FillGitHubSecurityAlerts(r *models.ScanResult, owner, repo, token string) (nCVEs int, err error) {
src := oauth2.StaticTokenSource(

12
go.mod
View File

@@ -15,10 +15,12 @@ require (
github.com/aquasecurity/trivy v0.9.1
github.com/aquasecurity/trivy-db v0.0.0-20200616161554-cd5b3da29bc8
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
github.com/aws/aws-sdk-go v1.32.6
github.com/aws/aws-sdk-go v1.33.21
github.com/boltdb/bolt v1.3.1
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/d4l3k/messagediff v1.2.2-0.20190829033028-7e0a312ae40b
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21
github.com/emersion/go-smtp v0.13.0
github.com/google/subcommands v1.2.0
github.com/gosuri/uitable v0.0.4
github.com/hashicorp/go-uuid v1.0.2
@@ -31,14 +33,14 @@ require (
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d
github.com/knqyf263/go-rpm-version v0.0.0-20170716094938-74609b86c936
github.com/knqyf263/go-version v1.1.1
github.com/knqyf263/gost v0.1.3
github.com/knqyf263/gost v0.1.4
github.com/kotakanbe/go-cve-dictionary v0.5.0
github.com/kotakanbe/go-pingscanner v0.1.0
github.com/kotakanbe/goval-dictionary v0.2.8
github.com/kotakanbe/goval-dictionary v0.2.10
github.com/kotakanbe/logrus-prefixed-formatter v0.0.0-20180123152602-928f7356cb96
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
github.com/mitchellh/go-homedir v1.1.0
github.com/mozqnet/go-exploitdb v0.0.0-20200612044106-ea30f49f0902
github.com/mozqnet/go-exploitdb v0.1.0
github.com/nlopes/slack v0.6.0
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1 // indirect
github.com/olekukonko/tablewriter v0.0.4
@@ -47,7 +49,7 @@ require (
github.com/sirupsen/logrus v1.6.0
github.com/spf13/afero v1.3.0
github.com/spf13/cobra v1.0.0
github.com/takuzoo3868/go-msfdb v0.1.0
github.com/takuzoo3868/go-msfdb v0.1.1
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d

27
go.sum
View File

@@ -92,9 +92,10 @@ github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.19.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.27.1 h1:MXnqY6SlWySaZAqNnXThOvjRFdiiOuKtC6i7baFdNdU=
github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.32.6 h1:HoswAabUWgnrUF7X/9dr4WRgrr8DyscxXvTDm7Qw/5c=
github.com/aws/aws-sdk-go v1.32.6/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.33.21 h1:ziUemjajvLABlnJFe+8sM3fpqlg/DNA4944rUZ05PhY=
github.com/aws/aws-sdk-go v1.33.21/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
@@ -186,6 +187,10 @@ github.com/elazarl/goproxy v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:/Zj4wYkg
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 h1:dWB6v3RcOy03t/bUadywsbyrQwCqZeNIEX6M1OtSZOM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-smtp v0.13.0 h1:aC3Kc21TdfvXnuJXCQXuhnDXUldhc12qME/S7Y3Y94g=
github.com/emersion/go-smtp v0.13.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emirpasic/gods v1.9.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
@@ -382,6 +387,7 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
@@ -416,8 +422,8 @@ github.com/knqyf263/go-rpm-version v0.0.0-20170716094938-74609b86c936/go.mod h1:
github.com/knqyf263/go-rpmdb v0.0.0-20190501070121-10a1c42a10dc/go.mod h1:MrSSvdMpTSymaQWk1yFr9sxFSyQmKMj6jkbvGrchBV8=
github.com/knqyf263/go-version v1.1.1 h1:+MpcBC9b7rk5ihag8Y/FLG8get1H2GjniwKQ+9DxI2o=
github.com/knqyf263/go-version v1.1.1/go.mod h1:0tBvHvOBSf5TqGNcY+/ih9o8qo3R16iZCpB9rP0D3VM=
github.com/knqyf263/gost v0.1.3 h1:jr0H56Vfvf23X319TGmIacpgR7PwmW8q5pjo4xLhOFY=
github.com/knqyf263/gost v0.1.3/go.mod h1:okRxldLs7RVZEjNVBOQEqKj93OU91TmULMnHWU6gJ1s=
github.com/knqyf263/gost v0.1.4 h1:X6HxOUozp/eSSzyLHb/C8/gkzWtRPHcJ8sLbKJ5mXu0=
github.com/knqyf263/gost v0.1.4/go.mod h1:okRxldLs7RVZEjNVBOQEqKj93OU91TmULMnHWU6gJ1s=
github.com/knqyf263/nested v0.0.1/go.mod h1:zwhsIhMkBg90DTOJQvxPkKIypEHPYkgWHs4gybdlUmk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -427,8 +433,8 @@ github.com/kotakanbe/go-cve-dictionary v0.5.0 h1:wai3ymaI0BFhcofW7ITOAAILm4CvsBn
github.com/kotakanbe/go-cve-dictionary v0.5.0/go.mod h1:zgnFBROvdhyd30KU0yekNI0J1kQkjTMND8GqlL8y25k=
github.com/kotakanbe/go-pingscanner v0.1.0 h1:VG4/9l0i8WeToXclj7bIGoAZAu7a07Z3qmQiIfU0gT0=
github.com/kotakanbe/go-pingscanner v0.1.0/go.mod h1:/761QZzuZFcfN8h/1QuawUA+pKukp3qcNj5mxJCOiAk=
github.com/kotakanbe/goval-dictionary v0.2.8 h1:C2hAEA3HdsaJbSoWjyZjZFeBjBoF/CVLmZJxSrcpAkM=
github.com/kotakanbe/goval-dictionary v0.2.8/go.mod h1:OozI5ZbKWHIPcjYgOITYHRy+Vo6ZbksY1FU8aCwojK4=
github.com/kotakanbe/goval-dictionary v0.2.10 h1:ilzsGCwe74b+OsajFO+VbOW9IUxu5i3dYNWdl+8JZrw=
github.com/kotakanbe/goval-dictionary v0.2.10/go.mod h1:OozI5ZbKWHIPcjYgOITYHRy+Vo6ZbksY1FU8aCwojK4=
github.com/kotakanbe/logrus-prefixed-formatter v0.0.0-20180123152602-928f7356cb96 h1:xNVK0mQJdQjw+QYeaMM4G6fvucWr8rTGGIhlPakx1wU=
github.com/kotakanbe/logrus-prefixed-formatter v0.0.0-20180123152602-928f7356cb96/go.mod h1:ljq48H1V+0Vh0u7ucA3LjR4AfkAeCpxrf7LaaCk8Vmo=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
@@ -442,6 +448,7 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/gommon v0.2.9/go.mod h1:E8ZTmW9vw5az5/ZyHWCp0Lw4OH2ecsaBP1C/NKavGG4=
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
@@ -512,8 +519,8 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
github.com/mozqnet/go-exploitdb v0.0.0-20200612044106-ea30f49f0902 h1:JXh+QEZqWJ5SIWdm8WsztZqvaeLubj9IZ/vvir0jMEY=
github.com/mozqnet/go-exploitdb v0.0.0-20200612044106-ea30f49f0902/go.mod h1:TsEciLihBvN8yO9iCHBahCLxZff11NxbBO/xm8nVH9g=
github.com/mozqnet/go-exploitdb v0.1.0 h1:pZDwJQEn3TFsaH+N1B6pBoCmK95XKzCve63sZjXkGCY=
github.com/mozqnet/go-exploitdb v0.1.0/go.mod h1:8mbqC/rcubAo8AEQ2zwR90IkhsltyQg70zllgmvEpAw=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -669,8 +676,8 @@ github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/takuzoo3868/go-msfdb v0.1.0 h1:v1pdFGuBXQ0yWPk1vfL4Ln2JwGfKE8FwaPCz1wIy4uY=
github.com/takuzoo3868/go-msfdb v0.1.0/go.mod h1:QnJq9bY6PHQN5DUT793Sr9HxL5WnHkHw6GI+qpI2dPM=
github.com/takuzoo3868/go-msfdb v0.1.1 h1:eaVDXmiKRAe8xSAVagybUdLJE3pLjerXYJIuYazVWHE=
github.com/takuzoo3868/go-msfdb v0.1.1/go.mod h1:QnJq9bY6PHQN5DUT793Sr9HxL5WnHkHw6GI+qpI2dPM=
github.com/tealeg/xlsx v1.0.3/go.mod h1:uxu5UY2ovkuRPWKQ8Q7JG0JbSivrISjdPzZQKeo74mA=
github.com/testcontainers/testcontainers-go v0.3.1/go.mod h1:br7bkzIukhPSIjy07Ma3OuXjjFvl2jm7CDU0LQNsqLw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=

View File

@@ -21,8 +21,23 @@ type packCves struct {
cves []models.CveContent
}
func (deb Debian) Supported(major string) bool {
_, ok := map[string]string{
"8": "jessie",
"9": "stretch",
"10": "buster",
}[major]
return ok
}
// DetectUnfixed fills cve information that has in Gost
func (deb Debian) DetectUnfixed(driver db.DB, r *models.ScanResult, _ bool) (nCVEs int, err error) {
if !deb.Supported(major(r.Release)) {
// only logging
util.Log.Warnf("Debian %s is not supported yet", r.Release)
return 0, nil
}
linuxImage := "linux-image-" + r.RunningKernel.Release
// Add linux and set the version of running kernel to search OVAL.
if r.Container.ContainerID == "" {
@@ -37,9 +52,17 @@ func (deb Debian) DetectUnfixed(driver db.DB, r *models.ScanResult, _ bool) (nCV
}
}
// Debian Security Tracker does not support Package for Raspbian, so skip it.
var scanResult models.ScanResult
if r.Family != config.Raspbian {
scanResult = *r
} else {
scanResult = r.RemoveRaspbianPackFromResult()
}
packCvesList := []packCves{}
if config.Conf.Gost.IsFetchViaHTTP() {
url, _ := util.URLPathJoin(config.Conf.Gost.URL, "debian", major(r.Release), "pkgs")
url, _ := util.URLPathJoin(config.Conf.Gost.URL, "debian", major(scanResult.Release), "pkgs")
responses, err := getAllUnfixedCvesViaHTTP(r, url)
if err != nil {
return 0, err
@@ -64,8 +87,8 @@ func (deb Debian) DetectUnfixed(driver db.DB, r *models.ScanResult, _ bool) (nCV
if driver == nil {
return 0, nil
}
for _, pack := range r.Packages {
cveDebs := driver.GetUnfixedCvesDebian(major(r.Release), pack.Name)
for _, pack := range scanResult.Packages {
cveDebs := driver.GetUnfixedCvesDebian(major(scanResult.Release), pack.Name)
cves := []models.CveContent{}
for _, cveDeb := range cveDebs {
cves = append(cves, *deb.ConvertToModel(&cveDeb))
@@ -78,8 +101,8 @@ func (deb Debian) DetectUnfixed(driver db.DB, r *models.ScanResult, _ bool) (nCV
}
// SrcPack
for _, pack := range r.SrcPackages {
cveDebs := driver.GetUnfixedCvesDebian(major(r.Release), pack.Name)
for _, pack := range scanResult.SrcPackages {
cveDebs := driver.GetUnfixedCvesDebian(major(scanResult.Release), pack.Name)
cves := []models.CveContent{}
for _, cveDeb := range cveDebs {
cves = append(cves, *deb.ConvertToModel(&cveDeb))

61
gost/debian_test.go Normal file
View File

@@ -0,0 +1,61 @@
package gost
import "testing"
func TestDebian_Supported(t *testing.T) {
type fields struct {
Base Base
}
type args struct {
major string
}
tests := []struct {
name string
args args
want bool
}{
{
name: "8 is supported",
args: args{
major: "8",
},
want: true,
},
{
name: "9 is supported",
args: args{
major: "9",
},
want: true,
},
{
name: "10 is supported",
args: args{
major: "10",
},
want: true,
},
{
name: "11 is not supported yet",
args: args{
major: "11",
},
want: false,
},
{
name: "empty string is not supported yet",
args: args{
major: "",
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
deb := Debian{}
if got := deb.Supported(tt.args.major); got != tt.want {
t.Errorf("Debian.Supported() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -23,7 +23,7 @@ func NewClient(family string) Client {
switch family {
case cnf.RedHat, cnf.CentOS:
return RedHat{}
case cnf.Debian:
case cnf.Debian, cnf.Raspbian:
return Debian{}
case cnf.Windows:
return Microsoft{}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 247 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -1,414 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.17-->
<key attr.name="Description" attr.type="string" for="graph" id="d0"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key for="graphml" id="d7" yfiles.type="resources"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d0"/>
<node id="n0">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="56.0" width="268.0" x="309.6849206349206" y="0.0"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="83.482421875" x="92.2587890625" y="18.93359375">Detect the OS<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="0.1619001116071429" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n1">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.decision">
<y:Geometry height="40.0" width="80.0" x="403.6849206349206" y="206.44247787610618"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="4.0" x="38.0" y="18.0">
<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n2">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="90.44247787610618" width="268.0" x="309.6849206349206" y="86.0"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="right" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="88.796875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="170.763671875" x="48.61816406250006" y="0.8228014380530908">Get installed packages
Alpine: apk
Debian/Ubuntu: dpkg-query
Amazon/RHEL/CentOS: rpm
SUSE: zypper
FreeBSD: pkg<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="2.220446049250313E-16" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n3">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="56.0" width="268.0" x="609.3698412698412" y="630.0546766682629"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="152.634765625" x="57.6826171875" y="18.93359375">Write results to JSON files<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="0.1619001116071429" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n4">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="56.0" width="268.0" x="609.3698412698412" y="287.8409153761062"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="46.3984375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="232.744140625" x="17.6279296875" y="4.80078125">Get CVE IDs by using package manager
Amazon: yum plugin security
FreeBSD: pkg audit<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n5">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="56.0" width="268.0" x="609.3698412698412" y="750.4705298628534"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="42.595703125" x="112.7021484375" y="18.93359375">Report<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n6" yfiles.foldertype="group">
<data key="d4"/>
<data key="d6">
<y:ProxyAutoBoundsNode>
<y:Realizers active="0">
<y:GroupNode>
<y:Geometry height="116.89483989807195" width="333.6788874841973" x="234.29467728596296" y="709.1901021013174"/>
<y:Fill color="#F5F5F5" transparent="false"/>
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.666015625" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="333.6788874841973" x="0.0" y="0.0">Vulnerability Database</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
<y:GroupNode>
<y:Geometry height="50.0" width="50.0" x="0.0" y="60.0"/>
<y:Fill color="#F5F5F5" transparent="false"/>
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.666015625" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="63.75830078125" x="-6.879150390625" y="0.0">Folder 1</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="true" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
</y:Realizers>
</y:ProxyAutoBoundsNode>
</data>
<graph edgedefault="directed" id="n6:">
<node id="n6::n0">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.dataBase">
<y:Geometry height="65.22882427307195" width="136.83944374209864" x="416.1341210280616" y="745.8561177263174"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="117.970703125" x="9.434370308549205" y="23.548005886535975">CVE DB (NVD / JVN)<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="-8.326672684688674E-16" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n6::n1">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.dataBase">
<y:Geometry height="65.22882427307195" width="136.83944374209864" x="249.29467728596296" y="745.8561177263174"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="55.533203125" x="40.653120308549205" y="23.548005886535975">OVAL DB<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="-8.326672684688674E-16" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
</graph>
</node>
<node id="n7">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="56.0" width="268.0" x="27.144753476611868" y="287.8409153761062"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="260.83984375" x="3.580078125" y="11.8671875">Check upgradable packages
Debian/Ubuntu: apt-get upgrade --dry-run<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n8">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.loopLimit">
<y:Geometry height="51.10998735777497" width="137.19216182048035" x="92.54867256637169" y="376.28592169721867"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="131.751953125" x="2.7201043477401754" y="9.422181178887513">foreach
upgradable packages<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="5.551115123125783E-16" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n9">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="56.0" width="268.0" x="27.144753476611868" y="459.8409153761062"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="213.619140625" x="27.1904296875" y="11.8671875">Parse changelog and get CVE IDs
Debian/Ubuntu: aptitude changelog<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n10">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.loopLimitEnd">
<y:Geometry height="50.0" width="137.0" x="92.64475347661187" y="545.8409153761062"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="55.24609375" x="40.876953125" y="15.93359375">end loop<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<edge id="e0" source="n2" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="45.22123893805309" tx="0.0" ty="-20.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n1" target="n4">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="40.0" sy="0.0" tx="0.0" ty="-28.0">
<y:Point x="743.3698412698412" y="226.44247787610618"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="right" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="51.806640625" x="183.35883739927397" y="2.000003510871693">Amazon
FreeBSD<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="1.9999999999998863" distanceToCenter="false" position="right" ratio="0.7796030035582084" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n0" target="n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="28.0" tx="0.0" ty="-45.22123893805309"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n5" target="n6">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="10.8330078125"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n1" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="-123.36984126984123" ty="0.0">
<y:Point x="443.6849206349206" y="658.0546766682629"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="right" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="102.9296875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="77.078125" x="-97.68364242524859" y="5.005267793098369">Alpine Linux
CentOS
RHEL
Ubuntu
Debian
Oracle Linux
Suse<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="59.14459455430983" distanceToCenter="true" position="right" ratio="0.0" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e5" source="n4" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e6" source="n7" target="n8">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="28.0" tx="0.0" ty="-25.554993678887485"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e7" source="n8" target="n9">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="25.554993678887485" tx="0.0" ty="-28.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e8" source="n9" target="n10">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="28.0" tx="0.0" ty="-25.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e9" source="n3" target="n5">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e10" source="n1" target="n7">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="161.14475347661187" y="226.44247787610618"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="56.98046875" x="-196.80057112212188" y="20.933597260871807">Raspbian<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="left" ratio="0.6447921222409765" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e11" source="n10" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="-125.78842258255952" ty="0.0">
<y:Point x="161.14475347661187" y="658.0546766682629"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d7">
<y:Resources/>
</data>
</graphml>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

View File

@@ -1,515 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.17-->
<key attr.name="Description" attr.type="string" for="graph" id="d0"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key for="graphml" id="d7" yfiles.type="resources"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d0"/>
<node id="n0">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="56.0" width="268.0" x="309.6849206349206" y="0.0"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="83.482421875" x="92.2587890625" y="18.93359375">Detect the OS<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="0.1619001116071429" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n1">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.decision">
<y:Geometry height="40.0" width="80.0" x="403.6849206349206" y="206.44247787610618"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="4.0" x="38.0" y="18.0">
<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n2">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="90.44247787610618" width="268.0" x="309.6849206349206" y="86.0"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="right" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="88.796875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="170.763671875" x="48.61816406250006" y="0.8228014380530908">Get installed packages
Alpine Linux: apk
Debian/Ubuntu: dpkg-query
Amazon/RHEL/CentOS: rpm
FreeBSD: pkg
SUSE: zypper<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="2.220446049250313E-16" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n3">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="56.0" width="268.0" x="10.0" y="287.8409153761062"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="260.83984375" x="3.580078125" y="11.8671875">Check upgradable packages
Debian/Ubuntu: apt-get upgrade --dry-run<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n4">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.loopLimit">
<y:Geometry height="51.10998735777497" width="137.19216182048035" x="75.40391908975982" y="376.28592169721867"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="131.751953125" x="2.7201043477401754" y="9.422181178887513">foreach
upgradable packages<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="5.551115123125783E-16" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n5">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="56.0" width="268.0" x="10.0" y="459.8409153761062"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="213.619140625" x="27.1904296875" y="11.8671875">Parse changelog and get CVE IDs
Debian/Ubuntu: aptitude changelog<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n6">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.loopLimitEnd">
<y:Geometry height="50.0" width="137.0" x="75.5" y="545.8409153761062"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="55.24609375" x="40.876953125" y="15.93359375">end loop<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n7">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="56.0" width="268.0" x="609.3698412698412" y="625.8409153761062"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="152.634765625" x="57.6826171875" y="18.93359375">Write results to JSON files<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="0.1619001116071429" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n8">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="56.0" width="268.0" x="609.3698412698412" y="287.8409153761062"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="46.3984375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="232.744140625" x="17.6279296875" y="4.80078125">Get CVE IDs by using package manager
Amazon/RHEL: yum plugin security
FreeBSD: pkg audit<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n9">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="56.0" width="268.0" x="609.3698412698412" y="716.4553275126422"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="42.595703125" x="112.7021484375" y="18.93359375">Report<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n10">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="56.0" width="268.0" x="309.6849206349206" y="371.39590905499364"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="293.06640625" x="-12.533203124999943" y="11.8671875">Get all changelogs of updatable packages at once
yum changelog<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="2.220446049250313E-16" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n11">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="56.0" width="268.0" x="309.68492063492056" y="459.8409153761062"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="205.52734375" x="31.236328125000057" y="18.93359375">Parse changelogs and get CVE IDs <y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="2.220446049250313E-16" nodeRatioY="0.1619001116071429" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n12">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.process">
<y:Geometry height="56.0" width="268.0" x="609.3698412698412" y="373.8409153761062"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="293.06640625" x="-12.533203124999886" y="11.8671875">Get all changelogs of updatable packages at once
Amazon / RHEL: yum changelog<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="2.220446049250313E-16" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n13" yfiles.foldertype="group">
<data key="d4"/>
<data key="d6">
<y:ProxyAutoBoundsNode>
<y:Realizers active="0">
<y:GroupNode>
<y:Geometry height="116.89483989807195" width="333.6788874841973" x="229.74083438685204" y="675.1748997511062"/>
<y:Fill color="#F5F5F5" transparent="false"/>
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.666015625" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="333.6788874841973" x="0.0" y="0.0">Vulnerability Database</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
<y:GroupNode>
<y:Geometry height="50.0" width="50.0" x="0.0" y="60.0"/>
<y:Fill color="#F5F5F5" transparent="false"/>
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.666015625" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="63.75830078125" x="-6.879150390625" y="0.0">Folder 1</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="true" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
</y:Realizers>
</y:ProxyAutoBoundsNode>
</data>
<graph edgedefault="directed" id="n13:">
<node id="n13::n0">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.dataBase">
<y:Geometry height="65.22882427307195" width="136.83944374209864" x="411.5802781289507" y="711.8409153761062"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="117.970703125" x="9.434370308549205" y="23.548005886535975">CVE DB (NVD / JVN)<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="-8.326672684688674E-16" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n13::n1">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.dataBase">
<y:Geometry height="65.22882427307195" width="136.83944374209864" x="244.74083438685204" y="711.8409153761062"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="55.533203125" x="40.653120308549205" y="23.548005886535975">OVAL DB<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="-8.326672684688674E-16" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
</y:GenericNode>
</data>
</node>
</graph>
</node>
<edge id="e0" source="n2" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="45.22123893805309" tx="0.0" ty="-20.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n1" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="-40.0" sy="0.0" tx="0.0" ty="-28.0">
<y:Point x="144.0" y="226.44247787610618"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="right" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="46.3984375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="56.98046875" x="-257.65322875976574" y="2.0000035108718635">Debian
Ubuntu
Raspbian<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="1.9999999999998863" distanceToCenter="false" position="left" ratio="0.8652035780364729" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n3" target="n4">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="28.0" tx="0.0" ty="-25.554993678887485"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n4" target="n5">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="25.554993678887485" tx="0.0" ty="-28.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n5" target="n6">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="28.0" tx="0.0" ty="-25.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e5" source="n6" target="n7">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="68.5" sy="0.0" tx="0.0" ty="-28.0">
<y:Point x="743.3698412698412" y="570.8409153761062"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e6" source="n1" target="n8">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="40.0" sy="0.0" tx="0.0" ty="-28.0">
<y:Point x="743.3698412698412" y="226.44247787610618"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="right" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="46.3984375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="51.806640625" x="200.87829463898197" y="4.000003510871693">Amazon
RHEL
FreeBSD<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="6.999999999999886" distanceToCenter="false" position="right" ratio="0.8192728556300707" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e7" source="n0" target="n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="28.0" tx="0.0" ty="-45.22123893805309"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e8" source="n7" target="n9">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="28.0" tx="0.0" ty="-28.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e9" source="n1" target="n10">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="20.0" tx="0.0" ty="-28.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="46.708984375" x="-53.35447755843876" y="5.000003510871807">CentOS<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.0" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e10" source="n10" target="n11">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="28.0" tx="0.0" ty="-28.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e11" source="n11" target="n7">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="-24.34091537610618">
<y:Point x="743.3698412698412" y="487.8409153761062"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e12" source="n8" target="n12">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e13" source="n12" target="n7">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e14" source="n9" target="n13">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="10.8330078125"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e15" source="n1" target="n7">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="999.0" y="226.44247787610618"/>
<y:Point x="999.0" y="570.8409153761062"/>
<y:Point x="743.3698412698412" y="570.8409153761062"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="none"/>
<y:EdgeLabel alignment="right" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="76.8203125" x="422.923942251054" y="13.867191010871807">Alpine Linux
SUSE<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.8856709076027529" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d7">
<y:Resources/>
</data>
</graphml>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 KiB

View File

@@ -1,265 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.14.2-->
<key attr.name="Description" attr.type="string" for="graph" id="d0"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key for="graphml" id="d7" yfiles.type="resources"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d0"/>
<node id="n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="50.0" width="73.25" x="478.6165008544913" y="1358.206868489578"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="28.87890625" x="22.185546875" y="15.93359375">Vuls<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="50.0" width="73.25" x="711.9623756408686" y="1043.7241210937468"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="38.623046875" x="17.3134765625" y="15.93359375">Nginx<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n2">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="50.0" width="73.25" x="711.9623756408686" y="1287.206868489578"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="42.7890625" x="15.23046875" y="15.93359375">MySQL<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n3" yfiles.foldertype="group">
<data key="d4"/>
<data key="d6">
<y:ProxyAutoBoundsNode>
<y:Realizers active="0">
<y:GroupNode>
<y:Geometry height="101.666015625" width="291.7208747863772" x="602.72693824768" y="1146.2994791666624"/>
<y:Fill color="#F5F5F5" transparent="false"/>
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.666015625" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="291.7208747863772" x="0.0" y="0.0">Web/App</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="23" leftF="23.0" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
<y:GroupNode>
<y:Geometry height="50.0" width="50.0" x="0.0" y="60.0"/>
<y:Fill color="#F5F5F5" transparent="false"/>
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.666015625" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="63.75830078125" x="-6.879150390625" y="0.0">Folder 5</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="true" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
</y:Realizers>
</y:ProxyAutoBoundsNode>
</data>
<graph edgedefault="directed" id="n3:">
<node id="n3::n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="50.0" width="73.25" x="640.72693824768" y="1182.9654947916624"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="31.26953125" x="20.990234375" y="15.93359375">Rails<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n3::n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="50.0" width="73.25" x="723.4623756408686" y="1182.9654947916624"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="31.26953125" x="20.990234375" y="15.93359375">Rails<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n3::n2">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="50.0" width="73.25" x="806.1978130340572" y="1182.9654947916624"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="31.26953125" x="20.990234375" y="15.93359375">Rails<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
</graph>
</node>
<node id="n4">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="50.0" width="73.25" x="821.1978130340572" y="1287.206868489578"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="35.412109375" x="18.9189453125" y="15.93359375">Redis<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<edge id="e0" source="n3" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n3" target="n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n0" target="n3::n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n0" target="n3::n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n0" target="n3::n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e5" source="n3" target="n4">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e6" source="n0" target="n4">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e7" source="n0" target="n1">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e8" source="n0" target="n2">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d7">
<y:Resources/>
</data>
</graphml>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -1,194 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.14.2-->
<key attr.name="Description" attr.type="string" for="graph" id="d0"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key for="graphml" id="d7" yfiles.type="resources"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d0"/>
<node id="n0">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="50.0" width="73.25" x="508.30825042724564" y="1132.4827473958312"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="28.87890625" x="22.185546875" y="15.93359375">Vuls<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n1">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="50.0" width="73.25" x="749.6541252136229" y="993.2413736979156"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="23.8046875" x="24.72265625" y="15.93359375">ELB<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n2">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="50.0" width="73.25" x="749.6541252136229" y="1236.7241210937468"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="27.0390625" x="23.10546875" y="15.93359375">RDS<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n3" yfiles.foldertype="group">
<data key="d4"/>
<data key="d5"/>
<data key="d6">
<y:ProxyAutoBoundsNode>
<y:Realizers active="0">
<y:GroupNode>
<y:Geometry height="101.666015625" width="291.7208747863772" x="640.4186878204343" y="1095.8167317708312"/>
<y:Fill color="#F5F5F5" transparent="false"/>
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.666015625" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="291.7208747863772" x="0.0" y="0.0">Web/App</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="23" leftF="23.0" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
<y:GroupNode>
<y:Geometry height="50.0" width="50.0" x="0.0" y="60.0"/>
<y:Fill color="#F5F5F5" transparent="false"/>
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.666015625" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="63.75830078125" x="-6.879150390625" y="0.0">Folder 5</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="true" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
</y:Realizers>
</y:ProxyAutoBoundsNode>
</data>
<graph edgedefault="directed" id="n3:">
<node id="n3::n0">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="50.0" width="73.25" x="678.4186878204343" y="1132.4827473958312"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="31.26953125" x="20.990234375" y="15.93359375">Rails<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n3::n1">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="50.0" width="73.25" x="761.1541252136229" y="1132.4827473958312"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="31.26953125" x="20.990234375" y="15.93359375">Rails<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n3::n2">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="50.0" width="73.25" x="843.8895626068115" y="1132.4827473958312"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="31.26953125" x="20.990234375" y="15.93359375">Rails<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
</graph>
</node>
<edge id="e0" source="n3" target="n1">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n3" target="n2">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n0" target="n3::n0">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d7">
<y:Resources/>
</data>
</graphml>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -17,7 +17,7 @@ import (
"github.com/future-architect/vuls/util"
)
// FillLibrary fills LibraryScanner informations
// FillLibrary fills LibraryScanner information
func FillLibrary(r *models.ScanResult) (totalCnt int, err error) {
if len(r.LibraryScanners) == 0 {
return

View File

@@ -256,7 +256,7 @@ const (
// RedHatAPI is RedHat
RedHatAPI CveContentType = "redhat_api"
// DebianSecurityTracker is Debian Secury tracker
// DebianSecurityTracker is Debian Security tracker
DebianSecurityTracker CveContentType = "debian_security_tracker"
// Debian is Debian

View File

@@ -42,7 +42,7 @@ type LibraryScanner struct {
func (s LibraryScanner) Scan() ([]VulnInfo, error) {
scanner, err := library.DriverFactory{}.NewDriver(filepath.Base(string(s.Path)))
if err != nil {
return nil, xerrors.Errorf("Faild to new a library driver: %w", err)
return nil, xerrors.Errorf("Failed to new a library driver: %w", err)
}
var vulnerabilities = []VulnInfo{}
for _, pkg := range s.Libs {
@@ -71,7 +71,7 @@ func (s LibraryScanner) convertFanalToVuln(tvulns []types.DetectedVulnerability)
for _, tvuln := range tvulns {
vinfo, err := s.getVulnDetail(tvuln)
if err != nil {
util.Log.Debugf("failed to getVulnDetail. err: %s, tvun: %#v", err, tvuln)
util.Log.Debugf("failed to getVulnDetail. err: %s, tvuln: %#v", err, tvuln)
continue
}
vulns = append(vulns, vinfo)

View File

@@ -3,6 +3,7 @@ package models
import (
"bytes"
"fmt"
"regexp"
"strings"
"golang.org/x/xerrors"
@@ -173,9 +174,29 @@ type Changelog struct {
// AffectedProcess keep a processes information affected by software update
type AffectedProcess struct {
PID string `json:"pid,omitempty"`
Name string `json:"name,omitempty"`
ListenPorts []string `json:"listenPorts,omitempty"`
PID string `json:"pid,omitempty"`
Name string `json:"name,omitempty"`
ListenPorts []ListenPort `json:"listenPorts,omitempty"`
}
// ListenPort has the result of parsing the port information to the address and port.
type ListenPort struct {
Address string `json:"address"`
Port string `json:"port"`
PortScanSuccessOn []string `json:"portScanSuccessOn"`
}
// HasPortScanSuccessOn checks if Package.AffectedProcs has PortScanSuccessOn
func (p Package) HasPortScanSuccessOn() bool {
for _, ap := range p.AffectedProcs {
for _, lp := range ap.ListenPorts {
if len(lp.PortScanSuccessOn) > 0 {
return true
}
}
}
return false
}
// NeedRestartProcess keep a processes information affected by software update
@@ -227,3 +248,28 @@ func (s SrcPackages) FindByBinName(name string) (*SrcPackage, bool) {
}
return nil, false
}
// raspiPackNamePattern is a regular expression pattern to detect the Raspberry Pi specific package from the package name.
// e.g. libraspberrypi-dev, rpi-eeprom, python3-rpi.gpio, pi-bluetooth
var raspiPackNamePattern = regexp.MustCompile(`(.*raspberry.*|^rpi.*|.*-rpi.*|^pi-.*)`)
// raspiPackNamePattern is a regular expression pattern to detect the Raspberry Pi specific package from the version.
// e.g. ffmpeg 7:4.1.4-1+rpt7~deb10u1, vlc 3.0.10-0+deb10u1+rpt2
var raspiPackVersionPattern = regexp.MustCompile(`.+\+rp(t|i)\d+`)
// raspiPackNameList is a package name array of Raspberry Pi specific packages that are difficult to detect with regular expressions.
var raspiPackNameList = []string{"piclone", "pipanel", "pishutdown", "piwiz", "pixflat-icons"}
// IsRaspbianPackage judges whether it is a package related to Raspberry Pi from the package name and version
func IsRaspbianPackage(name, version string) bool {
if raspiPackNamePattern.MatchString(name) || raspiPackVersionPattern.MatchString(version) {
return true
}
for _, n := range raspiPackNameList {
if n == name {
return true
}
}
return false
}

View File

@@ -297,3 +297,87 @@ func TestPackage_FormatVersionFromTo(t *testing.T) {
})
}
}
func Test_IsRaspbianPackage(t *testing.T) {
type args struct {
name string
ver string
}
tests := []struct {
name string
in []args
expect []bool
}{
{
name: "nameRegExp",
in: []args{
{
name: "libraspberrypi-dev",
ver: "1.20200811-1",
},
{
name: "rpi-eeprom",
ver: "7.10-1",
},
{
name: "python3-rpi.gpio",
ver: "0.7.0-0.1~bpo10+1",
},
{
name: "arping",
ver: "2.19-6",
},
{
name: "pi-bluetooth",
ver: "0.1.14",
},
},
expect: []bool{true, true, true, false, true, false},
},
{
name: "verRegExp",
in: []args{
{
name: "ffmpeg",
ver: "7:4.1.6-1~deb10u1+rpt1",
},
{
name: "gcc",
ver: "4:8.3.0-1+rpi2",
},
},
expect: []bool{true, true},
},
{
name: "nameList",
in: []args{
{
name: "piclone",
ver: "0.16",
},
},
expect: []bool{true},
},
{
name: "debianPackage",
in: []args{
{
name: "apt",
ver: "1.8.2.1",
},
},
expect: []bool{false},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
for i, p := range tt.in {
ret := IsRaspbianPackage(p.name, p.ver)
if !reflect.DeepEqual(ret, tt.expect[i]) {
t.Errorf("[%s->%s] expected: %t, actual: %t, in: %#v", tt.name, tt.in[i].name, tt.expect[i], ret, tt.in[i])
}
}
})
}
}

View File

@@ -216,7 +216,7 @@ func (r ScanResult) FilterIgnorePkgs() ScanResult {
for _, pkgRegexp := range ignorePkgsRegexps {
re, err := regexp.Compile(pkgRegexp)
if err != nil {
util.Log.Errorf("Faild to parse %s. err: %+v", pkgRegexp, err)
util.Log.Errorf("Failed to parse %s. err: %+v", pkgRegexp, err)
continue
} else {
regexps = append(regexps, re)
@@ -339,8 +339,8 @@ func (r ScanResult) FormatServerName() (name string) {
return
}
// FormatTextReportHeadedr returns header of text report
func (r ScanResult) FormatTextReportHeadedr() string {
// FormatTextReportHeader returns header of text report
func (r ScanResult) FormatTextReportHeader() string {
var buf bytes.Buffer
for i := 0; i < len(r.ServerInfo()); i++ {
buf.WriteString("=")
@@ -400,7 +400,7 @@ func (r ScanResult) FormatMetasploitCveSummary() string {
return fmt.Sprintf("%d modules", nMetasploitCve)
}
// FormatAlertSummary returns a summary of XCERT alerts
// FormatAlertSummary returns a summary of CERT alerts
func (r ScanResult) FormatAlertSummary() string {
jaCnt := 0
enCnt := 0
@@ -416,6 +416,10 @@ func (r ScanResult) FormatAlertSummary() string {
}
func (r ScanResult) isDisplayUpdatableNum() bool {
if r.Family == config.FreeBSD {
return false
}
var mode config.ScanMode
s, _ := config.Conf.Servers[r.ServerName]
mode = s.Mode
@@ -472,3 +476,30 @@ type Platform struct {
Name string `json:"name"` // aws or azure or gcp or other...
InstanceID string `json:"instanceID"`
}
// RemoveRaspbianPackFromResult is for Raspberry Pi and removes the Raspberry Pi dedicated package from ScanResult.
func (r ScanResult) RemoveRaspbianPackFromResult() ScanResult {
if r.Family != config.Raspbian {
return r
}
result := r
packs := make(Packages)
for _, pack := range r.Packages {
if !IsRaspbianPackage(pack.Name, pack.Version) {
packs[pack.Name] = pack
}
}
srcPacks := make(SrcPackages)
for _, pack := range r.SrcPackages {
if !IsRaspbianPackage(pack.Name, pack.Version) {
srcPacks[pack.Name] = pack
}
}
result.Packages = packs
result.SrcPackages = srcPacks
return result
}

View File

@@ -688,7 +688,7 @@ func TestIsDisplayUpdatableNum(t *testing.T) {
{
mode: []byte{config.Fast},
family: config.FreeBSD,
expected: true,
expected: false,
},
{
mode: []byte{config.Fast},

View File

@@ -38,7 +38,13 @@ func (o DebianBase) update(r *models.ScanResult, defPacks defPacks) {
defPacks.def.Debian.CveID)
cveContents = models.CveContents{}
}
vinfo.Confidences.AppendIfMissing(models.OvalMatch)
if r.Family != config.Raspbian {
vinfo.Confidences.AppendIfMissing(models.OvalMatch)
} else {
if len(vinfo.Confidences) == 0 {
vinfo.Confidences.AppendIfMissing(models.OvalMatch)
}
}
cveContents[ctype] = ovalContent
vinfo.CveContents = cveContents
}
@@ -132,12 +138,28 @@ func (o Debian) FillWithOval(driver db.DB, r *models.ScanResult) (nCVEs int, err
var relatedDefs ovalResult
if config.Conf.OvalDict.IsFetchViaHTTP() {
if relatedDefs, err = getDefsByPackNameViaHTTP(r); err != nil {
return 0, err
if r.Family != config.Raspbian {
if relatedDefs, err = getDefsByPackNameViaHTTP(r); err != nil {
return 0, err
}
} else {
// OVAL does not support Package for Raspbian, so skip it.
result := r.RemoveRaspbianPackFromResult()
if relatedDefs, err = getDefsByPackNameViaHTTP(&result); err != nil {
return 0, err
}
}
} else {
if relatedDefs, err = getDefsByPackNameFromOvalDB(driver, r); err != nil {
return 0, err
if r.Family != config.Raspbian {
if relatedDefs, err = getDefsByPackNameFromOvalDB(driver, r); err != nil {
return 0, err
}
} else {
// OVAL does not support Package for Raspbian, so skip it.
result := r.RemoveRaspbianPackFromResult()
if relatedDefs, err = getDefsByPackNameFromOvalDB(driver, &result); err != nil {
return 0, err
}
}
}

View File

@@ -100,7 +100,7 @@ func (o RedHatBase) update(r *models.ScanResult, defPacks defPacks) (nCVEs int)
cveContents := vinfo.CveContents
if v, ok := vinfo.CveContents[ctype]; ok {
if v.LastModified.After(ovalContent.LastModified) {
util.Log.Debugf("%s, OvalID: %d ignroed: ",
util.Log.Debugf("%s, OvalID: %d ignored: ",
cve.CveID, defPacks.def.ID)
} else {
util.Log.Debugf("%s OVAL will be overwritten", cve.CveID)

View File

@@ -327,7 +327,8 @@ func isOvalDefAffected(def ovalmodels.Definition, req request, family string, ru
config.Amazon,
config.SUSEEnterpriseServer,
config.Debian,
config.Ubuntu:
config.Ubuntu,
config.Raspbian:
// Use fixed state in OVAL for these distros.
return true, false, ovalPack.Version
}
@@ -362,7 +363,8 @@ var esVerPattern = regexp.MustCompile(`\.el(\d+)(?:_\d+)?`)
func lessThan(family, newVer string, packInOVAL ovalmodels.Package) (bool, error) {
switch family {
case config.Debian,
config.Ubuntu:
config.Ubuntu,
config.Raspbian:
vera, err := debver.NewVersion(newVer)
if err != nil {
return false, err

View File

@@ -1089,7 +1089,7 @@ func TestIsOvalDefAffected(t *testing.T) {
}
}
func TestMajor(t *testing.T) {
func Test_major(t *testing.T) {
var tests = []struct {
in string
expected string

View File

@@ -5,10 +5,11 @@ import (
"fmt"
"net"
"net/mail"
"net/smtp"
"strings"
"time"
sasl "github.com/emersion/go-sasl"
smtp "github.com/emersion/go-smtp"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
"golang.org/x/xerrors"
@@ -21,7 +22,6 @@ func (w EMailWriter) Write(rs ...models.ScanResult) (err error) {
conf := config.Conf
var message string
sender := NewEMailSender()
m := map[string]int{}
for _, r := range rs {
if conf.FormatOneEMail {
@@ -85,37 +85,50 @@ type EMailSender interface {
type emailSender struct {
conf config.SMTPConf
send func(string, smtp.Auth, string, []string, []byte) error
}
func smtps(emailConf config.SMTPConf, message string) (err error) {
auth := smtp.PlainAuth("",
emailConf.User,
emailConf.Password,
emailConf.SMTPAddr,
)
func (e *emailSender) sendMail(smtpServerAddr, message string) (err error) {
var c *smtp.Client
var auth sasl.Client
emailConf := e.conf
//TLS Config
tlsConfig := &tls.Config{
ServerName: emailConf.SMTPAddr,
}
smtpServer := net.JoinHostPort(emailConf.SMTPAddr, emailConf.SMTPPort)
//New TLS connection
con, err := tls.Dial("tcp", smtpServer, tlsConfig)
if err != nil {
return xerrors.Errorf("Failed to create TLS connection: %w", err)
switch emailConf.SMTPPort {
case "465":
//New TLS connection
c, err = smtp.DialTLS(smtpServerAddr, tlsConfig)
if err != nil {
return xerrors.Errorf("Failed to create TLS connection to SMTP server: %w", err)
}
default:
c, err = smtp.Dial(smtpServerAddr)
if err != nil {
return xerrors.Errorf("Failed to create connection to SMTP server: %w", err)
}
}
defer con.Close()
defer c.Close()
c, err := smtp.NewClient(con, emailConf.SMTPAddr)
if err != nil {
return xerrors.Errorf("Failed to create new client: %w", err)
if err = c.Hello("localhost"); err != nil {
return xerrors.Errorf("Failed to send Hello command: %w", err)
}
if ok, _ := c.Extension("STARTTLS"); ok {
if err := c.StartTLS(tlsConfig); err != nil {
return xerrors.Errorf("Failed to STARTTLS: %w", err)
}
}
if ok, param := c.Extension("AUTH"); ok {
authList := strings.Split(param, " ")
auth = e.newSaslClient(authList)
}
if err = c.Auth(auth); err != nil {
return xerrors.Errorf("Failed to authenticate: %w", err)
}
if err = c.Mail(emailConf.From); err != nil {
if err = c.Mail(emailConf.From, nil); err != nil {
return xerrors.Errorf("Failed to send Mail command: %w", err)
}
for _, to := range emailConf.To {
@@ -169,38 +182,13 @@ func (e *emailSender) Send(subject, body string) (err error) {
smtpServer := net.JoinHostPort(emailConf.SMTPAddr, emailConf.SMTPPort)
if emailConf.User != "" && emailConf.Password != "" {
switch emailConf.SMTPPort {
case "465":
err := smtps(emailConf, message)
if err != nil {
return xerrors.Errorf("Failed to send emails: %w", err)
}
default:
err = e.send(
smtpServer,
smtp.PlainAuth(
"",
emailConf.User,
emailConf.Password,
emailConf.SMTPAddr,
),
emailConf.From,
mailAddresses,
[]byte(message),
)
if err != nil {
return xerrors.Errorf("Failed to send emails: %w", err)
}
err = e.sendMail(smtpServer, message)
if err != nil {
return xerrors.Errorf("Failed to send emails: %w", err)
}
return nil
}
err = e.send(
smtpServer,
nil,
emailConf.From,
mailAddresses,
[]byte(message),
)
err = e.sendMail(smtpServer, message)
if err != nil {
return xerrors.Errorf("Failed to send emails: %w", err)
}
@@ -209,5 +197,19 @@ func (e *emailSender) Send(subject, body string) (err error) {
// NewEMailSender creates emailSender
func NewEMailSender() EMailSender {
return &emailSender{config.Conf.EMail, smtp.SendMail}
return &emailSender{config.Conf.EMail}
}
func (e *emailSender) newSaslClient(authList []string) sasl.Client {
for _, v := range authList {
switch v {
case "PLAIN":
auth := sasl.NewPlainClient("", e.conf.User, e.conf.Password)
return auth
case "LOGIN":
auth := sasl.NewLoginClient(e.conf.User, e.conf.Password)
return auth
}
}
return nil
}

View File

@@ -1,115 +0,0 @@
package report
import (
"net/smtp"
"reflect"
"strings"
"testing"
"github.com/future-architect/vuls/config"
)
type emailRecorder struct {
addr string
auth smtp.Auth
from string
to []string
body string
}
type mailTest struct {
in config.SMTPConf
out emailRecorder
}
var mailTests = []mailTest{
{
config.SMTPConf{
SMTPAddr: "127.0.0.1",
SMTPPort: "25",
From: "from@address.com",
To: []string{"to@address.com"},
Cc: []string{"cc@address.com"},
},
emailRecorder{
addr: "127.0.0.1:25",
auth: smtp.PlainAuth("", "", "", "127.0.0.1"),
from: "from@address.com",
to: []string{"to@address.com", "cc@address.com"},
body: "body",
},
},
{
config.SMTPConf{
SMTPAddr: "127.0.0.1",
SMTPPort: "25",
User: "vuls",
Password: "password",
From: "from@address.com",
To: []string{"to1@address.com", "to2@address.com"},
Cc: []string{"cc1@address.com", "cc2@address.com"},
},
emailRecorder{
addr: "127.0.0.1:25",
auth: smtp.PlainAuth(
"",
"vuls",
"password",
"127.0.0.1",
),
from: "from@address.com",
to: []string{"to1@address.com", "to2@address.com",
"cc1@address.com", "cc2@address.com"},
body: "body",
},
},
}
func TestSend(t *testing.T) {
for i, test := range mailTests {
f, r := mockSend(nil)
sender := &emailSender{conf: test.in, send: f}
subject := "subject"
body := "body"
if err := sender.Send(subject, body); err != nil {
t.Errorf("unexpected error: %s", err)
}
if r.addr != test.out.addr {
t.Errorf("#%d: wrong 'addr' field.\r\nexpected: %s\n got: %s", i, test.out.addr, r.addr)
}
if !reflect.DeepEqual(r.auth, test.out.auth) && r.auth != nil {
t.Errorf("#%d: wrong 'auth' field.\r\nexpected: %v\n got: %v", i, test.out.auth, r.auth)
}
if r.from != test.out.from {
t.Errorf("#%d: wrong 'from' field.\r\nexpected: %v\n got: %v", i, test.out.from, r.from)
}
if !reflect.DeepEqual(r.to, test.out.to) {
t.Errorf("#%d: wrong 'to' field.\r\nexpected: %v\n got: %v", i, test.out.to, r.to)
}
if r.body != test.out.body {
t.Errorf("#%d: wrong 'body' field.\r\nexpected: %v\n got: %v", i, test.out.body, r.body)
}
}
}
func mockSend(errToReturn error) (func(string, smtp.Auth, string, []string, []byte) error, *emailRecorder) {
r := new(emailRecorder)
return func(addr string, a smtp.Auth, from string, to []string, msg []byte) error {
// Split into header and body
messages := strings.Split(string(msg), "\r\n\r\n")
body := messages[1]
*r = emailRecorder{addr, a, from, to, body}
return errToReturn
}, r
}

View File

@@ -49,7 +49,7 @@ func FillCveInfos(dbclient DBClient, rs []models.ScanResult, dir string) ([]mode
wpVulnCaches := map[string]string{}
for _, r := range rs {
if c.Conf.RefreshCve || needToRefreshCve(r) {
if ovalSupported(&r) {
if !useScannedCves(&r) {
r.ScannedCves = models.VulnInfos{}
}
cpeURIs := []string{}
@@ -285,7 +285,7 @@ func FillWithOval(driver ovaldb.DB, r *models.ScanResult) (nCVEs int, err error)
var ovalFamily string
switch r.Family {
case c.Debian:
case c.Debian, c.Raspbian:
ovalClient = oval.NewDebian()
ovalFamily = c.Debian
case c.Ubuntu:
@@ -311,7 +311,7 @@ func FillWithOval(driver ovaldb.DB, r *models.ScanResult) (nCVEs int, err error)
case c.Amazon:
ovalClient = oval.NewAmazon()
ovalFamily = c.Amazon
case c.Raspbian, c.FreeBSD, c.Windows:
case c.FreeBSD, c.Windows:
return 0, nil
case c.ServerTypePseudo:
return 0, nil

View File

@@ -13,7 +13,7 @@ type StdoutWriter struct{}
// WriteScanSummary prints Scan summary at the end of scan
func (w StdoutWriter) WriteScanSummary(rs ...models.ScanResult) {
fmt.Printf("\n\n")
fmt.Println("One Line Summary")
fmt.Println("Scan Summary")
fmt.Println("================")
fmt.Printf("%s\n", formatScanSummary(rs...))
}

View File

@@ -617,6 +617,14 @@ func summaryLines(r models.ScanResult) string {
pkgNames = append(pkgNames, vinfo.WpPackageFixStats.Names()...)
pkgNames = append(pkgNames, vinfo.LibraryFixedIns.Names()...)
av := vinfo.AttackVector()
for _, pname := range vinfo.AffectedPackages.Names() {
if r.Packages[pname].HasPortScanSuccessOn() {
av = fmt.Sprintf("%s ◉", av)
break
}
}
exploits := ""
if 0 < len(vinfo.Exploits) || 0 < len(vinfo.Metasploits) {
exploits = "POC"
@@ -627,7 +635,7 @@ func summaryLines(r models.ScanResult) string {
fmt.Sprintf(indexFormat, i+1),
vinfo.CveID,
cvssScore + " |",
fmt.Sprintf("%4s |", vinfo.AttackVector()),
fmt.Sprintf("%-6s |", av),
fmt.Sprintf("%3s |", exploits),
fmt.Sprintf("%6s |", vinfo.AlertDict.FormatSource()),
fmt.Sprintf("%7s |", vinfo.PatchStatus(r.Packages)),
@@ -639,6 +647,7 @@ func summaryLines(r models.ScanResult) string {
}
stable.AddRow(icols...)
}
return fmt.Sprintf("%s", stable)
}
@@ -710,8 +719,23 @@ func setChangelogLayout(g *gocui.Gui) error {
if len(pack.AffectedProcs) != 0 {
for _, p := range pack.AffectedProcs {
if len(p.ListenPorts) == 0 {
lines = append(lines, fmt.Sprintf(" * PID: %s %s Port: []",
p.PID, p.Name))
continue
}
var ports []string
for _, pp := range p.ListenPorts {
if len(pp.PortScanSuccessOn) == 0 {
ports = append(ports, fmt.Sprintf("%s:%s", pp.Address, pp.Port))
} else {
ports = append(ports, fmt.Sprintf("%s:%s(◉ Scannable: %s)", pp.Address, pp.Port, pp.PortScanSuccessOn))
}
}
lines = append(lines, fmt.Sprintf(" * PID: %s %s Port: %s",
p.PID, p.Name, p.ListenPorts))
p.PID, p.Name, ports))
}
}
}

View File

@@ -97,7 +97,7 @@ func formatOneLineSummary(rs ...models.ScanResult) string {
}
func formatList(r models.ScanResult) string {
header := r.FormatTextReportHeadedr()
header := r.FormatTextReportHeader()
if len(r.Errors) != 0 {
return fmt.Sprintf(
"%s\nError: Use configtest subcommand or scan with --debug to view the details\n%s\n\n",
@@ -171,7 +171,7 @@ No CVE-IDs are found in updatable packages.
}
func formatFullPlainText(r models.ScanResult) (lines string) {
header := r.FormatTextReportHeadedr()
header := r.FormatTextReportHeader()
if len(r.Errors) != 0 {
return fmt.Sprintf(
"%s\nError: Use configtest subcommand or scan with --debug to view the details\n%s\n\n",
@@ -261,8 +261,22 @@ No CVE-IDs are found in updatable packages.
if len(pack.AffectedProcs) != 0 {
for _, p := range pack.AffectedProcs {
if len(p.ListenPorts) == 0 {
data = append(data, []string{"",
fmt.Sprintf(" - PID: %s %s, Port: []", p.PID, p.Name)})
}
var ports []string
for _, pp := range p.ListenPorts {
if len(pp.PortScanSuccessOn) == 0 {
ports = append(ports, fmt.Sprintf("%s:%s", pp.Address, pp.Port))
} else {
ports = append(ports, fmt.Sprintf("%s:%s(◉ Scannable: %s)", pp.Address, pp.Port, pp.PortScanSuccessOn))
}
}
data = append(data, []string{"",
fmt.Sprintf(" - PID: %s %s, Port: %s", p.PID, p.Name, p.ListenPorts)})
fmt.Sprintf(" - PID: %s %s, Port: %s", p.PID, p.Name, ports)})
}
}
}
@@ -388,15 +402,14 @@ func formatChangelogs(r models.ScanResult) string {
}
return strings.Join(buf, "\n")
}
func ovalSupported(r *models.ScanResult) bool {
func useScannedCves(r *models.ScanResult) bool {
switch r.Family {
case
config.Amazon,
config.FreeBSD,
config.Raspbian:
return false
return true
}
return true
return false
}
func needToRefreshCve(r models.ScanResult) bool {
@@ -500,9 +513,9 @@ func getDiffCves(previous, current models.ScanResult) models.VulnInfos {
updated[v.CveID] = v
util.Log.Debugf("updated: %s", v.CveID)
// TODO commented out beause a bug of diff logic when multiple oval defs found for a certain CVE-ID and same updated_at
// TODO commented out because a bug of diff logic when multiple oval defs found for a certain CVE-ID and same updated_at
// if these OVAL defs have different affected packages, this logic detects as updated.
// This logic will be uncommented after integration with ghost https://github.com/knqyf263/gost
// This logic will be uncomented after integration with ghost https://github.com/knqyf263/gost
// } else if isCveFixed(v, previous) {
// updated[v.CveID] = v
// util.Log.Debugf("fixed: %s", v.CveID)

View File

@@ -147,6 +147,9 @@ func (o *alpine) parseApkInfo(stdout string) (models.Packages, error) {
line := scanner.Text()
ss := strings.Split(line, "-")
if len(ss) < 3 {
if strings.Contains(ss[0], "WARNING") {
continue
}
return nil, xerrors.Errorf("Failed to parse apk info -v: %s", line)
}
name := strings.Join(ss[:len(ss)-2], "-")

View File

@@ -4,6 +4,7 @@ import (
"bufio"
"encoding/json"
"fmt"
"io/ioutil"
"net"
"os"
"regexp"
@@ -545,8 +546,8 @@ func (l *base) scanLibraries() (err error) {
}
// delete last "-o "
// find / -name "*package-lock.json" -o -name "*yarn.lock" ... 2>&1 | grep -v "Permission denied"
cmd := fmt.Sprintf(`find / ` + findopt[:len(findopt)-3] + ` 2>&1 | grep -v "Permission denied"`)
// find / -name "*package-lock.json" -o -name "*yarn.lock" ... 2>&1 | grep -v "find: "
cmd := fmt.Sprintf(`find / ` + findopt[:len(findopt)-3] + ` 2>&1 | grep -v "find: "`)
r := exec(l.ServerInfo, cmd, noSudo)
if r.ExitStatus != 0 && r.ExitStatus != 1 {
return xerrors.Errorf("Failed to find lock files")
@@ -562,12 +563,23 @@ func (l *base) scanLibraries() (err error) {
if _, ok := libFilemap[path]; ok {
continue
}
cmd := fmt.Sprintf("cat %s", path)
r := exec(l.ServerInfo, cmd, noSudo)
if !r.isSuccess() {
return xerrors.Errorf("Failed to get target file: %s, filepath: %s", r, path)
var bytes []byte
switch l.Distro.Family {
case config.ServerTypePseudo:
bytes, err = ioutil.ReadFile(path)
if err != nil {
return xerrors.Errorf("Failed to get target file: %s, filepath: %s", err, path)
}
default:
cmd := fmt.Sprintf("cat %s", path)
r := exec(l.ServerInfo, cmd, noSudo)
if !r.isSuccess() {
return xerrors.Errorf("Failed to get target file: %s, filepath: %s", r, path)
}
bytes = []byte(r.Stdout)
}
libFilemap[path] = []byte(r.Stdout)
libFilemap[path] = bytes
}
for path, b := range libFilemap {
@@ -717,6 +729,109 @@ func (l *base) detectWpPlugins() ([]models.WpPackage, error) {
return plugins, nil
}
func (l *base) scanPorts() (err error) {
dest := l.detectScanDest()
open, err := l.execPortsScan(dest)
if err != nil {
return err
}
l.updatePortStatus(open)
return nil
}
func (l *base) detectScanDest() []string {
scanIPPortsMap := map[string][]string{}
for _, p := range l.osPackages.Packages {
if p.AffectedProcs == nil {
continue
}
for _, proc := range p.AffectedProcs {
if proc.ListenPorts == nil {
continue
}
for _, port := range proc.ListenPorts {
scanIPPortsMap[port.Address] = append(scanIPPortsMap[port.Address], port.Port)
}
}
}
scanDestIPPorts := []string{}
for addr, ports := range scanIPPortsMap {
if addr == "*" {
for _, addr := range l.ServerInfo.IPv4Addrs {
for _, port := range ports {
scanDestIPPorts = append(scanDestIPPorts, addr+":"+port)
}
}
} else {
for _, port := range ports {
scanDestIPPorts = append(scanDestIPPorts, addr+":"+port)
}
}
}
m := map[string]bool{}
uniqScanDestIPPorts := []string{}
for _, e := range scanDestIPPorts {
if !m[e] {
m[e] = true
uniqScanDestIPPorts = append(uniqScanDestIPPorts, e)
}
}
return uniqScanDestIPPorts
}
func (l *base) execPortsScan(scanDestIPPorts []string) ([]string, error) {
listenIPPorts := []string{}
for _, ipPort := range scanDestIPPorts {
conn, err := net.DialTimeout("tcp", ipPort, time.Duration(1)*time.Second)
if err != nil {
continue
}
conn.Close()
listenIPPorts = append(listenIPPorts, ipPort)
}
return listenIPPorts, nil
}
func (l *base) updatePortStatus(listenIPPorts []string) {
for name, p := range l.osPackages.Packages {
if p.AffectedProcs == nil {
continue
}
for i, proc := range p.AffectedProcs {
if proc.ListenPorts == nil {
continue
}
for j, port := range proc.ListenPorts {
l.osPackages.Packages[name].AffectedProcs[i].ListenPorts[j].PortScanSuccessOn = l.findPortScanSuccessOn(listenIPPorts, port)
}
}
}
}
func (l *base) findPortScanSuccessOn(listenIPPorts []string, searchListenPort models.ListenPort) []string {
addrs := []string{}
for _, ipPort := range listenIPPorts {
ipPort := l.parseListenPorts(ipPort)
if searchListenPort.Address == "*" {
if searchListenPort.Port == ipPort.Port {
addrs = append(addrs, ipPort.Address)
}
} else if searchListenPort.Address == ipPort.Address && searchListenPort.Port == ipPort.Port {
addrs = append(addrs, ipPort.Address)
}
}
return addrs
}
func (l *base) ps() (stdout string, err error) {
cmd := `LANGUAGE=en_US.UTF-8 ps --no-headers --ppid 2 -p 2 --deselect -o pid,comm`
r := l.exec(util.PrependProxyEnv(cmd), noSudo)
@@ -797,3 +912,11 @@ func (l *base) parseLsOf(stdout string) map[string]string {
}
return portPid
}
func (l *base) parseListenPorts(port string) models.ListenPort {
sep := strings.LastIndex(port, ":")
if sep == -1 {
return models.ListenPort{}
}
return models.ListenPort{Address: port[:sep], Port: port[sep+1:]}
}

View File

@@ -12,6 +12,7 @@ import (
_ "github.com/aquasecurity/fanal/analyzer/library/poetry"
_ "github.com/aquasecurity/fanal/analyzer/library/yarn"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
)
func TestParseDockerPs(t *testing.T) {
@@ -275,3 +276,242 @@ docker-pr 9135 root 4u IPv6 297133 0t0 TCP *:6379 (LISTEN)
})
}
}
func Test_detectScanDest(t *testing.T) {
tests := []struct {
name string
args base
expect []string
}{
{
name: "empty",
args: base{osPackages: osPackages{
Packages: models.Packages{"curl": models.Package{
Name: "curl",
Version: "7.64.0-4+deb10u1",
NewVersion: "7.64.0-4+deb10u1",
}},
}},
expect: []string{},
},
{
name: "single-addr",
args: base{osPackages: osPackages{
Packages: models.Packages{"libaudit1": models.Package{
Name: "libaudit1",
Version: "1:2.8.4-3",
NewVersion: "1:2.8.4-3",
AffectedProcs: []models.AffectedProcess{
{PID: "21", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "127.0.0.1", Port: "22"}}}, {PID: "10876", Name: "sshd"}},
},
}},
},
expect: []string{"127.0.0.1:22"},
},
{
name: "dup-addr",
args: base{osPackages: osPackages{
Packages: models.Packages{"libaudit1": models.Package{
Name: "libaudit1",
Version: "1:2.8.4-3",
NewVersion: "1:2.8.4-3",
AffectedProcs: []models.AffectedProcess{
{PID: "21", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "127.0.0.1", Port: "22"}}}, {PID: "21", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "127.0.0.1", Port: "22"}}}},
},
}},
},
expect: []string{"127.0.0.1:22"},
},
{
name: "multi-addr",
args: base{osPackages: osPackages{
Packages: models.Packages{"libaudit1": models.Package{
Name: "libaudit1",
Version: "1:2.8.4-3",
NewVersion: "1:2.8.4-3",
AffectedProcs: []models.AffectedProcess{
{PID: "21", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "127.0.0.1", Port: "22"}}}, {PID: "21", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "192.168.1.1", Port: "22"}}}},
},
}},
},
expect: []string{"127.0.0.1:22", "192.168.1.1:22"},
},
{
name: "asterisk",
args: base{
osPackages: osPackages{
Packages: models.Packages{"libaudit1": models.Package{
Name: "libaudit1",
Version: "1:2.8.4-3",
NewVersion: "1:2.8.4-3",
AffectedProcs: []models.AffectedProcess{
{PID: "21", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "*", Port: "22"}}}},
},
}},
ServerInfo: config.ServerInfo{
IPv4Addrs: []string{"127.0.0.1", "192.168.1.1"},
},
},
expect: []string{"127.0.0.1:22", "192.168.1.1:22"},
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if dest := tt.args.detectScanDest(); !reflect.DeepEqual(dest, tt.expect) {
t.Errorf("base.detectScanDest() = %v, want %v", dest, tt.expect)
}
})
}
}
func Test_updatePortStatus(t *testing.T) {
type args struct {
l base
listenIPPorts []string
}
tests := []struct {
name string
args args
expect models.Packages
}{
{name: "nil_affected_procs",
args: args{
l: base{osPackages: osPackages{
Packages: models.Packages{"libc-bin": models.Package{Name: "libc-bin"}},
}},
listenIPPorts: []string{"127.0.0.1:22"}},
expect: models.Packages{"libc-bin": models.Package{Name: "libc-bin"}}},
{name: "nil_listen_ports",
args: args{
l: base{osPackages: osPackages{
Packages: models.Packages{"bash": models.Package{Name: "bash", AffectedProcs: []models.AffectedProcess{{PID: "1", Name: "bash"}}}},
}},
listenIPPorts: []string{"127.0.0.1:22"}},
expect: models.Packages{"bash": models.Package{Name: "bash", AffectedProcs: []models.AffectedProcess{{PID: "1", Name: "bash"}}}}},
{name: "update_match_single_address",
args: args{
l: base{osPackages: osPackages{
Packages: models.Packages{"libc6": models.Package{Name: "libc6", AffectedProcs: []models.AffectedProcess{{PID: "1", Name: "bash"}, {PID: "75", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "127.0.0.1", Port: "22"}}}}}},
}},
listenIPPorts: []string{"127.0.0.1:22"}},
expect: models.Packages{"libc6": models.Package{Name: "libc6", AffectedProcs: []models.AffectedProcess{{PID: "1", Name: "bash"}, {PID: "75", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "127.0.0.1", Port: "22", PortScanSuccessOn: []string{"127.0.0.1"}}}}}}}},
{name: "update_match_multi_address",
args: args{
l: base{osPackages: osPackages{
Packages: models.Packages{"libc6": models.Package{Name: "libc6", AffectedProcs: []models.AffectedProcess{{PID: "1", Name: "bash"}, {PID: "75", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "127.0.0.1", Port: "22"}, {Address: "192.168.1.1", Port: "22"}}}}}},
}},
listenIPPorts: []string{"127.0.0.1:22", "192.168.1.1:22"}},
expect: models.Packages{"libc6": models.Package{Name: "libc6", AffectedProcs: []models.AffectedProcess{{PID: "1", Name: "bash"}, {PID: "75", Name: "sshd", ListenPorts: []models.ListenPort{
{Address: "127.0.0.1", Port: "22", PortScanSuccessOn: []string{"127.0.0.1"}},
{Address: "192.168.1.1", Port: "22", PortScanSuccessOn: []string{"192.168.1.1"}},
}}}}}},
{name: "update_match_asterisk",
args: args{
l: base{osPackages: osPackages{
Packages: models.Packages{"libc6": models.Package{Name: "libc6", AffectedProcs: []models.AffectedProcess{{PID: "1", Name: "bash"}, {PID: "75", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "*", Port: "22"}}}}}},
}},
listenIPPorts: []string{"127.0.0.1:22", "127.0.0.1:80", "192.168.1.1:22"}},
expect: models.Packages{"libc6": models.Package{Name: "libc6", AffectedProcs: []models.AffectedProcess{{PID: "1", Name: "bash"}, {PID: "75", Name: "sshd", ListenPorts: []models.ListenPort{
{Address: "*", Port: "22", PortScanSuccessOn: []string{"127.0.0.1", "192.168.1.1"}},
}}}}}},
{name: "update_multi_packages",
args: args{
l: base{osPackages: osPackages{
Packages: models.Packages{
"packa": models.Package{Name: "packa", AffectedProcs: []models.AffectedProcess{{PID: "75", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "127.0.0.1", Port: "80"}}}}},
"packb": models.Package{Name: "packb", AffectedProcs: []models.AffectedProcess{{PID: "75", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "127.0.0.1", Port: "22"}}}}},
"packc": models.Package{Name: "packc", AffectedProcs: []models.AffectedProcess{{PID: "75", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "127.0.0.1", Port: "22"}, {Address: "192.168.1.1", Port: "22"}}}}},
"packd": models.Package{Name: "packd", AffectedProcs: []models.AffectedProcess{{PID: "75", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "*", Port: "22"}}}}},
},
}},
listenIPPorts: []string{"127.0.0.1:22", "192.168.1.1:22"}},
expect: models.Packages{
"packa": models.Package{Name: "packa", AffectedProcs: []models.AffectedProcess{{PID: "75", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "127.0.0.1", Port: "80", PortScanSuccessOn: []string{}}}}}},
"packb": models.Package{Name: "packb", AffectedProcs: []models.AffectedProcess{{PID: "75", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "127.0.0.1", Port: "22", PortScanSuccessOn: []string{"127.0.0.1"}}}}}},
"packc": models.Package{Name: "packc", AffectedProcs: []models.AffectedProcess{{PID: "75", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "127.0.0.1", Port: "22", PortScanSuccessOn: []string{"127.0.0.1"}}, {Address: "192.168.1.1", Port: "22", PortScanSuccessOn: []string{"192.168.1.1"}}}}}},
"packd": models.Package{Name: "packd", AffectedProcs: []models.AffectedProcess{{PID: "75", Name: "sshd", ListenPorts: []models.ListenPort{{Address: "*", Port: "22", PortScanSuccessOn: []string{"127.0.0.1", "192.168.1.1"}}}}}},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.args.l.updatePortStatus(tt.args.listenIPPorts)
if !reflect.DeepEqual(tt.args.l.osPackages.Packages, tt.expect) {
t.Errorf("l.updatePortStatus() = %v, want %v", tt.args.l.osPackages.Packages, tt.expect)
}
})
}
}
func Test_matchListenPorts(t *testing.T) {
type args struct {
listenIPPorts []string
searchListenPort models.ListenPort
}
tests := []struct {
name string
args args
expect []string
}{
{name: "open_empty", args: args{listenIPPorts: []string{}, searchListenPort: models.ListenPort{Address: "127.0.0.1", Port: "22"}}, expect: []string{}},
{name: "port_empty", args: args{listenIPPorts: []string{"127.0.0.1:22"}, searchListenPort: models.ListenPort{}}, expect: []string{}},
{name: "single_match", args: args{listenIPPorts: []string{"127.0.0.1:22"}, searchListenPort: models.ListenPort{Address: "127.0.0.1", Port: "22"}}, expect: []string{"127.0.0.1"}},
{name: "no_match_address", args: args{listenIPPorts: []string{"127.0.0.1:22"}, searchListenPort: models.ListenPort{Address: "192.168.1.1", Port: "22"}}, expect: []string{}},
{name: "no_match_port", args: args{listenIPPorts: []string{"127.0.0.1:22"}, searchListenPort: models.ListenPort{Address: "127.0.0.1", Port: "80"}}, expect: []string{}},
{name: "asterisk_match", args: args{listenIPPorts: []string{"127.0.0.1:22", "127.0.0.1:80", "192.168.1.1:22"}, searchListenPort: models.ListenPort{Address: "*", Port: "22"}}, expect: []string{"127.0.0.1", "192.168.1.1"}},
}
l := base{}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if match := l.findPortScanSuccessOn(tt.args.listenIPPorts, tt.args.searchListenPort); !reflect.DeepEqual(match, tt.expect) {
t.Errorf("findPortScanSuccessOn() = %v, want %v", match, tt.expect)
}
})
}
}
func Test_base_parseListenPorts(t *testing.T) {
tests := []struct {
name string
args string
expect models.ListenPort
}{{
name: "empty",
args: "",
expect: models.ListenPort{
Address: "",
Port: "",
},
}, {
name: "normal",
args: "127.0.0.1:22",
expect: models.ListenPort{
Address: "127.0.0.1",
Port: "22",
},
}, {
name: "asterisk",
args: "*:22",
expect: models.ListenPort{
Address: "*",
Port: "22",
},
}, {
name: "ipv6_loopback",
args: "[::1]:22",
expect: models.ListenPort{
Address: "[::1]",
Port: "22",
},
}}
l := base{}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if listenPort := l.parseListenPorts(tt.args); !reflect.DeepEqual(listenPort, tt.expect) {
t.Errorf("base.parseListenPorts() = %v, want %v", listenPort, tt.expect)
}
})
}
}

View File

@@ -2,6 +2,8 @@ package scan
import (
"bufio"
"crypto/rand"
"encoding/binary"
"fmt"
"regexp"
"strconv"
@@ -305,7 +307,18 @@ func (o *debian) scanPackages() error {
return nil
}
if o.getServerInfo().Mode.IsDeep() || o.Distro.Family == config.Raspbian {
if !o.getServerInfo().Mode.IsDeep() && o.Distro.Family == config.Raspbian {
raspbianPacks := o.grepRaspbianPackages(updatable)
unsecures, err := o.scanUnsecurePackages(raspbianPacks)
if err != nil {
o.log.Errorf("Failed to scan vulnerable packages: %s", err)
return err
}
o.VulnInfos = unsecures
return nil
}
if o.getServerInfo().Mode.IsDeep() {
unsecures, err := o.scanUnsecurePackages(updatable)
if err != nil {
o.log.Errorf("Failed to scan vulnerable packages: %s", err)
@@ -314,6 +327,7 @@ func (o *debian) scanPackages() error {
o.VulnInfos = unsecures
return nil
}
return nil
}
@@ -326,7 +340,7 @@ func (o *debian) rebootRequired() (bool, error) {
case 1:
return false, nil
default:
return false, xerrors.Errorf("Failed to check reboot reauired: %s", r)
return false, xerrors.Errorf("Failed to check reboot required: %s", r)
}
}
@@ -463,6 +477,17 @@ func (o *debian) aptGetUpdate() error {
return nil
}
func (o *debian) grepRaspbianPackages(updatables models.Packages) models.Packages {
raspbianPacks := models.Packages{}
for _, pack := range updatables {
if models.IsRaspbianPackage(pack.Name, pack.Version) {
raspbianPacks[pack.Name] = pack
}
}
return raspbianPacks
}
func (o *debian) scanUnsecurePackages(updatable models.Packages) (models.VulnInfos, error) {
// Setup changelog cache
current := cache.Meta{
@@ -477,12 +502,29 @@ func (o *debian) scanUnsecurePackages(updatable models.Packages) (models.VulnInf
return nil, err
}
// Make a directory for saving changelog to get changelog in Raspbian
tmpClogPath := ""
if o.Distro.Family == config.Raspbian {
tmpClogPath, err = o.makeTempChangelogDir()
if err != nil {
return nil, err
}
}
// Collect CVE information of upgradable packages
vulnInfos, err := o.scanChangelogs(updatable, meta)
vulnInfos, err := o.scanChangelogs(updatable, meta, tmpClogPath)
if err != nil {
return nil, xerrors.Errorf("Failed to scan unsecure packages. err: %s", err)
}
// Delete a directory for saving changelog to get changelog in Raspbian
if o.Distro.Family == config.Raspbian {
err := o.deleteTempChangelogDir(tmpClogPath)
if err != nil {
return nil, xerrors.Errorf("Failed to delete directory to save changelog for Raspbian. err: %s", err)
}
}
return vulnInfos, nil
}
@@ -505,7 +547,7 @@ func (o *debian) ensureChangelogCache(current cache.Meta) (*cache.Meta, error) {
if current.Distro.Family != cached.Distro.Family ||
current.Distro.Release != cached.Distro.Release {
o.log.Debugf("Need to refesh meta: %s", current.Name)
o.log.Debugf("Need to refresh meta: %s", current.Name)
err = cache.DB.EnsureBuckets(current)
if err != nil {
return nil, xerrors.Errorf("Failed to ensure buckets. err: %s", err)
@@ -601,6 +643,39 @@ func (o *debian) parseAptGetUpgrade(stdout string) (updatableNames []string, err
return
}
func (o *debian) makeTempChangelogDir() (string, error) {
suffix, err := generateSuffix()
if err != nil {
return "", err
}
path := "/tmp/vuls-" + suffix
cmd := fmt.Sprintf(`mkdir -p %s`, path)
cmd = util.PrependProxyEnv(cmd)
r := o.exec(cmd, noSudo)
if !r.isSuccess() {
return "", xerrors.Errorf("Failed to create directory to save changelog for Raspbian. cmd: %s, status: %d, stdout: %s, stderr: %s", cmd, r.ExitStatus, r.Stdout, r.Stderr)
}
return path, nil
}
func generateSuffix() (string, error) {
var n uint64
if err := binary.Read(rand.Reader, binary.LittleEndian, &n); err != nil {
return "", xerrors.Errorf("Failed to generate Suffix. err: %s", err)
}
return strconv.FormatUint(n, 36), nil
}
func (o *debian) deleteTempChangelogDir(tmpClogPath string) error {
cmd := fmt.Sprintf(`rm -rf %s`, tmpClogPath)
cmd = util.PrependProxyEnv(cmd)
r := o.exec(cmd, noSudo)
if !r.isSuccess() {
return xerrors.Errorf("Failed to delete directory to save changelog for Raspbian. cmd: %s, status: %d, stdout: %s, stderr: %s", cmd, r.ExitStatus, r.Stdout, r.Stderr)
}
return nil
}
// DetectedCveID has CveID, Confidence and DetectionMethod fields
// LenientMatching will be true if this vulnerability is not detected by accurate version matching.
// see https://github.com/future-architect/vuls/pull/328
@@ -609,7 +684,7 @@ type DetectedCveID struct {
Confidence models.Confidence
}
func (o *debian) scanChangelogs(updatablePacks models.Packages, meta *cache.Meta) (models.VulnInfos, error) {
func (o *debian) scanChangelogs(updatablePacks models.Packages, meta *cache.Meta, tmpClogPath string) (models.VulnInfos, error) {
type response struct {
pack *models.Package
DetectedCveIDs []DetectedCveID
@@ -645,7 +720,7 @@ func (o *debian) scanChangelogs(updatablePacks models.Packages, meta *cache.Meta
// if the changelog is not in cache or failed to get from local cache,
// get the changelog of the package via internet.
// After that, store it in the cache.
if cveIDs, pack, err := o.fetchParseChangelog(p); err != nil {
if cveIDs, pack, err := o.fetchParseChangelog(p, tmpClogPath); err != nil {
errChan <- err
} else {
resChan <- response{pack, cveIDs}
@@ -743,13 +818,22 @@ func (o *debian) getChangelogCache(meta *cache.Meta, pack models.Package) string
return changelog
}
func (o *debian) fetchParseChangelog(pack models.Package) ([]DetectedCveID, *models.Package, error) {
func (o *debian) fetchParseChangelog(pack models.Package, tmpClogPath string) ([]DetectedCveID, *models.Package, error) {
cmd := ""
switch o.Distro.Family {
case config.Ubuntu, config.Raspbian:
case config.Ubuntu:
cmd = fmt.Sprintf(`PAGER=cat apt-get -q=2 changelog %s`, pack.Name)
case config.Debian:
cmd = fmt.Sprintf(`PAGER=cat aptitude -q=2 changelog %s`, pack.Name)
case config.Raspbian:
changelogPath, err := o.getChangelogPath(pack.Name, tmpClogPath)
if err != nil {
// Ignore this Error.
o.log.Warnf("Failed to get Path to Changelog for Package: %s, err: %s", pack.Name, err)
return nil, nil, nil
}
cmd = fmt.Sprintf(`gzip -cd %s | cat`, changelogPath)
}
cmd = util.PrependProxyEnv(cmd)
@@ -765,7 +849,7 @@ func (o *debian) fetchParseChangelog(pack models.Package) ([]DetectedCveID, *mod
if clogFilledPack.Changelog.Method != models.FailedToGetChangelog {
err := cache.DB.PutChangelog(
o.getServerInfo().GetServerName(), pack.Name, pack.Changelog.Contents)
o.getServerInfo().GetServerName(), pack.Name, stdout)
if err != nil {
return nil, nil, xerrors.New("Failed to put changelog into cache")
}
@@ -775,6 +859,64 @@ func (o *debian) fetchParseChangelog(pack models.Package) ([]DetectedCveID, *mod
return cveIDs, clogFilledPack, nil
}
func (o *debian) getChangelogPath(packName, tmpClogPath string) (string, error) {
// `apt download` downloads deb package to current directory
cmd := fmt.Sprintf(`cd %s && apt download %s`, tmpClogPath, packName)
cmd = util.PrependProxyEnv(cmd)
r := o.exec(cmd, noSudo)
if !r.isSuccess() {
return "", xerrors.Errorf("Failed to Fetch deb package. cmd: %s, status: %d, stdout: %s, stderr: %s", cmd, r.ExitStatus, r.Stdout, r.Stderr)
}
cmd = fmt.Sprintf(`find %s -name "%s_*.deb"`, tmpClogPath, packName)
cmd = util.PrependProxyEnv(cmd)
r = o.exec(cmd, noSudo)
if !r.isSuccess() || r.Stdout == "" {
return "", xerrors.Errorf("Failed to find deb package. cmd: %s, status: %d, stdout: %s, stderr: %s", cmd, r.ExitStatus, r.Stdout, r.Stderr)
}
// e.g. <tmpPath>/ffmpeg_7%3a4.1.6-1~deb10u1+rpt1_armhf.deb\n => <tmpPath>/ffmpeg_7%3a4.1.6-1~deb10u1+rpt1_armhf
packChangelogDir := strings.Split(r.Stdout, ".deb")[0]
cmd = fmt.Sprintf(`dpkg-deb -x %s.deb %s`, packChangelogDir, packChangelogDir)
cmd = util.PrependProxyEnv(cmd)
r = o.exec(cmd, noSudo)
if !r.isSuccess() {
return "", xerrors.Errorf("Failed to dpkg-deb. cmd: %s, status: %d, stdout: %s, stderr: %s", cmd, r.ExitStatus, r.Stdout, r.Stderr)
}
// recurse if doc/packName is symbolic link
changelogDocDir := fmt.Sprintf("%s/usr/share/doc/%s", packChangelogDir, packName)
cmd = fmt.Sprintf(`test -L %s && readlink --no-newline %s`, changelogDocDir, changelogDocDir)
cmd = util.PrependProxyEnv(cmd)
r = o.exec(cmd, noSudo)
if r.isSuccess() {
return o.getChangelogPath(r.Stdout, tmpClogPath)
}
var results = make(map[string]execResult, 2)
packChangelogPath := fmt.Sprintf("%s/changelog.Debian.gz", changelogDocDir)
cmd = fmt.Sprintf(`test -e %s`, packChangelogPath)
cmd = util.PrependProxyEnv(cmd)
r = o.exec(cmd, noSudo)
if r.isSuccess() {
return packChangelogPath, nil
}
results["changelog.Debian.gz"] = r
packChangelogPath = fmt.Sprintf("%s/changelog.gz", changelogDocDir)
cmd = fmt.Sprintf(`test -e %s`, packChangelogPath)
cmd = util.PrependProxyEnv(cmd)
r = o.exec(cmd, noSudo)
if r.isSuccess() {
return packChangelogPath, nil
}
results["changelog.gz"] = r
return "", xerrors.Errorf(
"Failed to get changelog.\nresult(changelog.Debian.gz):%v\nresult(changelog.Debian.gz):%v",
results["changelog.Debian.gz"], results["changelog.gz"])
}
func (o *debian) getCveIDsFromChangelog(
changelog, name, ver string) ([]DetectedCveID, *models.Package) {
@@ -874,6 +1016,21 @@ func (o *debian) parseChangelog(changelog, name, ver string, confidence models.C
}
if !found {
if o.Distro.Family == config.Raspbian {
pack := o.Packages[name]
pack.Changelog = models.Changelog{
Contents: strings.Join(buf, "\n"),
Method: models.ChangelogLenientMatchStr,
}
cves := []DetectedCveID{}
for _, id := range cveIDs {
cves = append(cves, DetectedCveID{id, confidence})
}
return cves, &pack, nil
}
pack := o.Packages[name]
pack.Changelog = models.Changelog{
Contents: "",
@@ -1137,14 +1294,14 @@ func (o *debian) dpkgPs() error {
pidLoadedFiles[pid] = append(pidLoadedFiles[pid], ss...)
}
pidListenPorts := map[string][]string{}
pidListenPorts := map[string][]models.ListenPort{}
stdout, err = o.lsOfListen()
if err != nil {
return xerrors.Errorf("Failed to ls of: %w", err)
}
portPid := o.parseLsOf(stdout)
for port, pid := range portPid {
pidListenPorts[pid] = append(pidListenPorts[pid], port)
pidListenPorts[pid] = append(pidListenPorts[pid], o.parseListenPorts(port))
}
for pid, loadedFiles := range pidLoadedFiles {

View File

@@ -746,3 +746,121 @@ libuuid1:amd64: /lib/x86_64-linux-gnu/libuuid.so.1.3.0`,
})
}
}
func TestParseChangelog(t *testing.T) {
type args struct {
changelog string
name string
ver string
}
type expect struct {
cveIDs []DetectedCveID
pack models.Package
}
tests := []struct {
packName string
args args
expect expect
}{
{
packName: "vlc",
args: args{
changelog: `vlc (3.0.11-0+deb10u1+rpt2) buster; urgency=medium
* Add MMAL patch 19
-- Serge Schneider <serge@raspberrypi.com> Wed, 29 Jul 2020 14:28:28 +0100
vlc (3.0.11-0+deb10u1+rpt1) buster; urgency=high
* Add MMAL patch 18
* Add libxrandr-dev dependency
* Add libdrm-dev dependency
* Disable vdpau, libva, aom
* Enable dav1d
-- Serge Schneider <serge@raspberrypi.com> Wed, 17 Jun 2020 10:30:58 +0100
vlc (3.0.11-0+deb10u1) buster-security; urgency=high
* New upstream release
- Fix heap-based buffer overflow in hxxx_nall (CVE-2020-13428)
-- Sebastian Ramacher <sramacher@debian.org> Mon, 15 Jun 2020 23:08:37 +0200
vlc (3.0.10-0+deb10u1) buster-security; urgency=medium`,
name: "vlc",
ver: "3.0.10-0+deb10u1+rpt2",
},
expect: expect{
cveIDs: []DetectedCveID{{"CVE-2020-13428", models.ChangelogExactMatch}},
pack: models.Package{Changelog: models.Changelog{
Contents: `vlc (3.0.11-0+deb10u1+rpt2) buster; urgency=medium
* Add MMAL patch 19
-- Serge Schneider <serge@raspberrypi.com> Wed, 29 Jul 2020 14:28:28 +0100
vlc (3.0.11-0+deb10u1+rpt1) buster; urgency=high
* Add MMAL patch 18
* Add libxrandr-dev dependency
* Add libdrm-dev dependency
* Disable vdpau, libva, aom
* Enable dav1d
-- Serge Schneider <serge@raspberrypi.com> Wed, 17 Jun 2020 10:30:58 +0100
vlc (3.0.11-0+deb10u1) buster-security; urgency=high
* New upstream release
- Fix heap-based buffer overflow in hxxx_nall (CVE-2020-13428)
-- Sebastian Ramacher <sramacher@debian.org> Mon, 15 Jun 2020 23:08:37 +0200
`,
Method: models.ChangelogExactMatchStr,
}},
},
},
{
packName: "realvnc-vnc-server",
args: args{
changelog: `realvnc-vnc (6.7.2.42622) stable; urgency=low
* Debian package for VNC Server
-- RealVNC <noreply@realvnc.com> Wed, 13 May 2020 19:51:40 +0100
`,
name: "realvnc-vnc-server",
ver: "6.7.1.42348",
},
expect: expect{
cveIDs: []DetectedCveID{},
pack: models.Package{Changelog: models.Changelog{
Contents: `realvnc-vnc (6.7.2.42622) stable; urgency=low
* Debian package for VNC Server
-- RealVNC <noreply@realvnc.com> Wed, 13 May 2020 19:51:40 +0100
`,
Method: models.ChangelogLenientMatchStr,
}},
},
},
}
o := newDebian(config.ServerInfo{})
o.Distro = config.Distro{Family: config.Raspbian}
for _, tt := range tests {
t.Run(tt.packName, func(t *testing.T) {
cveIDs, pack, _ := o.parseChangelog(tt.args.changelog, tt.args.name, tt.args.ver, models.ChangelogExactMatch)
if !reflect.DeepEqual(cveIDs, tt.expect.cveIDs) {
t.Errorf("[%s]->cveIDs: expected: %s, actual: %s", tt.packName, tt.expect.cveIDs, cveIDs)
}
if !reflect.DeepEqual(pack.Changelog.Contents, tt.expect.pack.Changelog.Contents) {
t.Errorf("[%s]->changelog.Contents: expected: %s, actual: %s", tt.packName, tt.expect.pack.Changelog.Contents, pack.Changelog.Contents)
}
})
}
}

View File

@@ -333,7 +333,7 @@ func sshExecExternal(c conf.ServerInfo, cmd string, sudo bool) (result execResul
func getSSHLogger(log ...*logrus.Entry) *logrus.Entry {
if len(log) == 0 {
return util.NewCustomLogger(conf.ServerInfo{})
return util.Log
}
return log[0]
}

View File

@@ -163,12 +163,24 @@ func (o *bsd) rebootRequired() (bool, error) {
}
func (o *bsd) scanInstalledPackages() (models.Packages, error) {
cmd := util.PrependProxyEnv("pkg version -v")
// https://github.com/future-architect/vuls/issues/1042
cmd := util.PrependProxyEnv("pkg info")
r := o.exec(cmd, noSudo)
if !r.isSuccess() {
return nil, xerrors.Errorf("Failed to SSH: %s", r)
}
return o.parsePkgVersion(r.Stdout), nil
pkgs := o.parsePkgInfo(r.Stdout)
cmd = util.PrependProxyEnv("pkg version -v")
r = o.exec(cmd, noSudo)
if !r.isSuccess() {
return nil, xerrors.Errorf("Failed to SSH: %s", r)
}
// `pkg-audit` has a new version, overwrite it.
for name, p := range o.parsePkgVersion(r.Stdout) {
pkgs[name] = p
}
return pkgs, nil
}
func (o *bsd) scanUnsecurePackages() (models.VulnInfos, error) {
@@ -247,6 +259,27 @@ func (o *bsd) scanUnsecurePackages() (models.VulnInfos, error) {
return vinfos, nil
}
func (o *bsd) parsePkgInfo(stdout string) models.Packages {
packs := models.Packages{}
lines := strings.Split(stdout, "\n")
for _, l := range lines {
fields := strings.Fields(l)
if len(fields) < 2 {
continue
}
packVer := fields[0]
splitted := strings.Split(packVer, "-")
ver := splitted[len(splitted)-1]
name := strings.Join(splitted[:len(splitted)-1], "-")
packs[name] = models.Package{
Name: name,
Version: ver,
}
}
return packs
}
func (o *bsd) parsePkgVersion(stdout string) models.Packages {
packs := models.Packages{}
lines := strings.Split(stdout, "\n")

View File

@@ -197,3 +197,50 @@ WWW: https://vuxml.FreeBSD.org/freebsd/ab3e98d9-8175-11e4-907d-d050992ecde8.html
}
}
}
func TestParsePkgInfo(t *testing.T) {
var tests = []struct {
in string
expected models.Packages
}{
{
`bash-4.2.45 Universal Command Line Interface for Amazon Web Services
gettext-0.18.3.1 Startup scripts for FreeBSD/EC2 environment
tcl84-8.4.20_2,1 Update the system using freebsd-update when it first boots
ntp-4.2.8p8_1 GNU gettext runtime libraries and programs
teTeX-base-3.0_25 Foreign Function Interface`,
models.Packages{
"bash": {
Name: "bash",
Version: "4.2.45",
},
"gettext": {
Name: "gettext",
Version: "0.18.3.1",
},
"tcl84": {
Name: "tcl84",
Version: "8.4.20_2,1",
},
"teTeX-base": {
Name: "teTeX-base",
Version: "3.0_25",
},
"ntp": {
Name: "ntp",
Version: "4.2.8p8_1",
},
},
},
}
d := newBsd(config.ServerInfo{})
for _, tt := range tests {
actual := d.parsePkgInfo(tt.in)
if !reflect.DeepEqual(tt.expected, actual) {
e := pp.Sprintf("%v", tt.expected)
a := pp.Sprintf("%v", actual)
t.Errorf("expected %s, actual %s", e, a)
}
}
}

View File

@@ -279,13 +279,13 @@ func (o *redhatBase) parseInstalledPackages(stdout string) (models.Packages, mod
// openssl 0 1.0.1e 30.el6.11 x86_64
lines := strings.Split(stdout, "\n")
for _, line := range lines {
if trimed := strings.TrimSpace(line); len(trimed) != 0 {
if trimmed := strings.TrimSpace(line); len(trimmed) != 0 {
pack, err := o.parseInstalledPackagesLine(line)
if err != nil {
return nil, nil, err
}
// Kernel package may be isntalled multiple versions.
// `Kernel` and `kernel-devel` package may be installed multiple versions.
// From the viewpoint of vulnerability detection,
// pay attention only to the running kernel
isKernel, running := isRunningKernel(pack, o.Distro.Family, o.Kernel)
@@ -491,14 +491,14 @@ func (o *redhatBase) yumPs() error {
pidLoadedFiles[pid] = append(pidLoadedFiles[pid], ss...)
}
pidListenPorts := map[string][]string{}
pidListenPorts := map[string][]models.ListenPort{}
stdout, err = o.lsOfListen()
if err != nil {
return xerrors.Errorf("Failed to ls of: %w", err)
}
portPid := o.parseLsOf(stdout)
for port, pid := range portPid {
pidListenPorts[pid] = append(pidListenPorts[pid], port)
pidListenPorts[pid] = append(pidListenPorts[pid], o.parseListenPorts(port))
}
for pid, loadedFiles := range pidLoadedFiles {

View File

@@ -25,10 +25,10 @@ func TestParseInstalledPackagesLinesRedhat(t *testing.T) {
}{
{
in: `openssl 0 1.0.1e 30.el6.11 x86_64
Percona-Server-shared-56 1 5.6.19 rel67.0.el6 x84_64
kernel 0 2.6.32 696.20.1.el6 x86_64
kernel 0 2.6.32 696.20.3.el6 x86_64
kernel 0 2.6.32 695.20.3.el6 x86_64`,
Percona-Server-shared-56 1 5.6.19 rel67.0.el6 x84_64
kernel 0 2.6.32 696.20.1.el6 x86_64
kernel 0 2.6.32 696.20.3.el6 x86_64
kernel 0 2.6.32 695.20.3.el6 x86_64`,
kernel: models.Kernel{},
packages: models.Packages{
"openssl": models.Package{
@@ -50,10 +50,46 @@ func TestParseInstalledPackagesLinesRedhat(t *testing.T) {
},
{
in: `openssl 0 1.0.1e 30.el6.11 x86_64
Percona-Server-shared-56 1 5.6.19 rel67.0.el6 x84_64
kernel 0 2.6.32 696.20.1.el6 x86_64
kernel 0 2.6.32 696.20.3.el6 x86_64
kernel 0 2.6.32 695.20.3.el6 x86_64`,
Percona-Server-shared-56 1 5.6.19 rel67.0.el6 x84_64
kernel 0 2.6.32 696.20.1.el6 x86_64
kernel 0 2.6.32 696.20.3.el6 x86_64
kernel 0 2.6.32 695.20.3.el6 x86_64
kernel-devel 0 2.6.32 696.20.1.el6 x86_64
kernel-devel 0 2.6.32 696.20.3.el6 x86_64
kernel-devel 0 2.6.32 695.20.3.el6 x86_64`,
kernel: models.Kernel{Release: "2.6.32-696.20.3.el6.x86_64"},
packages: models.Packages{
"openssl": models.Package{
Name: "openssl",
Version: "1.0.1e",
Release: "30.el6.11",
},
"Percona-Server-shared-56": models.Package{
Name: "Percona-Server-shared-56",
Version: "1:5.6.19",
Release: "rel67.0.el6",
},
"kernel": models.Package{
Name: "kernel",
Version: "2.6.32",
Release: "696.20.3.el6",
},
"kernel-devel": models.Package{
Name: "kernel-devel",
Version: "2.6.32",
Release: "696.20.3.el6",
},
},
},
{
in: `openssl 0 1.0.1e 30.el6.11 x86_64
Percona-Server-shared-56 1 5.6.19 rel67.0.el6 x84_64
kernel 0 2.6.32 696.20.1.el6 x86_64
kernel 0 2.6.32 696.20.3.el6 x86_64
kernel 0 2.6.32 695.20.3.el6 x86_64
kernel-devel 0 2.6.32 696.20.1.el6 x86_64
kernel-devel 0 2.6.32 696.20.3.el6 x86_64
kernel-devel 0 2.6.32 695.20.3.el6 x86_64`,
kernel: models.Kernel{Release: "2.6.32-695.20.3.el6.x86_64"},
packages: models.Packages{
"openssl": models.Package{
@@ -71,6 +107,11 @@ func TestParseInstalledPackagesLinesRedhat(t *testing.T) {
Version: "2.6.32",
Release: "695.20.3.el6",
},
"kernel-devel": models.Package{
Name: "kernel-devel",
Version: "2.6.32",
Release: "695.20.3.el6",
},
},
},
}

View File

@@ -48,6 +48,7 @@ type osTypeInterface interface {
postScan() error
scanWordPress() error
scanLibraries() error
scanPorts() error
scanPackages() error
convertToModel() models.ScanResult
@@ -599,7 +600,7 @@ func setupChangelogCache() error {
needToSetupCache = true
break
case config.Ubuntu, config.Debian:
//TODO changelopg cache for RedHat, Oracle, Amazon, CentOS is not implemented yet.
//TODO changelog cache for RedHat, Oracle, Amazon, CentOS is not implemented yet.
if s.getServerInfo().Mode.IsDeep() {
needToSetupCache = true
}
@@ -637,11 +638,18 @@ func GetScanResults(scannedAt time.Time, timeoutSec int) (results models.ScanRes
return nil
}, timeoutSec)
for _, s := range servers {
if err = s.scanPorts(); err != nil {
util.Log.Errorf("Failed to scan Ports: %+v", err)
}
}
hostname, _ := os.Hostname()
ipv4s, ipv6s, err := util.IP()
if err != nil {
util.Log.Errorf("Failed to fetch scannedIPs. err: %+v", err)
}
for _, s := range append(servers, errServers...) {
r := s.convertToModel()
r.ScannedAt = scannedAt

View File

@@ -22,7 +22,8 @@ func isRunningKernel(pack models.Package, family string, kernel models.Kernel) (
return false, false
case config.RedHat, config.Oracle, config.CentOS, config.Amazon:
if pack.Name == "kernel" {
switch pack.Name {
case "kernel", "kernel-devel":
ver := fmt.Sprintf("%s-%s.%s", pack.Version, pack.Release, pack.Arch)
return true, kernel.Release == ver
}

View File

@@ -15,7 +15,7 @@ import (
formatter "github.com/kotakanbe/logrus-prefixed-formatter"
)
// Log for localhsot
// Log for localhost
var Log *logrus.Entry
func init() {
@@ -34,6 +34,10 @@ func NewCustomLogger(c config.ServerInfo) *logrus.Entry {
log.Level = logrus.DebugLevel
}
if flag.Lookup("test.v") != nil {
return logrus.NewEntry(log)
}
// File output
logDir := GetDefaultLogDir()
if 0 < len(config.Conf.LogDir) {
@@ -52,6 +56,7 @@ func NewCustomLogger(c config.ServerInfo) *logrus.Entry {
if file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644); err == nil {
log.Out = file
} else {
log.Out = os.Stderr
log.Errorf("Failed to create log file. path: %s, err: %s", logFile, err)
}
} else {
@@ -65,14 +70,18 @@ func NewCustomLogger(c config.ServerInfo) *logrus.Entry {
if _, err := os.Stat(logDir); err == nil {
path := filepath.Join(logDir, fmt.Sprintf("%s.log", whereami))
log.Hooks.Add(lfshook.NewHook(lfshook.PathMap{
logrus.DebugLevel: path,
logrus.InfoLevel: path,
logrus.WarnLevel: path,
logrus.ErrorLevel: path,
logrus.FatalLevel: path,
logrus.PanicLevel: path,
}, nil))
if _, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644); err == nil {
log.Hooks.Add(lfshook.NewHook(lfshook.PathMap{
logrus.DebugLevel: path,
logrus.InfoLevel: path,
logrus.WarnLevel: path,
logrus.ErrorLevel: path,
logrus.FatalLevel: path,
logrus.PanicLevel: path,
}, nil))
} else {
log.Errorf("Failed to create log file. path: %s, err: %s", path, err)
}
}
fields := logrus.Fields{"prefix": whereami}

View File

@@ -42,11 +42,11 @@ func AppendIfMissing(slice []string, s string) []string {
// URLPathJoin make URL
func URLPathJoin(baseURL string, paths ...string) (string, error) {
baseURL = strings.TrimSuffix(baseURL, "/")
trimedPaths := []string{}
trimmedPaths := []string{}
for _, path := range paths {
trimed := strings.Trim(path, " /")
if len(trimed) != 0 {
trimedPaths = append(trimedPaths, trimed)
trimmed := strings.Trim(path, " /")
if len(trimmed) != 0 {
trimmedPaths = append(trimmedPaths, trimmed)
}
}
var url *url.URL
@@ -54,7 +54,7 @@ func URLPathJoin(baseURL string, paths ...string) (string, error) {
if err != nil {
return "", err
}
url.Path += "/" + strings.Join(trimedPaths, "/")
url.Path += "/" + strings.Join(trimmedPaths, "/")
return url.String(), nil
}