Vulsのgo-cve-dictionaryを有効活用

VulsはOSSの脆弱性スキャンツールで、サーバ内のパッケージ情報等をチェックして、公開されている脆弱性情報に該当するものがないかを調べてくれるツールです。

このVulsの仕組みの中で、go-cve-dictionaryというのがあります。
これは、脆弱性情報の公開データをDBに取り込み管理するためのツールとなっています。

NVD、JVNのサイト上で公開されている情報をクローリングしてVulsで活用できる状態でDBに保存します。

このgo-cve-dictionaryを使ってみたので記録を残しておきます。

# go-cve-dictionaryのインストール

基本的にはこちらに記載の通りでOK。
https://github.com/kotakanbe/go-cve-dictionary

今回は簡易にSQLite3をDBとして利用しました。

CentOS上に以下の通り実施。(goの環境は既にある状態からスタートしています)

```
# export GOPATH=$HOME/go
# export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
```
PATHに$GOPATH/binを通し忘れていると、以下のmake install時にdepコマンドが見つからないとエラーになるので要注意。

```
# mkdir -p $GOPATH/src/github.com/kotakanbe
# cd $GOPATH/src/github.com/kotakanbe
# git clone https://github.com/kotakanbe/go-cve-dictionary.git
# cd go-cve-dictionary
# make install
```

```
# mkdir /var/log/vuls
# chmod 700 /var/log/vuls
```
これでgo-cve-dictionaryコマンドが実行できる状態になります。

# fetch処理

NVDの情報をFetchする処理を走らせてみます。
2002年から現在までの情報をfetchします。

```
for i in `seq 2002 $(date +"%Y")`; do go-cve-dictionary fetchnvd -http-proxy=http://HTTPプロキシURL -years $i; done
```

プロキシを介さない場合は-http-proxyのオプションは除いて実行。

これでしばらく待つとcve.sqlite3という700MB程のデータベースファイルが出来上がります。

## httpで情報取り出し

このDBの情報をHTTPリクエスト経由で取り出せるようWebサーバを起動します。

```
# go-cve-dictionary server
```

これでhttp://localhost:1323でサーバが起動し、DBから情報が取り出せるようになります。

