CVE情報検索色々 @2023春

# 脆弱性調査再び

久方ぶりに脆弱性関連の調査をすることになりまして。

今回は自分が面倒を見ているシステムが使っているソフトに残留している脆弱性一覧を引っこ抜くのが目的。

「考える前にアップデートすりゃいいじゃん」が基本指針なのですが、まぁ、いろいろなケースがあります。
NVDやJVNと格闘するのも数年ぶりですので、勉強し直しながらやっていこうかと思います。

脆弱性情報は基本全数ダウンロードさせてもらえるので、それを手元でアレコレする方針で考えます。

## 脱線。　そもそも今回の調査はサイト上の検索機能でうまいことできないの？

ちょっと微妙です。
実はNVDはバージョンまで指定していい感じに検索はできるのですが、、結果を一括でダウンロードするということが残念ながらできません。
（JVNはそもそバージョン指定の検索はさせてくれません、、）

https://nvd.nist.gov/vuln/search

![20230414_19h26m06s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/dde645e0-26ed-e638-6a86-952ec4c66b71.png)

![20230414_19h30m01s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/8ac03400-e300-dabf-f3fe-5b8274262833.png)

スナップショットがうまく取れていないのですが、VendorとProductのところに書き込むと予測変換でCPEを出してくれます。
CPEの採番は結構クセがあり、同じ製品っぽいもので複数選択肢があったりするので、CVEベースで検索してそちらのページに書いてあるCPE情報を調べて使っていく感じでしょうか。

急ぎの調査なら割り切ってこの方法で検索して手でコピペしてまとめますが、今回はもうちょっと調べてみようかなと思います。

## 脱線２。　そういうことするツールないの？

実は、最終的には、vulsに落ち着きます。
https://github.com/future-architect/vuls/blob/master/README.md
当初vulsがCPEベースで脆弱性の検索できることを知らず、パッケージで入れてないツールが今回の調査のメインであったこともあり、最初の段階で除外しちゃってました。

また、途中段階でcve-searchというツールも試していたのですが、細かい機能使ってくうちにコードにバグを見つけ、changelogを見るも去年でStopしており、使用するのを取りやめました。
（pipのrequirements.txtから該当するCVEを引き抜くオプションがあるのですが、内部的にdictの処理間違えてるし、バージョン文字列の考慮が不十分で機能しないんですよね、、dictのところは簡単に直せるのですが、バージョンの考慮は根が深い。。）
https://github.com/cve-search/cve-search

と、言うのは後出しの話。
こういうツールがあることに気が付かず調べものしながら書いてた記述があるので、せっかくなので整形して残しておきます。


# 脆弱性情報のソース

## NVD, JVN, Redhat, etc,,

自分の脳内の再整理の意味で。
- 脆弱性の採番や採点のルールは米国のMITRE社が定めている
- 実際の採番（CVE-XXXX-XXXXXX）のは、MITREが指名したソフトやハードウェアの大手ベンダやCERT（がさらに指名した子供や孫）が実施する。
- 採点は、有志が行う。

採点について、しないベンダ、自社の分はバッチリ計算するベンダ（Oracleとか）、基本CVEがついたものは全部計算してくれる団体などがあります。
点数付きでCSVを公開してくれている団体は、米国NISTのNVD、日本だとJPCERTとIPAのJVNとか。
おそらく他にもあるのだと思うのですが、、大体この２つで足りるので、他は調べたことないです。
あとは、自分のディストリで採用しているソフトに限る感じですが、RedhatやUbuntuなどでしょうか。

どれもCVE情報の一覧をダウンロードまでさせてくれるので、こういう調査の際は非常にありがたいサイトです。

NVD
https://nvd.nist.gov/search
https://nvd.nist.gov/vuln/data-feeds#APIS

JVN
https://jvndb.jvn.jp/search/index.php?mode=_vulnerability_search_IA_VulnSearch&lang=ja
https://jvndb.jvn.jp/ja/feed/

Redhat
https://access.redhat.com/security/security-updates/cve
https://access.redhat.com/documentation/en-us/red_hat_security_data_api/1.0/html/red_hat_security_data_api/overview

Ubuntu
https://ubuntu.com/security/cves
https://ubuntu.com/security/api/docs#/

ちなみに、検索画面があるけどデータの一括ダウンロードはできないのかな、、？という時は、datafeedやapiでサイト内検索すると結構ヒットする感じがあります。

## 掲載されている情報の違い

### 情報のくくり方

CVE番号は一緒ですが、概要説明は各団体でバラバラです。
情報のくくり方もバラバラ。

