Skip to content

Commit

Permalink
Integrate OWASP Dependency Check
Browse files Browse the repository at this point in the history
  • Loading branch information
kotakanbe committed Oct 27, 2016
1 parent 6f012fc commit b042a60
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 9 deletions.
25 changes: 25 additions & 0 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,31 @@ Vulsは、[CPE](https://nvd.nist.gov/cpe.cfm)に登録されているソフト
"cpe:/a:rubyonrails:ruby_on_rails:4.2.1",
]
```


# Usage: Integrate with OWASP Dependency Check to Automatic update when the libraries are updated (Experimental)
[OWASP Dependency check](https://www.owasp.org/index.php/OWASP_Dependency_Check) は、プログラミング言語のライブラリを特定し(CPEを推測)、公開済みの脆弱性を検知するツール。

VulsとDependency Checkを連携させる方法は以下
- Dependency Checkを、--format=XMLをつけて実行する
- そのXMLをconfig.toml内で以下のように定義する

```
[servers]
[servers.172-31-4-82]
host = "172.31.4.82"
user = "ec2-user"
keyPath = "/home/username/.ssh/id_rsa"
dependencyCheckXMLPath = "/tmp/dependency-check-report.xml"
```
VulsとDependency Checkの連携すると以下の利点がある
- ライブラリを更新した場合に、config.tomlのCPEの定義を変更しなくても良い
- Vulsの機能でSlack, Emailで通知可能
- 日本語のレポートが可能
- Dependency Checkは日本語レポートに対応していない
# Usage: Scan Docker containers
Expand Down
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ optional = [

----

# Usage: Scan vulnerability of non-OS package
# Usage: Scan vulnerabilites of non-OS packages

It is possible to detect vulnerabilities in non-OS packages, such as something you compiled by yourself, language libraries and frameworks, that have been registered in the [CPE](https://nvd.nist.gov/cpe.cfm).

Expand All @@ -890,6 +890,30 @@ To detect the vulnerability of Ruby on Rails v4.2.1, cpeNames needs to be set in
"cpe:/a:rubyonrails:ruby_on_rails:4.2.1",
]
```

# Usage: Integrate with OWASP Dependency Check to Automatic update when the libraries are updated (Experimental)
[OWASP Dependency check](https://www.owasp.org/index.php/OWASP_Dependency_Check) is a utility that identifies project dependencies and checks if there are any known, publicly disclosed, vulnerabilities.

Benefit of integrating Vuls And OWASP Dependency Check is below.
- Automatic Update of Vuls config when the libraries are updated.
- Reporting by Email or Slack by using Vuls.
- Reporting in Japanese
- OWASP Dependency Check supports only English

How to integrate Vuls with OWASP Dependency Check
- Execute OWASP Dependency Check with --format=XML option.
- Define the xml file path of dependency check in config.toml.

```
[servers]
[servers.172-31-4-82]
host = "172.31.4.82"
user = "ec2-user"
keyPath = "/home/username/.ssh/id_rsa"
dependencyCheckXMLPath = "/tmp/dependency-check-report.xml"
```
# Usage: Scan Docker containers
Expand Down
2 changes: 2 additions & 0 deletions commands/discover.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ subjectPrefix = "[vuls]"
#cpeNames = [
# "cpe:/a:rubyonrails:ruby_on_rails:4.2.1",
#]
#dependencyCheckXMLPath = "/tmp/dependency-check-report.xml"
#containers = ["${running}"]
#ignoreCves = ["CVE-2014-6271"]
#optional = [
Expand All @@ -132,6 +133,7 @@ host = "{{$ip}}"
#cpeNames = [
# "cpe:/a:rubyonrails:ruby_on_rails:4.2.1",
#]
#dependencyCheckXMLPath = "/tmp/dependency-check-report.xml"
#containers = ["${running}"]
#ignoreCves = ["CVE-2014-0160"]
#optional = [
Expand Down
4 changes: 3 additions & 1 deletion commands/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/future-architect/vuls/scan"
"github.com/future-architect/vuls/util"
"github.com/google/subcommands"
"github.com/k0kubun/pp"
"golang.org/x/net/context"
)

Expand Down Expand Up @@ -245,6 +246,7 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
return subcommands.ExitFailure
}

