Vulsをキックして脆弱性の差分をSlackにポストさせるPythonスクリプト

脆弱性検知にVulsを使っているのだが、現時点ではまだ差分検知の機能が実装されておらず、cronなどでまわして新しい脆弱性が見つかったらその脆弱性だけをSlackにポストさせるようにするにはVuls単体だとまだできない状態。 そろそろ実装されると思っているのだが、その間の繋ぎとしてPythonでスクリプトを書いてやることにした。

間に合わせなのであまり綺麗には書いてない状態。

vuls_run.py
#!/usr/bin/env python # -*- coding: utf-8 -*- from os.path import join, relpath import os,sys,subprocess,glob import ConfigParser import difflib import slackweb inifile = ConfigParser.SafeConfigParser() inifile.read('/home/vuls/.auth_info') # 変数 GO_CVE_BIN = '/home/vuls/go/bin/go-cve-dictionary' VULS_BIN = '/home/vuls/go/bin/vuls' VULS_HOME = '/home/vuls/' VULS_LOG = VULS_HOME + '/results' VULS_LOG_DIRDORMAT = '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_[0-9][0-9][0-9][0-9]' SLACK_WEBHOOK=inifile.get('slack', 'WEBHOOK_URL') SLACK_CHANNEL='#channel' SLACK_USER='User' # 【関数】脆弱性情報のアップデート def LibUpdate(option,period): update_command = GO_CVE_BIN + ' ' + option + ' -' + period + ' ' + '-dbpath ' + VULS_HOME + '/cve.sqlite3' update_out = subprocess.call(update_command.strip().split(' ')) if update_out <> 0: print 'Error Update "' + update_command + '".' # 【関数】Slack Post def SlackPost(ScanHost,txt): slack=slackweb.Slack(url=SLACK_WEBHOOK) attachments=[] attachment={'title': ScanHost,'text': txt,"color": "#FF00FF",} attachments.append(attachment) slack.notify(channel=SLACK_CHANNEL, username=SLACK_USER, icon_emoji=":vuls:", attachments=attachments) # 脆弱性ライブラリのアップデート LibUpdate("fetchnvd","last2y") LibUpdate("fetchjvn","last2y") # スキャン対象サーバリストの取得 FNULL = open(os.devnull, 'w') GETLIST_COMMAND = 'awk -F[].[] "/\[servers\./{printf \$3 \\" \\"}" ' + VULS_HOME + '/config.toml' GETLIST = subprocess.check_output(GETLIST_COMMAND,shell=True) # スキャンの実施 SCAN_COMMAND = VULS_BIN + ' scan -lang=ja -report-text -cve-dictionary-dbpath=' + VULS_HOME + '/cve.sqlite3 -config=' + VULS_HOME + '/config.toml -results-dir=' + VULS_LOG + ' ' + GETLIST subprocess.call(SCAN_COMMAND,shell=True) # 差分確認 dirs = glob.glob(VULS_LOG + '/' + VULS_LOG_DIRDORMAT) sort_dirs = sorted(dirs,key=str.lower,reverse=True) files = [relpath(x, sort_dirs[0]) for x in glob.glob(join(sort_dirs[0], '*'))] for check_file in files: if check_file == 'all.txt': continue # 対象ログの確認 before_log = sort_dirs[1] + '/' + check_file now_log = sort_dirs[0] + '/' + check_file if os.path.exists(before_log) == False: delta = ''.join(x[0:] for x in open(now_log, 'r') if x.startswith('CVE-') and len(x.split('\t'))>2) else: line=difflib.ndiff(open(before_log, 'r').readlines(), open(now_log, 'r').readlines()) delta = ''.join(x[2:] for x in line if x.startswith('+ CVE-') and len(x.split('\t'))>2) check_file.split('.')[0] if len(delta) == 0: continue else: ScanHost = check_file.split('.')[0] SlackPost(ScanHost,delta)

.authinfo(認証情報の記述ファイル)
[slack] WEBHOOK_URL = https://hooks.slack.com/services/TXXXX....

とりあえずこんな感じで。 ちゃんと機能として差分検知が実装されたら置き換えよう。

なお、Slackには以下のような感じで出力される。