そのままでは扱い難いJVN(Japan Vulnerability Note)
JVN(Japan Vulnerability Note)を活用されている方や、活用したいというは方は多いと思いますが、ウェブサイトの情報を使うにしても、JVNRSSの配信を使うにしても、日々大量の脆弱性情報が発表されていきますし、随時更新されるので、脆弱性の確認をしている間に新たな重要な情報が配信されてくるなんてことが考えられます。また、データフォーマットがXMLなので、必要な情報を抜き出して実際に役立つ形にするだけでも、慣れない人からすると、とても扱いやすいものとは言い難いのではないでしょうか。
弊社でもJVNのサイトで提供される脆弱性情報をJVNのウェブサイト経由で「手動」でごりごりと管理シートに集約して、対処が必要そうなものと、そうでないものを振り分ける仕事をしているメンバーがいました。他の業務と兼務だということもありますが、日々の脆弱性情報の量をこなすのに手一杯で、省力化や効率化に手が回らないようだったので、Sumologicを使って簡単クッキングしてダッシュボードにしてみました。
※本稿で紹介する主なSumologic機能:Boundary Expression、フィルタ、parseオペレータ、ifオペレータ、sortオペレータ、dedupオペレータ、transactionizeオペレータ
☘☘☘
JVNの何を見るのか
早速、脆弱性情報の振り分け業務を日々行っているメンバーと会話をしたところ、JVNの何を気にしているのか、いくつかポイントが見えてきました。これがそのままダッシュボードに求められる機能になります。
- 一定のCVSSスコア以上の情報にフォーカスしたい
- 最新の情報を見逃さないようにしたい(過去の情報に埋もれないようにしたい)
- 自社で利用しているシステムに関連しそうなものを優先的に把握したい
- ダッシュボードをCSIRTにも共有し、毎週のCSIRTへの報告にそのまま使いたい
先にダッシュボードを見せちゃいます
というわけで、これが今回作成したダッシュボードです。見やすい!と社内でなかなか好評です。
それぞれのパネルについて、左上から右に向かって説明します。
- 今日発表されたJVNの件数(62件)
- 直近7日に発表されたJVNの数(227件)※
- JVNのデータをSumologicにアップロードした最新時刻(10/21 19:00)
- 弊社に関係がありそうな脆弱性のリスト(CVSSスコアが7.0以上のもの)※
- CVSSスコアが7.0以上だった脆弱性の数(No data = 0件)※
- 過去1週間のJVN件数の推移(CVSSが7.0以上のものと、そうでないものを可視化)※
- CVSSスコアが7.0以上だった脆弱性の明細※
- CVSSスコアの高い脆弱性トップ20
最上部にはフィルタが2つ設定されています。1つは任意のキーワードを設定できます。例えば、「*Java*」と入力すると7のパネルに該当するキーワードを含む脆弱性が表示されます。もう一つのフィルタはCVSSスコアを設定できます。ここでは「7.0」に設定されていまして、「※」で示したパネルを表示する際の絞り込み条件で使われています。
可視化までの流れ
前述の機能を実装するまでの大まかな流れは以下のとおりです。
- データの取り込み
- パースの作成
- 要件に応じたグラフ(パネル)の作成とダッシュボードへの配置
- フィルタの設定
クッキングのコツ
ダッシュボードを見せちゃったので、このブログもこれで終わっても良いのですが(笑)、せっかくSumologicのブログなので、ダッシュボード作成にまつわるSumologic的なクッキングレシピをいくつか紹介します。
◇◇◇ XMLにおまじない ◇◇◇
RSSはXML形式で配信されます。実際のファイルは次のようなものです。はい、お気づきのとおり、問題は、1つのJVN情報が複数行にまたがっている点です。
普通のログは、1行に発生したイベントの情報が記録されますが、RSSでは、黄色枠で示したとおり、1つのJVN情報に関する情報が複数行にまたがって記録されています。上の例では、"<item rdf:about="という行から"</item>"までの間にあるJVNの各種情報が記録されています。
ですが、心配ありません。Sumologicでは、一行の先頭部分を示す正規表現を書くことで、複数にまたがった行を1行のログとして取り込めるのです!
実際には、ログの先頭を認識するための、次のような正規表現を設定します。おまじないのようですが、この正規表現の意味するところは、行の先頭から1つ以上のスペースの後、"</item"で始まり、その後ろは任意の文字(改行も含め)の連続という意味です。なので、" </item"が現れると取り込みはじめ、次の"</item"が現れるまでを1行として取り込んでくれます。
正規表現:(^\s+\<\/item\s.*)
自分で正規表現が書けるか自信が無い?弊社ユーザの皆様はご心配なく。弊社サポート窓口にお問い合わせいただければ、おまじない正規表現を提示させていただいてます。お気軽にお問い合わせください。
◇◇◇ 下ごしらえ ◇◇◇
RSSを取得するスクリプトはbashで書きました。curlでrssをダウンロードして、起動時のタイムスタンプを付加したファイル名で保存するという、とてもシンプルなものです。このシェルをSumologicのコレクタを動作させているマシンで定期実行するようcron設定します。
RSSの配信は12時と17時後だと後で知ったのですが、日中毎時に収集の当初設定のまま動かしています。もし、特別に配信があった場合にタイムリーに取り込めるかな、なんて期待もあります。SumologicのUIから、作成したファイルが読み込まれるようにコレクタを設定します。併せて、古いファイルを削除するcronの設定もお忘れなく。
No.4のパネルを作ります
先ほどダッシュボードで紹介した4番目のパネル、「弊社に関係がありそうな脆弱性のリスト」を作っていきます。
◇◇◇ 材料を切ります ◇◇◇
いよいよ素材を切っていきます。XMLは構造的なのでパースはとても簡単です。title、JVN、CVE、CVSSv3、modifiedをパースする例を示します。これを参考に他の情報も切り出してみてください。
<パースの例>
| parse "title>*<" as title
| parse "identifier>*<" as JVN
| parse "source=\"CVE\" id=\"*\"" as CVE
| parse "version=\"3.0\" score=\"*\"" as scorev3
| parse "modified>*<" as update
◇◇◇ 煮詰めます ◇◇◇
JVN情報は、cron設定に従い、1日に何回かSumologicに取り込まれます。つまり、ある日のSumologic内のJVN情報には、同一のJVN情報が複数あることになります。可視化にあたっては、そのうちの1行があれば十分なので(他は冗長)絞り込むのですが、そういう場合にうってつけなのが dedup というオペレータで、重複したログを排除してくれます(重複排除といいます)。
重複排除するには、同一の行であることを識別するためのキー項目を指定します。つまり、同一のキー項目を含むログは同じであるとみなし、重複しているログを削除してくれます。
JVNの情報には、先ほどパースした項目の中にキー項目に適している項目としてJVNとCVEがあります。さらに、同一JVN、CVEのログの項目の中でには更新日付が異なるものが含まれる可能性があるので、updateもキー項目として指定します。こうすることで、後続の処理で必要な最低限のログに絞り込め、後続の処理の高速化にも寄与します。
| dedup JVN, CVE, update
◇◇◇ 調味料を加え、盛り付けます ◇◇◇
ダッシュボードに期待されることとして、「弊社に関係のある製品や、影響の大きい製品(Javaなど)の脆弱性にいち早く気づきたい」というのがありました。これは、条件に合致するものを上位に表示するようにしてみました。具体的には、上位に表示したいものに高いプライオリティを付与することで、プライオリティの高い順、CVSSスコアの高い順に表示することにしました。
<プライオリティ付けの例>
| if( description matches /bind|BIND/, 2, 0) as priority
| if( description matces /java|Java|JAVA/, 1, priority) as priority
| sort by priority, scorev3
| fields -priority
弊社に関係のある製品〜例えば、Infobloxの心臓部に当たるBIND〜には最も高いプライオリティに2を、あちこちで使われているので何かあると影響の大きい製品(Java)には中位のプライオリティに1を、それ以外には低いプライオリティに0をつけます。なお、if文は一行で書くこともできますが、読み難くなるので、僕は2行に分ける方が好きです。
クエリの最後でsortオペレータを使って表示順を指定して利用者の興味のある情報を上位に表示するようにします。sortオペレーターは、デフォルト後順で並べ替えます。また、priorityは表示したくないので、fieldsオペレータで削除して見た目を整えています。
◇◇◇ もうひと工夫 ◇◇◇
ここまででも見栄えは整うのですが、見た目だけでなく中身をもう一段洗練させます。冒頭、メンバーからヒアリングしたポイントに、一定以上のCVSSのスコアを見たいというのがありました。実装の仕方としては、①特定の値をクエリ内に埋め込む、または②フィルタ機能を使って任意の値を任意のパネル内のクエリで利用する方法があります。もちろん①の方法でも良いのですが、自由度が高いこと~選択できること~は利用者にとって嬉しいことですよね。
青いロートのアイコン(フィルタ設定のアイコン)をクリックすると「Create a template variable +」と表示されます。
「+」ボタンをクリックと設定画面が現れるので、キャプチャのように設定します。
- Variable Name: フィルタ変数名で、クエリの内部で参照します。Scoreとしました。
- Variable Type:ここではCustome Listを選択します。
- List Item: カンマで区切って任意の値のリストを作ると、ドロップダウンで値を選択できるようになります。
- Include the option to select all values (*) : Onにするとドロップダウン・リストに「*」を含めることができ、その場合はすべてのスコアを対象にできます。
- Default Value: ここに通常使う値を設定します。例えば、7.0などです。
フィルタの準備ができたので、クエリを修正します。修正箇所はフィルタを参照したいパネルの「where」オペレータの箇所で、次のように「{}」で括って作成したフィルタ変数を記述します。こうすることで、ダッシュボードのフィルタに設定された値を使ってクエリが実行されます。
| where scorev3 >= {{Score}}
ちなみに、フィルタ変数をパネルのタイトルに埋め込むことも可能です。このようにすることの利点は、利用者にパネルの表示内容に影響を与えている値が何なのかを示すことができるのはもちろんですが、フィルタがそのパネルに影響を与えていることを利用者に伝えることができる点で、利用者は、他のフィルタ値を使おうと自ら考え始めるところです。
利用者がやりたいと思ったことを可能な限り柔軟にできるようにすること。
作り手として大事にしたいところですね。
CSIRTへの週次報告に向けて
JVN情報は更新されていきますので、ダッシュボードは最新の情報を提供しなければなりません。これは、現場のメンバーにとっても大事なことですが、CSIRTへの週次報告で使う上でも重要なことです。
ある日、新たなJVNがRSS内に出現したとします。数日後、同じ識別子のJVNの情報が更新されて再度出現することがあります。こうしたことは、ある1日の中でも起きえますし、CSIRTへの報告周期である1週間の中でも起きうる話しです。そうした場合に、最新の情報をダッシュボードに表示するようにしなければなりません。
ひとつひとつのJVN情報にはタイムスタンプが付けられていて、JVN内の情報に更新があればタイムスタンプも更新されます。そのタイムスタンプとは、実はdedupのところでキー項目として利用した update です。updateがそれぞれのJVN情報の更新日を保持していますので、あるJVNの最新情報を保持するログを抽出するには、そのJVNのupdateが最も直近のものを選択すればよいのです。
Sumologicには、こういうことができるtransactionizeという便利なオペレータがあります。キーとなるJVNを指定すると、複数のログを調べて同一JVNを含む行のフィールドを1行にまとめることができます。
<最新の行を選択する例>
| transactionize JVN ( sort update | merge JVN takeDistinct, CVE takeDistinct, update takeLast, scorev3 takeLast)
このようにすると、JVN毎にupdateが最新のログからscorev3を抽出することができます。
この1行のクエリがやっていることを文章で書くと、①複数ログを調べて同じJVN番号を含むログを集め、②updateで降順にソートし(最新のものが1番上にくる)、③ユニークなJVN番号ごとにユニークなCVEを抽出し、降順で並べられたリストの直近のupdateとscorev3を選択する、となります。
なかなか小難しく聞こえますが、これを使えるようになるとグラフやテーブルの表現力がグッとアップしますので、この機会にマスターしてはいかがでしょうか。
☘☘☘
ところで、scorev3以外の項目が更新された場合はどうするのか?
それにはさらに工夫必要です。それはまた別の機会にでも☕
- カテゴリ:
- Sumo Logic
- 技術情報
- JVN
- XML