5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

NVDのAPIを叩いて脆弱性情報を自動収集してみる

Posted at

背景

 私の勤めている会社では脆弱性の情報収集はメーリングリストベースのサービスを利用しているが、提供される形がテキストベースであり、自動化には即していない形となっていて効率化が難しい状態。脆弱性情報の収集自動化のための試みとして、NVDのAPIを叩いてCVE情報を自動取得する。
(もうやられている方いるのは知っていますが勉強のため自分でやる)

NVDのAPI

 NVDのデータを自動取得するための手段はNVD Data Feedsに記載されている。その中でAPIの情報はこちらにある。APIは主にCVEとCPEの2つが用意されている。共通プラットフォーム一覧CPE(Common Platform Enumeration)は脆弱性をさすものではないので、今回はCVEのAPIを利用する。

CVEのAPI

 CVEのAPIはhttps://nvd.nist.gov/developers/vulnerabilities にまとめられている。この中で用意されているAPIは2つ。

Retrieve a specific CVE

 個別のCVE番号の情報を取得するためのAPI。今回は脆弱性情報の収集を目的にしているため、こちらは使わない。

Retrieve a collection of CVE

 条件にマッチした範囲のCVEをjsonでまとめて返してくれるAPI。今回はこちらを使う。パラメータは以下の通り。(とりあえず自分が使うパラメータだけ記載)
パラメータはすべてGETで投げればよいらしい。

Parameter Description
apiKey APIキーなのだが、NVDのAPIの利用には必要とされていない。いつ使うんだろう。
pubStartDate CVEがリリースされた日で検索する際の、検索期間の開始日。これを設定すると後述のpubEndDateも必須になる。
pubEndDate CVEがリリースされた日で検索する際の、検索期間の終了日。これを設定すると前述のpubStartDateも必須になる。
resultsPerPage 1回のリクエストで返ってくるCVEの最大件数を設定する。デフォルトは20で最大は2000が設定される。
startIndex 検索を開始するインデックスを指定する。検索件数がresultsPerPageを超える場合に、2回目のリクエストで指定する。

サンプルスクリプト

 1日1回実行して新規に発行されたCVE情報を収集することをイメージして以下のサンプルスクリプトを作ってみた。検索範囲は日本時間でスクリプト実行の前日の中で発行されたCVEを検索する

nvd_apitest.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import requests
import json
import datetime

def callCvesApi(pubStartDate=None,pubEndDate=None,resultsPerPage=2000):
    url=u'https://services.nvd.nist.gov/rest/json/cves/1.0/'
    if pubStartDate==None or pubEndDate==None:
        now=datetime.datetime.now()
        pubStartDate=datetime.datetime(now.year,now.month,now.day-1,0,0,0)
        pubStartDate=datetime.datetime(now.year,now.month,now.day,0,0,0)
    pubStartDateStr=pubStartDate.sptftime('%Y-%m-%d 00:00:00 000 UTC+09:00')
    pubEndDateStr=pubEndDate.sptftime('%Y-%m-%d 00:00:00 000 UTC+09:00')
    urlstr=u'{0}?modStartDate={1}&modEndDate={2}'.format(url,pubStartDateStr,pubEndDateStr)
    response=requests.get(urlstr)
    values=json.loads(response.text)
    return values

if __name__ == '__main__':
    today_CVEs=callCvesApi()
    print(today_CVEs)

レスポンスは以下のようになる。レスポンスの見方はまた調べてまとめる。キーポイントあたりだけ//から始まるコメントを入れてます。

{
  'resultsPerPage': 3, //検索数
  'startIndex': 0,
  'totalResults': 3,
  'result': {
    'CVE_data_type': 'CVE',
    'CVE_data_format': 'MITRE',
    'CVE_data_version': '4.0',
    'CVE_data_timestamp': '2021-11-15T07:50Z',
    'CVE_Items': [{
      'cve': {
        'data_type': 'CVE',
        'data_format': 'MITRE',
        'data_version': '4.0',
        'CVE_data_meta': {
          'ID': 'CVE-2021-42739', //CVE番号 
          'ASSIGNER': 'cve@mitre.org'
        },
        'problemtype': {
          'problemtype_data': [{
            'description': [{
              'lang': 'en',
              'value': 'CWE-787'
            }]
          }]
        },
        'references': {
(中略(
        },
        'description': {
          'description_data': [{ //説明
            'lang': 'en',
            'value': 'The firewire subsystem in the Linux kernel through 5.14.13 has a buffer overflow related to drivers/media/firewire/firedtv-avc.c and drivers/media/firewire/firedtv-ci.c, because avc_ca_pmt mishandles bounds checking.'
          }]
        }
      },
      'configurations': {
        'CVE_data_version': '4.0',
        'nodes': [{
          'operator': 'OR',
          'children': [],
          'cpe_match': [{
            'vulnerable': True,
            'cpe23Uri': 'cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*', //脆弱性の対象プラットフォーム
            'versionEndIncluding': '5.14.13',
            'cpe_name': []
          }]
        }]
      },
      'impact': { //脆弱性のCVSS値等
        'baseMetricV3': {
          'cvssV3': {
            'version': '3.1',
            'vectorString': 'CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H',
            'attackVector': 'LOCAL',
            'attackComplexity': 'LOW',
            'privilegesRequired': 'LOW',
            'userInteraction': 'NONE',
            'scope': 'UNCHANGED',
            'confidentialityImpact': 'HIGH',
            'integrityImpact': 'HIGH',
            'availabilityImpact': 'HIGH',
            'baseScore': 7.8,
            'baseSeverity': 'HIGH'
          },
          'exploitabilityScore': 1.8,
          'impactScore': 5.9
        },
        'baseMetricV2': {
          'cvssV2': {
            'version': '2.0',
            'vectorString': 'AV:L/AC:L/Au:N/C:P/I:P/A:P',
            'accessVector': 'LOCAL',
            'accessComplexity': 'LOW',
            'authentication': 'NONE',
            'confidentialityImpact': 'PARTIAL',
            'integrityImpact': 'PARTIAL',
            'availabilityImpact': 'PARTIAL',
            'baseScore': 4.6
          },
          'severity': 'MEDIUM',
          'exploitabilityScore': 3.9,
          'impactScore': 6.4,
          'acInsufInfo': False,
          'obtainAllPrivilege': False,
          'obtainUserPrivilege': False,
          'obtainOtherPrivilege': False,
          'userInteractionRequired': False
        }
      },
      'publishedDate': '2021-10-20T07:15Z',
      'lastModifiedDate': '2021-11-14T06:15Z'
    }
(以下略)
5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?