脆弱性対応情報データベース (MyJVN API) の API を使って OSS の脆弱性を見てみる

この記事は Akerun Advent Calendar 2020 - Qiita の 11 日目の記事です。

今週 2 回目の登場です。 AkiAbe - Qiita です。
前回は、スプリント開発の話でマネジメント寄りの話でした。 akerun.hateblo.jp

今回は、少しテック寄りにしようと思います。

OSS脆弱性の情報確認

この記事読むようなかたは、Open Source Software (OSS) については把握していますね。
意識の高いエンジニアのみなさんとしては、自分が使っている開発環境の OSS脆弱性がどんなものあるか把握しておきたいですよね。

OSS脆弱性はデータベース化されています。
jvndb.jvn.jp

たとえば、debian 系 OS で、sudo コマンドの脆弱性はどのようなものがあるか調べてみましょう。

JVN iPedia - 脆弱性対策情報データベース
JVNDB-2019-014477 - JVN iPedia - 脆弱性対策情報データベース

JVNDB-2019-014477
Sudo における境界外書き込みに関する脆弱性

という指摘がでてきました。

こんな感じで、自分の環境のどのパッケージにどんな脆弱性があるかを調べることができます。

API を利用して、まとめて調べたい

ひとつずつパッケージ名入れて検索するの面倒ですよね。
MyJVN API という API が公開されているのでそれを利用してまとめて調べられないか試してみます。

私は試しに手元のラズパイでやってみます。
これから使うラズパイの OS 情報です。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 9.13 (stretch)
Release:    9.13
Codename:   stretch

$ uname -a
Linux rpiTester 4.19.66-v7+ #1253 SMP Thu Aug 15 11:49:46 BST 2019 armv7l GNU/Linux

ためしに、前述した sudo コマンドを API を叩いて調べてみます。
JVNDB-2019-014477 の指摘が得られます。 (それ以外のも得られます)

$ curl -G -d "method=getVulnOverviewList" -d "feed=hnd"  -d "keyword=sudo" -d "datePublicStartY=2019" -d "rangeDatePublished=n" -d "rangeDateFirstPublished=n"  https://jvndb.jvn.jp/myjvn

<?xml version="1.0" encoding="UTF-8" ?>   
<rdf:RDF 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://purl.org/rss/1.0/" 
xmlns:rss="http://purl.org/rss/1.0/" 
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
xmlns:dc="http://purl.org/dc/elements/1.1/" 
xmlns:dcterms="http://purl.org/dc/terms/" 
xmlns:sec="http://jvn.jp/rss/mod_sec/3.0/" 
xmlns:marking="http://data-marking.mitre.org/Marking-1" 
xmlns:tlpMarking="http://data-marking.mitre.org/extensions/MarkingStructure#TLP-1" 
xmlns:status="http://jvndb.jvn.jp/myjvn/Status" 
xsi:schemaLocation="http://purl.org/rss/1.0/ https://jvndb.jvn.jp/schema/jvnrss_3.2.xsd http://jvndb.jvn.jp/myjvn/Status https://jvndb.jvn.jp/schema/status_3.3.xsd" 
xml:lang="ja">
    <channel rdf:about="https://jvndb.jvn.jp/apis/myjvn">
      <title>JVNDB 脆弱性対策情報</title>
      <link>https://jvndb.jvn.jp/apis/myjvn</link>
      <description>JVNDB 脆弱性対策情報</description>
      <dc:date>2020-12-07T17:58:27+09:00</dc:date>
      <dcterms:issued/>
      <dcterms:modified>2020-12-07T17:58:27+09:00</dcterms:modified>
      <sec:handling>
        <marking:Marking>
          <marking:Marking_Structure xsi:type="tlpMarking:TLPMarkingStructureType" marking_model_name="TLP" marking_model_ref="http://www.us-cert.gov/tlp/" color="WHITE"/>
        </marking:Marking>
      </sec:handling>
      <items>
        <rdf:Seq>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-014477.html"/>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-013632.html"/>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-013631.html"/>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-011719.html"/>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-011096.html"/>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-010626.html"/>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-007171.html"/>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-005598.html"/>
        </rdf:Seq>
      </items>
    </channel>
    <item rdf:about="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-014477.html">
      <title>Sudo における境界外書き込みに関する脆弱性</title>
      <link>https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-014477.html</link>
      <description>Sudo には、境界外書き込みに関する脆弱性が存在します。</description>
      <dc:creator>Information-technology Promotion Agency, Japan</dc:creator>
      <sec:identifier>JVNDB-2019-014477</sec:identifier>
    .....
    .....
    以後、省略

