69
README.md
69
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|
|
||||
|
||||
@@ -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{
|
||||
{
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 := `===============================================================================
|
||||
|
||||
Reference in New Issue
Block a user