The First Real Data Source

昨天決策鏈跑起來,我在文章裡寫得挺有信心的:每一列都說得出理由。
寫完才想到,引擎吃的那些 CVSS,是我自己打進 scanner.csv 的。
沒有來源,沒有取得日期,下次重跑也不保證一樣。排序說得出理由,但理由的源頭說不出來,那其實只是比較會講話而已。
所以今天接 NVD。
豆知識:NVD 是誰?
National Vulnerability Database,美國 NIST 維運。CVE 編號其實不是它發的——那是 MITRE 主持的 CVE Program 在做;NVD 負責後半段:補上 CVSS 分數、CWE 分類與受影響版本範圍。CVE 給漏洞一張身分證,NVD 幫它做體檢報告。你弱掃報告上的那個分數,多半輾轉來自這裡。

NVD 有公開 API,抓一筆 CVE 十來行就能動。麻煩的是三十天後、或 NVD 當掉的那天,這篇文章裡的數字還在不在。
所以快照除了存抽出來的欄位,也把原始回應整包留著。今天只讀 v3.1,但哪天要重新解讀同一份資料,欄位還在,不用再抓一次。順手記下來源網址和取得時間——CVSS 是會被重新評分的,retrieved_at 跟分數一樣重要。
預設也改成讀快照、不碰網路,--refresh 才重抓。
還有一條是從 Day 5 帶下來的:NVD 沒給 v3.1 分數時,回 None 標 UNKNOWN,不是 0.0。缺資料變成低分,比沒有資料更麻煩,因為它會安安靜靜混進排序裡。
取數失敗也分開處理。找不到是一回事,逾時和被限流是另一回事——前者是答案,後者只是還沒拿到答案。但兩種都不能當成「這個 CVE 沒風險」。
沒有 API key,NVD 限制三十秒五次,所以每抓一筆要等 6.5 秒。五個 CVE,我就坐在那邊看它一行一行吐出來。五筆全中,第二次重跑走快取,1.16 秒。
但有一行我看了兩次。

CVE-2022-41082,NVD 給 8.0。我在 Day 6 填的是 8.8。
第一反應是自己 parser 寫壞了、挑錯 metric。翻開快照對 vector 才發現,壞的是我:AV:A、PR:L——鄰接網路、需要低權限。我憑印象填的時候,腦袋裡想的是「網路可達、免權限」那一類。
所以差的不是 0.8 分。Attack Vector 是昨天 Effective Exposure 的輸入,我填錯的是利用條件,連帶錯掉的是後面整條推論。
昨天才說每一列都說得出理由,今天發現理由的源頭是我隨手打的。這個尷尬大概是今天最有用的產出。
只認 v3.1,而且優先拿 NVD 自己的 Primary 評分。v4.0 在 NVD 上是並存的,欄位結構也不一樣,那是明天的事。
真實分數現在還躺在快照裡,scanner.csv 的 8.8 我沒有改。改下去就得重算昨天的排序,而重算之前,得先有一個能同時容納 v3.1 和 v4.0 的模型。
快照也只是某個時間點的 NVD,不是永恆真理。
十二個測試全離線跑:重跑不碰網路、--refresh 才重抓、缺分數不變零、404 和 429 對到不同錯誤、限流會乖乖等。
Day 8|CVSS v3.1、v4.0 怎麼共存?
程式、快照與測試:github.com/oldgi/cve2action。CVE 與 CVSS 為 NVD 公開資料;資產與企業環境均為虛構。