WindowsイベントログをGraylogにInputする

Graylogは色んなログをどんどん取り込むことができるので、SIEMとして活用できそうです。試しに今回はWindowsのイベントログをGraylogに取り込んでみたいと思います。
やり方は色々あると思いますが、ここではPythonからGELFを使って取り込みます。
環境情報
Graylogサーバー
・CentOS7
・Graylog v3.0.1
クライアント
・Windows10 or 7
・Python3.6.2
Windowsイベントログを取得
Windowsイベントログはpowershellやwmicなど色んな方法で取得できますが、ここではwevtutilコマンドを使って取得します。
wevtutilコマンドはBookmark機能があるので、すでに取り込んだログを取り込むことなく2回目以降高速に取得できるからです。
wevtutil qe System /f:text /sbm:bookmark.xml > system.txt
ローカルPCのSystemイベントログを取得するにはこのようにします。
wevtutil qe System /f:text /bm:bookmark.xml /sbm:bookmark.xml > system.txt
2回目以降は /bm オプションを追加して、前回のbookmarkの位置を取得するようにします。
wevtutil qe System /r:remotecomputer /f:text /bm:bookmark.xml /sbm:bookmark.xml > system.txt
また、リモートPCのイベンログを取得するには /r オプションを指定します。
出力形式をText形式にすると、出力に時間がかかるようになりますが、xml形式だとGraylogに送信するときにメッセージが日本語で表示できなくなりますので、Text形式で取得しています。
Inputの設定

[System / Imputs] – [Inputs]を開きます。

GELF HTTPを選択して、[Launch new input]をクリックします。

分かりやすいタイトルを入力し、[Save]をクリックします。
なお、ここで指定したPort番号に対して送信しますので、覚えておいてください。
GELF形式について
Graylog(Graylog Extended Log Format)は、JSON形式のGraylog用のログフォーマットです。
基本的にはJSON形式にすればいいのですが、次のフィールドを必要とします。
- version
string (UTF-8)
- 必須フィールドです。 1.1と指定してください。
- host
string (UTF-8)
- 必須フィールドです。ここに指定する文字列が、Graylog側でのSourceフィールドとなります。
- short_message
string (UTF-8)
- 必須フィールドです。ここに指定する文字列が、Graylog側でのmessageフィールドとなります。
- full_message
string (UTF-8)
- short_messageより長い文字列が必要な場合はオプションで。
- timestamp
number
- オプションですが、ログのtimestampは入れておいたほうがいいでしょう。UNIXエポックタイムを指定します。
- level
number
- オプションです。デフォルトでは1となります。
- facility
string (UTF-8)
- オプションです。facilityを指定したい場合は入力。
- line
number
- オプションです。エラーとなったファイルの行数を指定しますが、このフィールドは非推奨のようです。
- file
string (UTF-8)
- オプションです。こちらも非推奨なのですが、エラーとなったファイル名またはフルパスを指定します。
- _[additional field]
string (UTF-8)
ornumber
- 上記以外のフィールドを追加するには、_を付けて追加フィールドを作成します。
PythonでイベントログをGELF形式に変換してGraylogに送信
それでは、wevtutilで取得したテキスト形式のイベントログをGELF形式に変換してGraylogに送信してみます。
#-*- coding: utf-8 -*-
import urllib.request, json
from datetime import datetime, timedelta
import os
url = "http://graylogserver:12202/gelf"
method = "POST"
headers = {"Content-Type" : "application/json"}
def posteventlog(evntfile):
f = open(evntfile, encoding="shift-jis")
lines = f.readlines()
f.close()
dsfl = False
lists = []
dstr = ""
for line in lines:
line = line.replace("\n", "")
if "Event[0]" in line:
continue
if dsfl == False:
lists.append(line.split(": ")[1])
if "Description:" in line:
dsfl = True
else:
if "Event[" in line and dsfl == True:
short_message = "pc eventlog"
timestamp = datetime.strptime(lists[2], "%Y-%m-%dT%H:%M:%S.%f")
data = {
"version" : "1.1", "host" : "pc", "short_message" : short_message,
"timestamp" : int(timestamp.timestamp()),
"_LogName" : lists[0], "_Source" : lists[1], "_Date" : lists[2], "_EventID" : lists[3],
"_Task" : lists[4], "_Level" : lists[5], "_Opcode" : lists[6], "_Keyword" : lists[7],
"_User" : lists[8], "_UserName" : lists[9], "_Computer" : lists[10], "_Description" : dstr
}
json_data = json.dumps(data).encode("utf-8")
dstr = ""
# httpリクエストを準備してPOST
request = urllib.request.Request(url, data=json_data, method=method, headers=headers)
with urllib.request.urlopen(request) as response:
response_body = response.read().decode("utf-8")
lists = []
dsfl = False
else:
dstr += line
if __name__ == "__main__":
posteventlog("System.txt")
ちょっとあれなコードですが、ゴリゴリ回して変換してます。
まあでも、そんなに時間はかからず送信できますのでご容赦を。
これでGraylogにWindowsのイベントログを送信することができるようになります。
-
前の記事
Graylogのアラート機能を使ってアラートメールを飛ばす 2019.07.04
-
次の記事
scikit-learnとjanomeを使ってスパムメール判別器を作る 2019.07.30