paloma blog

NWエンジニアやってます。主に自宅環境のお遊びを書きます。Pythonもちょっと。タイトルは好きなカクテルから。

Fortigateの脆弱性情報RSS取得ツールを自作する

オンプレ環境の話になりますが、システムを運用するとなると保守サポートに入りますよね。
NW機器なんかもそこで脆弱性情報を提供してくれるんですが、
どうにもFortigateの情報が少ない。

よくよく聞くと情報を精査して提示しているそうなので、
Fortiの情報が欲しければ自分で探してくれという流れになりました。

脆弱性情報のRSSも提供されているそうなので、いっちょ収集ツールでも作りましょう。

しかし、RSSでタイトルを確認するレベルならどこかのRSSフィードサイトに登録すれば事足ります。

ここは脆弱性の対象バージョンも取れるように作りたいと思います。

Forti機器のRSS

  • サイト

https://fortiguard.com/rss/ir.xml

ここではタイトル、掲載日、詳細リンクしかないので
さらにリンクを辿って対象のバージョンまで取れるようします。

コード

from bs4 import BeautifulSoup
import requests
import time

url = 'https://fortiguard.com/rss/ir.xml'

r = requests.get(url)

soup = BeautifulSoup(r.text, 'xml') 

items = soup.find_all('item')

n = 1
for content in items:

    time.sleep(3)
    detail = requests.get(content.link.text)
    
    soup = BeautifulSoup(detail.text, 'html.parser')
    
    for affected_ver in soup.find_all('div', class_='detail-item'):
        if 'Affected Products' in affected_ver.text:
        
            print(""" 
    --- No. {} ---
    Titile: {}
    Date: {}
    Link: {}
    Affected Ver: {}
    """.format(n, content.title.text, content.pubDate.text, content.link.text, 
        affected_ver.text.replace("\n", "\n\t")))
        
    time.sleep(3)
    n += 1

よく見るBeautifulSoup、requestsのセットですね。
かじっててよかったスクレイピング

リンクをクローリングすることになるのでsleepは多めにとってます。

動かしてみる

RSSページは25件あってスクリプトも全件取りますが、サンプル的に3件だけ出力させてみます。

サブ機Windows10で動かします。

  • 環境
PS C:\Users\masashi\tools\fortirss> $psversiontable

Name                           Value
----                           -----
PSVersion                      5.1.17763.592
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.17763.592
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
  • 実行
PS C:\Users\masashi\tools\fortirss> python .\fortirss.py

    --- No. 1 ---
    Titile: XSS vulnerability in FortiClientEMS
    Date: Mon, 23 Sep 2019 07:13:10 +0000
    Link: https://fortiguard.com/psirt/FG-IR-19-072
    Affected Ver:
        Affected Products
        FortiClientEMS version 6.2.0 and below.



    --- No. 2 ---
    Titile: IPMI network LAN interface failover operational risk
    Date: Tue, 17 Sep 2019 09:54:20 +0000
    Link: https://fortiguard.com/psirt/FG-IR-17-195
    Affected Ver:
        Affected Products

        FortiAnalyzer models:

        FAZ-400E, FAZ-1000E, FAZ-2000E, FAZ-3000F, FAZ-3500F, FAZ-3700F

        FortiManager models:

        FMG-300E, FMG-400E, FMG-2000E, FMG-3000F

        Other models and Fortinet products are confirmed to not have a default Failover setting.




    --- No. 3 ---
    Titile: HTTP/2 Multiple DoS Attacks (VU#605641)
    Date: Tue, 03 Sep 2019 14:41:11 +0000
    Link: https://fortiguard.com/psirt/FG-IR-19-225
    Affected Ver:
        Affected Products

        The following products have been confirmed to NOT be vulnerable to any of the above:

        FortiOS
        FortiAP
        FortiSwitch
        FortiAnalyzer
        FortiWeb
        FortiManager
        FortiMail


・・・

こんな感じ。
対象バージョンの中身はhtmlをそのまま抜き出してるので出力がバラバラですが、
使っているバージョンの有無は探せますね。

対象バージョンがある場合はリンク先URLへ行けば詳細が分かります。
いちいち全件見なくていいので運用が楽になりますね。

ちょっと大変だったところ

詳細ページのリンクへ行った後、対象バージョン部分のテキストを抜き出すのが苦労しました。
対象タグを探してからその配下を抜き出そうとしたのですがその方法がわかりませんでした。

対象の部分はこんな感じです。
(執筆時の1件目の詳細ページです。)

    <div class="detail-item">
        <h3>Affected Products</h3>
        <p>FortiClientEMS version 6.2.0 and below.<br></p>
    </div>

この部分が内容によってあったりなかったり、
テキストが多かったり少なかったりでどうやったらうまく取れるかを考えました。

文字列を検索して、ヒットしたらその要素を抜き出すという方法にしたら
何とか望みの結果が得られました。

"detail-item"クラスはページ内にいくつかあるのですが、
今回は"detail-item"内に"Affected Products"の文字列があったら
その部分を出力する、という処理で対応できました。

あとは出力の際にいいバランスになるようにタブを挿入してます。

せっかくなのでGithubに置きました

いつもの家で使うようなツールと違って職場でも使えると思いGithubに上げました。

https://github.com/masashi69/fortirss

(READMEのハイライトがなんかおかしい…)


全件取るだけのシンプルツールですが、更新された分だけチェックするようにしたり
他メーカーバージョンも作ってみたいですね。