NVDは1CVE1件。
JVNはJVNDB-YYYY-NNNNNNという番号を付与しており、製品の脆弱性公開やパッチごとにまとめている感じです。
Redhatは詳細をまとめているRHSA-YYYY:NNNNという番号を付与したものと、CVE番号単位の情報の2面で情報まとめてくれてます。
UbuntuもUSN-NNNN-NとCVE単位の2面管理。

実際に危険度判断しようとしたり、対処考える際には、結局は各ソフトの実際の開発者の発信している情報を見に行くことになるので、人間が見る分にはくくり方の違いは対して問題になりません。
ただし、データをダウンロードしてきてアレコレしようとすると、めんどくさい。。
CVEが一意識別市になるように整形してやる必要があります。

### CVSS（採点結果）

CVSSは計算式はガッツリ固まっているのですが、その中に入れる変数の決め方が「高中低」の3段階だったりするので、団体によって線引きが揺らぎます。
https://www.ipa.go.jp/security/vuln/scap/cvss.html

まぁ、自身の経験上ここの点数のブレで大きな問題になったケースは思いつきませんし、あまり気にしなくていいかなと思ってます。

### データフォーマット

JVNはxml、NVDはjson/xmlどっちもOK、RedhatとUbuntuはjsonのみ。
（ただし、NVDはjsonでは複数のkeyで細分化して書いてくれている情報が、xmlだとTEXTベタうちで１つのタグにまとめられてしまっているので、かなり使いにくくなるので要注意ですが。。）

書式はパーサーをかませれば大体どれれも同じなので別にいいのですが、各要素の名前や階層構造は結構バラバラですので、どのソース使うかでカスタマイズしてやる必要があります。
そのカスタマイズは大した手間ではないのですが、結構大きな差異として、CPEの表記の違いがあります。

CPEはソフトウェアとバージョンをセットで一意に表現する記法。
https://www.ipa.go.jp/security/vuln/scap/cpe.html

で、今回の用途的に「自分が使ってるソフトとそのバージョンに存在する脆弱性」を引っこ抜くことなので、このCPEの情報ベースで検索をかけていくことになるのですが、、
バージョンの記載方法自体がソフトによってバラバラなので、単純に大小比較ってできないんですよね。。
また、同じソフトのはずなのに複数の表記方法があることも。。
さておき、このCPEをどう書いてくれているかはすごく重要になるわけです。

それぞれ比較してみると、こんな感じになります。
試しにCVE-2022-29885(Apache Tomcat)をみてみると、こんな。

NVD
![20230414_15h45m51s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/92c37e47-9022-5fa7-bdc4-d6ef9c5c73c2.png)

JVN
![20230414_15h48m20s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/5844213a-50e3-2a67-0525-919665a24f00.png)

NVDは、該当するバージョンを全部列挙してくれています。
（実はそうでもないケースもあり、もうもう一捻りしてやらないといけないのですが、それは後述）

一方JVNは、フリーフォーマットで「バージョンXX〜YY」という書き方。
ソースになっている開発ベンダ自体の情報開示方法自体がJVNのような書き方になっているのは事実なのですが、これだとスクリプトで該当バージョン引っ掛けるのがものすごく難しいです。。。
今回は日本語で結果まとめられる方がいいのでJVNを使おうと思っていたのですが、CPEの記載粒度の観点で見送り。
人手間かかりますが、NVDで引っ掛けてから、cveの番号で紐付けてJVNの情報引き抜くかなぁ、、

#### CPEにもう一捻り

NVDはCPEのバージョン情報を細かく書いてくれる、、ように見えるのですが、ダウンロードしてきた情報だともう一捻り必要です。
先程のCVE-2-22-29885のCVE検索画面をよくよく見ると、CPEの右にFromとUp toの枠があるものがあります。
で、表示の下に「Show Matching CPE(s) 」があり、これを開いてみると、、、

![20230414_20h19m27s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/a73ec30e-552c-c7d5-4a89-b1414bdf14c5.png)

たくさん出てきます。

なのですが、CVE情報としてダウンロードしてくる nvdcve-1.1-2022.jsonには以下のように、\*だらけのCPEとFrom,Toの情報は入っているのですが、展開後の各個のapache:tomcat:10.0.0:milestone10:*:*:*:*:*:*などのリストは入っていません。

![20230414_20h23m26s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/a66a8b5a-b7e5-948c-2c30-9e130d40fd52.png)