スクリプト

dpkg -l で、入っているパッケージ一覧がとれるので、それで取得できるパッケージに対して、上記の API脆弱性を確認してみます。

$ dpkg -l 

Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                            Version                           Architecture Description
+++-===============================-=================================-============-===============================================================================
ii  adduser                         3.115                             all          add and remove users and groups
ii  adwaita-icon-theme              3.22.0-1+deb9u1                   all          default icon theme of GNOME
ii  alsa-utils                      1.1.3-1                           armhf        Utilities for configuring and using ALSA
ii  apt                             1.4.10                            armhf        commandline package manager

    .....
    .....
    以後、省略

check.sh とかいう名前で以下のようなスクリプト作成します。
結構力技で書いてます... ^^;

#! /bin/bash

FEED="feed=hnd&"
MET1="method=getVulnOverviewList&"
URL="https://jvndb.jvn.jp/myjvn?"

# 2015 年以降で指摘があったパッケージを検索
START="datePublicStartY=2015&"
RANGEP="rangeDatePublished=n&"
RANGEF="rangeDateFirstPublished=n&"


RES_TMP_FILE="res_tmp.txt"

# 最初にみつけた指摘だけ出力する
res_check () {
    res_flg=1
    html_list=""
    
    while read str; do
    if [ "`echo $str | grep '該当する脆弱性対策情報はありません'`" ]; then
        res_flg=0
        break
    fi
    if [ "`echo $str | grep html`" ]; then
        html_list=$str
        break
    fi
    done < $RES_TMP_FILE

    echo $res_flg $html_list
    return
}



# パッケージリスト取得して、不要な文字列消す             
FILE_NAME="hoge.txt"
NEW_FILE="oss_list.txt"

dpkg -l > $FILE_NAME
sed -e 's/ii  //g' $FILE_NAME > $NEW_FILE


# package 名で web api 叩いて確認
while read Line; do

    # package 名抽出
    CHECK_PKG=` echo $Line | awk '{sub(" .*", "");print $0;}' `

    # "|" とか "||" とかの行をはぶく  
    if [[ $CHECK_PKG =~ ^[a-z].*$ ]]; then

        # keyword にパッケージ名指定して web api たたく 
        KEYWORD="keyword=${CHECK_PKG}&"
        curl -s ${URL}${MET1}${FEED}${KEYWORD}${START}${RANGEP}${RANGEF} > $RES_TMP_FILE

        # 返答解析する                                                                                                         
        ret=$(res_check)
        flg=`echo $ret | cut -c 1`

        if [ $flg -eq 0 ]; then
            echo "${CHECK_PKG}, 脆弱性報告なし "
        else
            tmp_url=`echo $ret | grep -oE 'http(s?)://[0-9a-zA-Z?=#+_&:/.%-]+'`
            echo "${CHECK_PKG}, 脆弱性あり (詳細確認してください), ${tmp_url}"
        fi
    fi


    
done < $NEW_FILE

rm -fr $FILE_NAME
rm -fr $NEW_FILE

実行してみる。

$  ./check.sh  

adduser, 脆弱性あり (詳細確認してください), https://jvndb.jvn.jp/ja/contents/2016/JVNDB-2016-006807.html
adwaita-icon-theme, 脆弱性報告なし 
alsa-utils, 脆弱性報告なし 
apt, 脆弱性あり (詳細確認してください), https://jvndb.jvn.jp/ja/contents/2020/JVNDB-2020-005502.html

    .....
    .....
    以後、省略

まとめ

上述のスクリプトは文字列でひっかけただけなので、意図してない指摘*1も含まれてしまいます。
うまいやり方は他にもありそうですが、見るものを絞ることはできた感じですね。
気になるパッケージの脆弱性があれば、自分でパッチを当てましょう。


株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 hrmos.co

Akerun Proの購入はこちらから akerun.com

*1: https://jvndb.jvn.jp/ja/contents/2016/JVNDB-2016-006807.html なんかだと adduser パッケージ自体の指摘ではない