Suricataで不審なパケットを検知したら、メールなりで通知してほしいなぁって思いました。
しかし、Suricataそのものには通知機能はないっぽい?ので、サードパーティ製のアプリを活用するか自前で実装する必要があるっぽいです。
ということなので、アラート発報時にGmail / LINEにて通知してくれる通知アプリを今回作りました。
$ uname -a Linux rasp4-1 6.1.21-v8+ #1642 SMP PREEMPT Mon Apr 3 17:24:16 BST 2023 aarch64 GNU/Linux
今回、通知先にGmailとLINEを採用します。そこで前準備をします。
アプリパスワードを作成します。
2段階認証プロセスに対応していないアプリでも、アプリパスワードを使用することでGoogleアカウントにログインできるようになります。
なお、Gmail以外のメールサービスや自前のメールサーバを使いたい場合はスキップしてください。
1.以下のリンクより2段階認証プロセスを有効にします。(案内に従って有効にしてください)
Googleアカウント セキュリティ - https://myaccount.google.com/security
2.2段階認証プロセスを有効にしたら、以下のリンクよりアプリパスワードを作成します。
Googleアカウント アプリパスワード - https://myaccount.google.com/apppasswords
アプリを選択 > その他 > (任意の名前) で、"生成"をクリックします。
3.生成されたアプリパスワードが表示されます。
これは後ほど使うので控えておきます。
完了ボタンをクリックすると前の画面に戻り、作成したアプリ名と作成日が確認できます。
LINE Notifyのアクセストークンを作成します。
LINE Notifyとは、LINEが提供する通知APIで無料で利用可能です。
なお、LINEを使ってない方やLINEへの通知が不要な場合はスキップしてください。
1.以下のリンク先にアクセスし、LINEにログインします。
LINE Notify - https://notify-bot.line.me/ja/
画面上部右にある"ログイン"からログインします。
2.ログイン後に下のようなステップを踏んでください。
3.トークン名と送信先のトークルームを選択して、"発行する"をクリックします。
今回はLINE Notifyと1対1で通知を受け取ります。
Suricataアラート通知受信用にグループを作っておいて、それを選択してもいいかもですね。
4.発行されたトークンを"コピー"でコピーし控えておきます。
(もちろん下のトークンはダミーです)
閉じると、連携済みのサービスということで一覧に表示されます。
さて、前準備も済んだので実装を.....しました。
コードはGitHubにあげてますのでお好きにご活用ください。
GitHub - https://github.com/himazin331/suricata-alert-notice/tree/no_gpio
ここにもコードベタ貼りしておきます。
コード中にコメント散りばめてるので何となく分かると思いますが、ちょくちょく説明を挟んでおきます。
メール送信処理です。
なんかよしなにメールを送信してくれます。
LINE Notifyを通じてメッセージを送信する処理です。
いつものようにAuthorizationヘッダにトークン乗っけて、メッセージと一緒にPOSTするだけです。
main.pyです。
やってることは通知なのですが、細かく説明すると、
alert
を含むかをみる。と、こんな感じです。
今回、私は特にHTTP通信での脅威に目を光らせてる(笑)ので、通知メッセージにはIPやプロコトルなどのパケット情報に加えて、
ホスト名やURL、HTTPメソッドなどのHTTP情報も含めるようにしてます。
HTTP以外のプロコトル情報も一緒に通知したいというのであれば、eve.jsonに乗る情報であれば自由に通知できるかと思いますので、
色々カスタマイズしてみてください。
コード中に含まれる各定数は次の項目で説明します。
通知設定と認証情報とで別のファイルで分けてます。
NoticeType
の各設定値はこんな意味合いです。
通知タイプ | 説明 |
---|---|
Nothing | 通知しない (動作確認用) |
メール通知のみ | |
LineNotify | LINE通知のみ |
Both | メール/LINE通知 |
その他の設定値は以下のとおりです。
設定値 | 説明 | 備考 |
---|---|---|
EVE_JSONL_PATH | eve.jsonのパス | |
NOTICE_TYPE | 通知タイプ |
|
SIGNATURE_ID_RANGE | 通知対象とするシグネチャIDの範囲 |
|
今回は、通知対象とするシグネチャIDの範囲として2000000 ~ 2099999をデフォルトに指定しました。
この範囲のシグネチャIDはET Open Rulesetsで使用しています。つまり、ET Open Rulesetsに合致したパケットに絞って通知をしてもらいます。
定数の説明は以下のとおりです。
定数 | 説明 | 備考 |
---|---|---|
SENDER_EMAIL | 送信者メールアドレス | |
RECEIVER_EMAIL | 受信者メールアドレス | |
SMTP_SERVER | SMTPサーバアドレス | Gmailは |
SMTP_PORT | SMTPポート | Gmailは |
SMTP_USER | 認証メールアドレス | Googleアカウント メールアドレス |
SMTP_PASS | 認証パスワード | Googleアカウント アプリパスワード |
LINE_NOTIFY_TOKEN | LINE Notifyアクセストークン |
さて、実際に動かしてみましょう。
しかし、ET Open RulesetsのシグネチャID範囲を通知対象としましたが、ここでは再現を容易にするためにデモ用のカスタムルールを通知対象とします。
通知対象とするデモ用カスタムルール↓
alert ssh any any -> 192.168.120.20 any (msg:"[Demo-SSH] SSH connection to Demo-VM"; ssh.software; content:"SSH"; nocase; sid:100001; rev:1;)
alert http any any -> any any (msg:"[Demo-HTTP-1] Access to himazin331.com"; http.host; content:"himazin331.com"; sid:100002; rev:1;)
alert http any any -> any any (msg:"[Demo-HTTP-2] Access to example.com"; http.host; content:"example.com"; sid:100003; rev:1;)
通知設定はこんな感じ↓
from enum import Enum
class NoticeType(Enum):
Nothing = 0
Email = 1
LineNotify = 2
Both = 3
EVE_JSONL_PATH: str = "/usr/local/var/log/suricata/eve.json"
NOTICE_TYPE = NoticeType.Both
# SIGNATURE_ID_RANGE内のシグネチャのみ通知
SIGNATURE_ID_RANGE: tuple[int, int] = (100001, 100003) # ET Open Rulesets
[Demo-HTTP-1] Access to himazin331.com
のアラート通知[Demo-HTTP-2] Access to example.com
のアラート通知[Demo-SSH] SSH connection to Demo-VM
のアラート通知こんな感じで、メールとLINEで通知することができました!
実際の運用を考えると、ET Open Rulesetsのすべてを通知するのはちょっと煩わしいかなと思います。
そもそもETの中にも"ET INFO"や"ET GAMES"といったさほど重要でないカテゴリもあるので、環境に応じて不要なカテゴリは除外しても良いのかなと思います。
ということで、ET Open Rulesetsのなかで検知の可能性が高いカテゴリのみにフィルタリングして通知するように、以下のようにちょっとだけ変更を加えました。
config/general.py
FILTER_SIG_CATEGORY: list[str] = [
"Attack Response", "DNS", "DOS", "Exploit", "FTP",
"ICMP", "IMAP", "Malware", "NETBIOS", "Phishing",
"POP3", "RPC", "Shellcode", "SMTP", "SNMP", "SQL",
"TELNET", "TFTP", "Web Client", "Web Server", "Web Specific Apps", "WORM"
] # "ET xxx"のxxx。
main.py
def is_priority_sig(self, sig: str) -> bool:
for category in PRIORITY_SIG_CATEGORY:
if category in sig:
return True
return False
~ 略 ~
if lower_sig_id <= sig_id and sig_id <= upper_sig_id:
if is_priority_sig(eve["alert"]["signature"]): # <-- 追加
notice_target_eve.append(eve)
FILTER_SIG_CATEGORY内のカテゴリ説明だけ書いておきます。
カテゴリ | 説明 | カテゴリ | 説明 |
---|---|---|---|
Attack Response | システムへの侵入活動 | RPC | RPCに関する攻撃や脆弱性 |
DNS | DNSに関する攻撃や脆弱性 | Shellcode | 遠隔からのシェルコード実行 |
DOS | DoS攻撃の試み | SMTP | SMTPに関する攻撃や脆弱性 |
Exploit | 特定のサービスに分類されない普遍的な攻撃 | SNMP | SNMPに関する攻撃や脆弱性 |
FTP | FTPに関する攻撃や脆弱性 | SQL | SQLに関する攻撃や脆弱性 |
ICMP | ICMPに関する攻撃や脆弱性 | TELNET | Telnetに関する攻撃や脆弱性 |
IMAP | IMAPに関する攻撃や脆弱性 | TFTP | TFTPに関する攻撃や脆弱性 |
Malware | マルウェア攻撃 | Web Client | Webブラウザやcurl、wgetなどに関する攻撃や脆弱性 |
NETBIOS | NetBIOSに関する攻撃や脆弱性 | Web Server | Webサーバに関する攻撃や脆弱性 |
Phishing | フィッシング活動 | Web Specific Apps | 特定のWebアプリケーションに関する攻撃や脆弱性 |
POP3 | POP3に関する攻撃や脆弱性 | WORM | ワーム攻撃 |
詳細はET Category Descriptions (PDF)を参照してください。
いかがでしたか?通知アプリ開発編ということで自前で通知システムを実装してみただけですが...
実際の運用ではバックグラウンドで実行させたり、systemdでサービス起動させたりすると良いと思います。
また、実装上eve.jsonのファイルサイズが大きいと処理に時間がかかるかと思いますので、Suricataのほうで適切なログローテーション設定を行うことを強くおすすめします。
あと、これはそういうものなのかわからないのですが、GmailのSMTPサーバを経由してのメール送信が非常に遅く、アラート発報から約3分後にメール受信するというようなことになってます....私のネット環境の問題なのかSMTPサーバ側の問題なのかわからないのですが、もし改善策がわかる方いらっしゃいましたらTwitter(X)のDMやメールで教えてください!
ちなみに通知アプリのおまけ編も出そうと思っていて、少しずつですが作業を進めています。あまり新規性はないのですが...
ということで終わります。お疲れ様でした。