じゃぁこの情報はどこから来ているかというと、CVEをダウンロードしてくるページに CPE Match Feed というjsonがおいてあり、この中に入っています。
https://nvd.nist.gov/vuln/data-feeds#cpeMatch

今回の用途的にあるソフトのあるバージョンが影響を受けるCVEを特定する必要があるので、CVEデータと上記のCPE Matchをと都合してCVEの影響対象CPEリストを作り、それと検索条件のソフト＋バージョンに該当するCPEと照合する、という処理が必要になります。

。。。NVDで手で検索してまとめたほうが楽な気が早くもしてきましたが、、、まぁ、、、がんばりますか。。


# NVDの情報ベースでの検索スクリプト

## 基本的な作り

やらないといけないことが結構たくさんあります。

### 1. 検索したいソフト名とバージョンをCPEに変換する

初っ端から結構厄介だったりします。
CPEはベンダ名、ソフト名、バージョンの３つから構成されるのですが、、、
例えばelasticsearchだと、ベンダ名がelasticとelasticsearchとどっちもあるんですよね、、

![20230414_20h56m41s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/c20002bb-4d6f-c11f-eb03-833bd1d6b4e0.png)

![20230414_21h01m52s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/45f5dd67-284d-c110-24ed-0bcb927af545.png)

最近のバージョンは皆elasticを使っているようなのですが、こういうのがポロポロあるんです。。

予測変換というわけではないですが、ソフトやベンダ名の一部をタイプすると該当しそうなCPEをリストアップさせる機能を作るなどしないといけません。

### 2. CPEの"AND"と"OR"

各CVEが該当するCPEなのですが、CPE Match Feedと照合するだけなく、さらに、もう一手間かけないといけません。
というのも、CVE情報には該当するソフトとバージョンのCPE一覧が書いてあるのではなく、AND/OR条件付きで書かれる、という形になっているからです。

具体的にデータを見ていくと、CVEの情報について、どのCPEが該当するかの情報は、JSONPATHライクに書くと$.CVE_Items.configurations.nodesに配列として格納されます。
nodes各データの中身は以下。

![20230415_13h56m30s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/85efa9f7-92e5-83a7-c63b-3ef9aa0e7273.png)

これはCVE-2022-0005のデータです。
ANDでchidlen以下の情報を並べて行きます。
この例だと、celeleron_g5205の利用者で、かつ、celeleron_g5025_firmwareを使っている場合は、CVE-2022-0005に該当する、となります。
NVDのWeb検索だとこのようになってます。
あり得るのかは微妙ですが。celeleron_g5205を使っているけどceleron_g5025_firmwareを使って「いない」人なら、影響を受けない、ということでしょうか。。

![20230415_14h06m21s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/8cc896e2-bcc5-401b-3293-67cfb444c503.png)

あと、vulnerableという要素もちょっと気になりますが、、trueはともかくfalseが。
データを見た感じ、AND条件の下のchildrenの２つ目で使われているようで、「脆弱じゃない」という意味ではなく、AND条件の２つ目で使われる、という使い方上のルールっぽい感じです。
Web画面で見ても「Running on/with」に該当する情報なので、「脆弱じゃない」という解釈ではないと思うので。

まぁ、今回は広く引っ掛けてあとからそのCVEの影響受けるかどうか人の目でふるい直せばいいと割り切って、AND/OR関わらず該当CPEが書いてあったら、そのCVEは影響あり、として列挙する方法が無難でしょうか。

### 3. で、実装、、

はしませんでした。
ココらへんで、実装の参考にできるコードないかなぁとググり始めて、cve-searchを見つけて大体必要な情報を引き抜けるようになり、残分のOS（Ubuntu）のパッケージのCVE特定の方は逐一CPE化してられないのでvulsを使うかーと思って調べてるうちにvulsでCPE指定の検索ができることに気がつき、今に至る、というわけです。

# まとめ

結局のところvulsベースで調べることにはなったのですが、ベースになっているNVDのデータの作りについて改めて勉強できました。
CPEはクセが強くて扱いにくいと言う認識があったのですが、改めて格闘してみると、やっぱり扱いにくかったです。
ツールを使うにしても、根っこではNVDのデータを使うものが大半ですので、ここは注意しておこうと思います。

改めて、vulsベースで「手動やベンダ個別のレポジトリから入れたソフト」「OSの標準ディストリから入れたパッケージ」「dockerコンテナで使用しているパッケージ」「pip群」の４種についてCVE情報を引っこ抜くということをシていくのですが、それはまた別の記事でまとめます。

そんなところで。