diff --git a/README.md b/README.md index 8ebf20e9..eaae1c47 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Vuls is a tool created to solve the problems listed above. It has the following # Main Features - Scan for any vulnerabilities in Linux/FreeBSD Server - - Supports Ubuntu, Debian, CentOS, Amazon Linux, RHEL, FreeBSD and Raspbian + - Supports Ubuntu, Debian, CentOS, Amazon Linux, RHEL, Oracle Linux, FreeBSD and Raspbian - Cloud, on-premise, Docker - Scan middleware that are not included in OS package management - Scan middleware, programming language libraries and framework for vulnerability @@ -361,15 +361,16 @@ Scan speed is fast and resource usage is light. - On Amazon, RHEL and FreeBSD High speed scan and resource usage is light because Vuls can get CVE IDs by using package manager(no need to parse a changelog). -| Distribution| Scan Speed | -|:------------|:-------------------| -| Ubuntu | First time: Slow / From the second time: Fast | -| Debian | First time: Slow / From the second time: Fast | -| CentOS | Fast | -| Amazon | Fast | -| RHEL | Fast | -| FreeBSD | Fast | -| Raspbian | First time: Slow / From the second time: Fast | +| Distribution | Scan Speed | +|:-------------|:-------------------| +| Ubuntu | First time: Slow / From the second time: Fast | +| Debian | First time: Slow / From the second time: Fast | +| CentOS | Fast | +| Amazon | Fast | +| RHEL | Fast | +| Oracle Linux | Fast | +| FreeBSD | Fast | +| Raspbian | First time: Slow / From the second time: Fast | ---- @@ -393,15 +394,16 @@ If there is a staging environment with the same configuration as the production # Support OS -| Distribution| Release | -|:------------|-------------------:| -| Ubuntu | 12, 14, 16| -| Debian | 7, 8| -| RHEL | 5, 6, 7| -| CentOS | 6, 7| -| Amazon Linux| All| -| FreeBSD | 10, 11| -| Raspbian | Wheezy, Jessie | +| Distribution | Release | +|:-------------|-------------------:| +| Ubuntu | 12, 14, 16| +| Debian | 7, 8| +| RHEL | 5, 6, 7| +| Oracle Linux | 5, 6, 7| +| CentOS | 6, 7| +| Amazon Linux | All| +| FreeBSD | 10, 11| +| Raspbian | Wheezy, Jessie | ---- @@ -623,16 +625,18 @@ The configtest subcommand checks the following In order to scan, the following dependencies are required, so you need to install them manually or with tools such as Ansible. -| Distribution| Release | Requirements | -|:------------|-------------------:|:-------------| -| Ubuntu | 12, 14, 16| - | -| Debian | 7, 8| aptitude | -| CentOS | 6, 7| yum-plugin-changelog | -| Amazon | All | - | -| RHEL | 5 | yum-security | -| RHEL | 6, 7 | - | -| FreeBSD | 10 | - | -| Raspbian | Wheezy, Jessie | - | +| Distribution | Release | Requirements | +|:-------------|-------------------:|:-------------| +| Ubuntu | 12, 14, 16| - | +| Debian | 7, 8| aptitude | +| CentOS | 6, 7| yum-plugin-changelog | +| Amazon | All | - | +| RHEL | 5 | yum-security | +| RHEL | 6, 7 | - | +| Oracle Linux | 5 | yum-security | +| Oracle Linux | 6, 7 | - | +| FreeBSD | 10 | - | +| Raspbian | Wheezy, Jessie | - | ## Check /etc/sudoers @@ -646,13 +650,13 @@ vuls ALL=(ALL) NOPASSWD:/usr/bin/yum --changelog --assumeno update * Defaults:vuls env_keep="http_proxy https_proxy HTTP_PROXY HTTPS_PROXY" ``` -- RHEL 5 +- RHEL 5 / Oracle Linux 5 ``` vuls ALL=(ALL) NOPASSWD:/usr/bin/yum --color=never repolist, /usr/bin/yum --color=never list-security --security, /usr/bin/yum --color=never check-update, /usr/bin/yum --color=never info-security Defaults:vuls env_keep="http_proxy https_proxy HTTP_PROXY HTTPS_PROXY" ``` -- RHEL 6, 7 +- RHEL 6, 7 / Oracle Linux 6, 7 ``` vuls ALL=(ALL) NOPASSWD:/usr/bin/yum --color=never repolist, /usr/bin/yum --color=never --security updateinfo list updates, /usr/bin/yum --color=never check-update, /usr/bin/yum --color=never --security updateinfo updates Defaults:vuls env_keep="http_proxy https_proxy HTTP_PROXY HTTPS_PROXY" @@ -1033,6 +1037,7 @@ Confidence 100 / YumUpdateSecurityMatch - `CWE` means [CWE - Common Weakness Enumeration](https://nvd.nist.gov/cwe.cfm) of the CVE. - `NVD` `MITRE` `CVE Details` `CVSS Caluculator` - `RHEL-CVE` means the URL of OS distributor support. +- `Oracle-CVE` means the URL of the Oracle Linux errata information. - `Package` shows the package version information including this vulnerability. - `Confidence` means the reliability of detection. - `100` is highly reliable @@ -1041,7 +1046,7 @@ Confidence 100 / YumUpdateSecurityMatch | Detection Method | Confidence | OS |Description| |:-----------------------|-------------------:|:---------------------------------|:--| - | YumUpdateSecurityMatch | 100 | RHEL, Amazon Linux |Detection using yum-plugin-security| + | YumUpdateSecurityMatch | 100 | RHEL, Oracle Linux, Amazon Linux |Detection using yum-plugin-security| | ChangelogExactMatch | 95 | CentOS, Ubuntu, Debian, Raspbian |Exact version match between changelog and package version| | ChangelogLenientMatch | 50 | Ubuntu, Debian, Raspbian |Lenient version match between changelog and package version| | PkgAuditMatch | 100 | FreeBSD |Detection using pkg audit| diff --git a/report/util.go b/report/util.go index 872e0e46..dd075e10 100644 --- a/report/util.go +++ b/report/util.go @@ -393,6 +393,21 @@ func distroLinks(cveInfo models.CveInfo, osFamily string) []distroLink { }) } return links + case "oraclelinux": + links := []distroLink{ + { + "Oracle-CVE", + fmt.Sprintf(oracleSecurityBaseURL, cveID), + }, + } + for _, advisory := range cveInfo.DistroAdvisories { + links = append(links, distroLink{ + // "Oracle-ELSA" + advisory.AdvisoryID, + fmt.Sprintf(oracleELSABaseBaseURL, advisory.AdvisoryID), + }) + } + return links case "amazon": links := []distroLink{ { diff --git a/report/writer.go b/report/writer.go index 9f7e1dce..28111943 100644 --- a/report/writer.go +++ b/report/writer.go @@ -33,6 +33,8 @@ const ( redhatSecurityBaseURL = "https://access.redhat.com/security/cve" redhatRHSABaseBaseURL = "https://rhn.redhat.com/errata/%s.html" amazonSecurityBaseURL = "https://alas.aws.amazon.com/%s.html" + oracleSecurityBaseURL = "https://linux.oracle.com/cve/%s.html" + oracleELSABaseBaseURL = "https://linux.oracle.com/errata/%s.html" ubuntuSecurityBaseURL = "http://people.ubuntu.com/~ubuntu-security/cve" debianTrackerBaseURL = "https://security-tracker.debian.org/tracker" diff --git a/scan/redhat.go b/scan/redhat.go index c5faae58..4214f341 100644 --- a/scan/redhat.go +++ b/scan/redhat.go @@ -54,6 +54,23 @@ func detectRedhat(c config.ServerInfo) (itsMe bool, red osTypeInterface) { return true, red } + if r := exec(c, "ls /etc/oracle-release", noSudo); r.isSuccess() { + // Need to discover Oracle Linux first, because it provides an + // /etc/redhat-release that matches the upstream distribution + if r := exec(c, "cat /etc/oracle-release", noSudo); r.isSuccess() { + re := regexp.MustCompile(`(.*) release (\d[\d.]*)`) + result := re.FindStringSubmatch(strings.TrimSpace(r.Stdout)) + if len(result) != 3 { + util.Log.Warn("Failed to parse Oracle Linux version: %s", r) + return true, red + } + + release := result[2] + red.setDistro("oraclelinux", release) + return true, red + } + } + if r := exec(c, "ls /etc/redhat-release", noSudo); r.isSuccess() { // https://www.rackaid.com/blog/how-to-determine-centos-or-red-hat-version/ // e.g. @@ -115,7 +132,7 @@ func (o *redhat) checkIfSudoNoPasswd() error { {"yum --changelog --assumeno update yum", []int{0, 1}}, } - case "rhel": + case "rhel", "oraclelinux": majorVersion, err := o.Distro.MajorVersion() if err != nil { return fmt.Errorf("Not implemented yet: %s, err: %s", o.Distro, err) @@ -187,7 +204,7 @@ func (o *redhat) checkDependencies() error { switch o.Distro.Family { case "centos": packName = "yum-plugin-changelog" - case "rhel": + case "rhel", "oraclelinux": if majorVersion < 6 { packName = "yum-security" } else { @@ -265,7 +282,7 @@ func (o *redhat) parseScannedPackagesLine(line string) (models.PackageInfo, erro func (o *redhat) scanVulnInfos() ([]models.VulnInfo, error) { if o.Distro.Family != "centos" { - // Amazon, RHEL has yum updateinfo as default + // Amazon, RHEL, Oracle Linux has yum updateinfo as default // yum updateinfo can collenct vendor advisory information. return o.scanUnsecurePackagesUsingYumPluginSecurity() } @@ -608,7 +625,7 @@ type distroAdvisoryCveIDs struct { } // Scaning unsecure packages using yum-plugin-security. -// Amazon, RHEL +// Amazon, RHEL, Oracle Linux func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos, error) { if o.Distro.Family == "centos" { // CentOS has no security channel. @@ -623,13 +640,13 @@ func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos, return nil, fmt.Errorf("Failed to SSH: %s", r) } - // get advisoryID(RHSA, ALAS) - package name,version + // get advisoryID(RHSA, ALAS, ELSA) - package name,version major, err := (o.Distro.MajorVersion()) if err != nil { return nil, fmt.Errorf("Not implemented yet: %s, err: %s", o.Distro, err) } - if o.Distro.Family == "rhel" && major == 5 { + if (o.Distro.Family == "rhel" || o.Distro.Family == "oraclelinux") && major == 5 { cmd = "yum --color=never list-security --security" } else { cmd = "yum --color=never --security updateinfo list updates" @@ -671,8 +688,8 @@ func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos, dict[advIDPackNames.AdvisoryID] = packInfoList } - // get advisoryID(RHSA, ALAS) - CVE IDs - if o.Distro.Family == "rhel" && major == 5 { + // get advisoryID(RHSA, ALAS, ELSA) - CVE IDs + if (o.Distro.Family == "rhel" || o.Distro.Family == "oraclelinux") && major == 5 { cmd = "yum --color=never info-security" } else { cmd = "yum --color=never --security updateinfo updates" @@ -772,7 +789,7 @@ func (o *redhat) parseYumUpdateinfo(stdout string) (result []distroAdvisoryCveID // So use yum check-update && parse changelog return result, fmt.Errorf( "yum updateinfo is not suppported on CentOS") - case "rhel", "amazon": + case "rhel", "amazon", "oraclelinux": // nop } @@ -933,14 +950,15 @@ func (o *redhat) extractPackNameVerRel(nameVerRel string) (name, ver, rel string return } -// parseYumUpdateinfoListAvailable collect AdvisorID(RHSA, ALAS), packages +// parseYumUpdateinfoListAvailable collect AdvisorID(RHSA, ALAS, ELSA), packages func (o *redhat) parseYumUpdateinfoListAvailable(stdout string) (advisoryIDPacksList, error) { result := []advisoryIDPacks{} lines := strings.Split(stdout, "\n") for _, line := range lines { if !(strings.HasPrefix(line, "RHSA") || - strings.HasPrefix(line, "ALAS")) { + strings.HasPrefix(line, "ALAS") || + strings.HasPrefix(line, "ELSA")) { continue } diff --git a/scan/redhat_test.go b/scan/redhat_test.go index f43c7d46..16097892 100644 --- a/scan/redhat_test.go +++ b/scan/redhat_test.go @@ -344,6 +344,111 @@ func TestParseYumUpdateinfoToGetSeverity(t *testing.T) { } } +func TestParseYumUpdateinfoOL(t *testing.T) { + stdout := `=============================================================================== + bind security update +=============================================================================== + Update ID : ELSA-2017-0276 + Release : Oracle Linux 7 + Type : security + Status : final + Issued : 2017-02-15 + CVEs : CVE-2017-3135 +Description : [32:9.9.4-38.2] + : - Fix CVE-2017-3135 (ISC change 4557) + : - Fix and test caching CNAME before DNAME (ISC + : change 4558) + Severity : Moderate + +=============================================================================== + openssl security update +=============================================================================== + Update ID : ELSA-2017-0286 + Release : Oracle Linux 7 + Type : security + Status : final + Issued : 2017-02-15 + CVEs : CVE-2016-8610 + : CVE-2017-3731 +Description : [1.0.1e-48.4] + : - fix CVE-2017-3731 - DoS via truncated packets + : with RC4-MD5 cipher + : - fix CVE-2016-8610 - DoS of single-threaded + : servers via excessive alerts + Severity : Moderate + +=============================================================================== + Unbreakable Enterprise kernel security update +=============================================================================== + Update ID : ELSA-2017-3520 + Release : Oracle Linux 7 + Type : security + Status : final + Issued : 2017-02-15 + CVEs : CVE-2017-6074 +Description : kernel-uek + : [4.1.12-61.1.28] + : - dccp: fix freeing skb too early for + : IPV6_RECVPKTINFO (Andrey Konovalov) [Orabug: + : 25598257] {CVE-2017-6074} + Severity : Important + + ` + issued, _ := time.Parse("2006-01-02", "2017-02-15") + + r := newRedhat(config.ServerInfo{}) + r.Distro = config.Distro{Family: "oraclelinux"} + + var tests = []struct { + in string + out []distroAdvisoryCveIDs + }{ + { + stdout, + []distroAdvisoryCveIDs{ + { + DistroAdvisory: models.DistroAdvisory{ + AdvisoryID: "ELSA-2017-0276", + Severity: "Moderate", + Issued: issued, + }, + CveIDs: []string{"CVE-2017-3135"}, + }, + { + DistroAdvisory: models.DistroAdvisory{ + AdvisoryID: "ELSA-2017-0286", + Severity: "Moderate", + Issued: issued, + }, + CveIDs: []string{ + "CVE-2016-8610", + "CVE-2017-3731", + }, + }, + { + DistroAdvisory: models.DistroAdvisory{ + AdvisoryID: "ELSA-2017-3520", + Severity: "Important", + Issued: issued, + }, + CveIDs: []string{"CVE-2017-6074"}, + }, + }, + }, + } + for _, tt := range tests { + actual, _ := r.parseYumUpdateinfo(tt.in) + for i, advisoryCveIDs := range actual { + if !reflect.DeepEqual(tt.out[i], advisoryCveIDs) { + e := pp.Sprintf("%v", tt.out[i]) + a := pp.Sprintf("%v", advisoryCveIDs) + t.Errorf("[%d] Alas is not same. \nexpected: %s\nactual: %s", + i, e, a) + } + } + } +} + func TestParseYumUpdateinfoRHEL(t *testing.T) { stdout := `===============================================================================