c.Conf.Debug = p.debug
err = c.Load(p.configPath, keyPass)
if err != nil {
logrus.Errorf("Error loading %s, %s", p.configPath, err)
Expand Down Expand Up @@ -295,9 +297,9 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
if 0 < len(servernames) {
c.Conf.Servers = target
}
logrus.Debugf("%s", pp.Sprintf("%v", target))

c.Conf.Lang = p.lang
c.Conf.Debug = p.debug
c.Conf.DebugSQL = p.debugSQL

// logger
Expand Down
4 changes: 2 additions & 2 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,6 @@ type SlackConf struct {

// Validate validates configuration
func (c *SlackConf) Validate() (errs []error) {

if !c.UseThisTime {
return
}
Expand Down Expand Up @@ -228,7 +227,8 @@ type ServerInfo struct {
KeyPath string
KeyPassword string

CpeNames []string
CpeNames []string
DependencyCheckXMLPath string

// Container Names or IDs
Containers []string
Expand Down
29 changes: 24 additions & 5 deletions config/tomlloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,19 @@ import (

"github.com/BurntSushi/toml"
log "github.com/Sirupsen/logrus"
"github.com/k0kubun/pp"
"github.com/future-architect/vuls/contrib/owasp-dependency-check/parser"
)

// TOMLLoader loads config
type TOMLLoader struct {
}

// Load load the configuraiton TOML file specified by path arg.
func (c TOMLLoader) Load(pathToToml, keyPass string) (err error) {
func (c TOMLLoader) Load(pathToToml, keyPass string) error {
if Conf.Debug {
log.SetLevel(log.DebugLevel)
}

var conf Config
if _, err := toml.DecodeFile(pathToToml, &conf); err != nil {
log.Error("Load config failed", err)
Expand Down Expand Up @@ -102,6 +106,23 @@ func (c TOMLLoader) Load(pathToToml, keyPass string) (err error) {
s.CpeNames = d.CpeNames
}

s.DependencyCheckXMLPath = v.DependencyCheckXMLPath
if len(s.DependencyCheckXMLPath) == 0 {
s.DependencyCheckXMLPath = d.DependencyCheckXMLPath
}

// Load CPEs from OWASP Dependency Check XML
if len(s.DependencyCheckXMLPath) != 0 {
cpes, err := parser.Parse(s.DependencyCheckXMLPath)
if err != nil {
return fmt.Errorf(
"Failed to read OWASP Dependency Check XML: %s", err)
}
log.Infof("Loaded from OWASP Dependency Check XML: %s",
s.ServerName)
s.CpeNames = append(s.CpeNames, cpes...)
}

s.Containers = v.Containers
if len(s.Containers) == 0 {
s.Containers = d.Containers
Expand Down Expand Up @@ -140,8 +161,6 @@ func (c TOMLLoader) Load(pathToToml, keyPass string) (err error) {

servers[name] = s
}
log.Debug("Config loaded")
log.Debugf("%s", pp.Sprintf("%v", servers))
Conf.Servers = servers
return
return nil
}
64 changes: 64 additions & 0 deletions contrib/owasp-dependency-check/parser/parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package parser

import (
"encoding/xml"
"fmt"
"io/ioutil"
"os"
"sort"
"strings"
)

type analysis struct {
Dependencies []dependency `xml:"dependencies>dependency"`
}

type dependency struct {
Identifiers []identifier `xml:"identifiers>identifier"`
}

type identifier struct {
Name string `xml:"name"`
Type string `xml:"type,attr"`
}

func appendIfMissing(slice []string, str string) []string {
for _, s := range slice {
if s == str {
return slice
}
}
return append(slice, str)
}

// Parse parses XML and collect list of cpe
func Parse(path string) ([]string, error) {
file, err := os.Open(path)
if err != nil {
return []string{}, fmt.Errorf("Failed to open: %s", err)
}
defer file.Close()

b, err := ioutil.ReadAll(file)
if err != nil {
return []string{}, fmt.Errorf("Failed to read: %s", err)
}

var anal analysis
if err := xml.Unmarshal(b, &anal); err != nil {
fmt.Errorf("Failed to unmarshal: %s", err)
}

cpes := []string{}
for _, d := range anal.Dependencies {
for _, ident := range d.Identifiers {
if ident.Type == "cpe" {
name := strings.TrimPrefix(ident.Name, "(")
name = strings.TrimSuffix(name, ")")
cpes = appendIfMissing(cpes, name)
}
}
}
sort.Strings(cpes)
return cpes, nil
}

0 comments on commit b042a60

Please sign in to comment.