## CVEのIDを元に取り出す方法
[CVE-2018-7716](https://nvd.nist.gov/vuln/detail/CVE-2018-7716)の情報

```shell-session

# curl http://127.0.0.1:1323/cves/CVE-2018-7716 |jq
{
  "CveID": "CVE-2018-7716",
  "Nvd": {
    "CveID": "CVE-2018-7716",
    "Summary": "PrivateVPN 2.0.31 for macOS suffers from a root privilege escalation vulnerability with its com.privat.vpn.helper privileged helper tool. This privileged helper tool implements an XPC service that allows arbitrary installed applications to connect and send messages. The XPC service extracts the config string from the corresponding XPC message. This string is supposed to point to an internal OpenVPN configuration file. If a new connection has not already been established, an attacker can send the XPC service a malicious XPC message with the config string pointing at an OpenVPN configuration file that he or she controls. In the configuration file, an attacker can specify a dynamic library plugin that should run for every new VPN connection. This plugin will execute code in the context of the root user.",
    "Score": 10,
    "AccessVector": "NETWORK",
    "AccessComplexity": "LOW",
    "Authentication": "NONE",
    "ConfidentialityImpact": "COMPLETE",
    "IntegrityImpact": "COMPLETE",
    "AvailabilityImpact": "COMPLETE",
    "Cpes": [],
    "CweID": "CWE-264",
    "References": [
      {
        "Source": "MISC",
        "Link": "https://github.com/VerSprite/research/edit/master/advisories/VS-2018-006.md"
      }
    ],
    "PublishedDate": "2018-03-05T18:29:00.41-05:00",
    "LastModifiedDate": "2018-03-18T10:10:08.78-04:00"
  },
  "Jvn": {
    "CveID": "",
    "Title": "",
    "Summary": "",
    "JvnLink": "",
    "JvnID": "",
    "Score": 0,
    "Severity": "",
    "Vector": "",
    "References": null,
    "Cpes": null,
    "PublishedDate": "0001-01-01T00:00:00Z",
    "LastModifiedDate": "0001-01-01T00:00:00Z"
  }
}
```

## CPEベースで検索して関連する情報を取り出す方法

例えば、Zabbixの3.0.0のバージョンに関連する脆弱性情報だけをピックアップしたい場合は以下のように実行

```shell-session

# curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"name": "cpe:/a:zabbix:zabbix:3.0.0"}' http://localhost:1323/cpes | jq "."
[
  {
    "CveID": "CVE-2016-10134",
    "Nvd": {
      "CveID": "CVE-2016-10134",
      "Summary": "SQL injection vulnerability in Zabbix before 2.2.14 and 3.0 before 3.0.4 allows remote attackers to execute arbitrary SQL commands via the toggle_ids array parameter in latest.php.",
      "Score": 7.5,
      "AccessVector": "NETWORK",
      "AccessComplexity": "LOW",
      "Authentication": "NONE",
      "ConfidentialityImpact": "PARTIAL",
      "IntegrityImpact": "PARTIAL",
      "AvailabilityImpact": "PARTIAL",
      "Cpes": [],
      "CweID": "CWE-89",
      "References": [
        {
          "Source": "DEBIAN",
          "Link": "http://www.debian.org/security/2017/dsa-3802"
        },
        {
          "Source": "MLIST",
          "Link": "http://www.openwall.com/lists/oss-security/2017/01/12/4"
        },
        {
          "Source": "MLIST",
          "Link": "http://www.openwall.com/lists/oss-security/2017/01/13/4"
        },
        {
          "Source": "BID",
          "Link": "http://www.securityfocus.com/bid/95423"
        },
        {
          "Source": "CONFIRM",
          "Link": "https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=850936"
        },
        {
          "Source": "MISC",
          "Link": "https://code610.blogspot.com/2017/10/zbx-11023-quick-autopsy.html"
        },
        {
          "Source": "CONFIRM",
          "Link": "https://support.zabbix.com/browse/ZBX-11023"
        }
      ],
      "PublishedDate": "2017-02-16T21:59:10.623-05:00",
      "LastModifiedDate": "2017-11-03T21:29:15.63-04:00"
    },
    "Jvn": {
      "CveID": "",
      "Title": "",
      "Summary": "",
      "JvnLink": "",
      "JvnID": "",
      "Score": 0,
      "Severity": "",
      "Vector": "",
      "References": null,
      "Cpes": null,
      "PublishedDate": "0001-01-01T00:00:00Z",
      "LastModifiedDate": "0001-01-01T00:00:00Z"
    }
  },
  {
    "CveID": "CVE-2016-4338",
    "Nvd": {
      "CveID": "CVE-2016-4338",
      "Summary": "The mysql user parameter configuration script (userparameter_mysql.conf) in the agent in Zabbix before 2.0.18, 2.2.x before 2.2.13, and 3.0.x before 3.0.3, when used with a shell other than bash, allows context-dependent attackers to execute arbitrary code or SQL commands via the mysql.size parameter.",
      "Score": 6.8,
      "AccessVector": "NETWORK",
      "AccessComplexity": "MEDIUM",
      "Authentication": "NONE",
      "ConfidentialityImpact": "PARTIAL",
      "IntegrityImpact": "PARTIAL",
      "AvailabilityImpact": "PARTIAL",
      "Cpes": [],
      "CweID": "CWE-89",
・・・略
```
CPE nameは完全一致で取得するしかなさそうです。

# DBの構造確認

DBの中身を直接確認してみます。

```shell-session
# sqplite3 cve.sqlite3
sqlite> .tables  
cpes         cve_details  jvns         nvds         references 

　先程のfetchnvdを実行した場合、nvdsに大量の情報が格納されています。
　スキーマは以下のような感じ。

sqlite> .schema nvds
CREATE TABLE "nvds" ("id" integer primary key autoincrement,"created_at" datetime,"updated_at" datetime,"deleted_at" datetime,"cve_detail_id" integer,"cve_id" varchar(255),"summary" varchar(4096),"score" real,"access_vector" varchar(255),"access_complexity" varchar(255),"authentication" varchar(255),"confidentiality_impact" varchar(255),"integrity_impact" varchar(255),"availability_impact" varchar(255),"cwe_id" varchar(255),"published_date" datetime,"last_modified_date" datetime );
CREATE INDEX idx_nvds_deleted_at ON "nvds"(deleted_at) ;
CREATE INDEX idx_nvds_cve_detail_id ON "nvds"(cve_detail_id) ;

　先程HTTPで確認したCVE-2018-7716の情報は以下。
sqlite> select * from nvds where cve_id = 'CVE-2018-7716';
103734|2018-03-22 17:21:08.567976282+09:00|2018-03-22 17:21:08.567976282+09:00||103734|CVE-2018-7716|PrivateVPN 2.0.31 for macOS suffers from a root privilege escalation vulnerability with its com.privat.vpn.helper privileged helper tool. This privileged helper tool implements an XPC service that allows arbitrary installed applications to connect and send messages. The XPC service extracts the config string from the corresponding XPC message. This string is supposed to point to an internal OpenVPN configuration file. If a new connection has not already been established, an attacker can send the XPC service a malicious XPC message with the config string pointing at an OpenVPN configuration file that he or she controls. In the configuration file, an attacker can specify a dynamic library plugin that should run for every new VPN connection. This plugin will execute code in the context of the root user.|10.0|NETWORK|LOW|NONE|COMPLETE|COMPLETE|COMPLETE|CWE-264|2018-03-05 18:29:00.41-05:00|2018-03-18 10:10:08.78-04:00

　このCVEに関連するCPEはcpesテーブルから情報が引っ張ってこれる。この例だと、pravatevpnの2.0.31に関する脆弱性だとわかる。

sqlite> select * from cpes where nvd_id = 103734;
2554941|2018-03-22 17:21:08.568139431+09:00|2018-03-22 17:21:08.568139431+09:00||0|103734|cpe:/a:privatevpn:privatevpn:2.0.31::~~~mac_os~~|a|privatevpn|privatevpn|2.0.31||~~~mac_os~~|

```

## ※注意
go-cve-dictionaryとは直接関係ないが、sqlite3でdbファイルに接続して直接データを確認しようとした際、
以下のエラーが発生。

```
Error: file is encrypted or is not a database
```

sqlite3のバージョンが3.6のクライアントを使ってアクセスしているのが原因だった模様。
3.7にUpdateすると解消された。
[参考](https://stackoverflow.com/questions/31209951/file-is-encrypted-or-is-not-a-database-sqlite)

# 更新情報のfetch処理

再度fetch処理を走らせると既に登録済みのものはパスされて更新情報だけ登録されるようです。
そのため、以下のような処理をcronとかで定期的に走らせて常時最新化しておくとよいと思います。

```
go-cve-dictionary fetchnvd -http-proxy=http://HTTPプロキシサーバ -last2y
```

# まとめ

この仕組みを使えば、自分で脆弱性情報をみに行かなくても情報の集約が簡単にできそうです。
情報の集約ができればいろいろと活用できる幅広がりそうですね。