LoginSignup
3
2

More than 3 years have passed since last update.

標的型攻撃に対するJPCERT/CCのおすすめログ設定をElasticsearchで構築してみる(メールサーバ編)

Last updated at Posted at 2019-05-02

はじめに

「標的型攻撃に対するJPCERT/CCのおすすめログ設定をElasticsearchで構築してみる」のメールサーバ編です。メールサーバとして(Postfix)を利用します。

(これまでの記事)
* 「準備編」
* 「プロキシサーバ編」

※本記事で作成するFilebeatモジュールやPostfixの設定例はこちらへ仮置きしておきます(今後、もう少しわかりやすい配置にする予定です)。

※Ubuntu18.04上で構築(FilebeatはDEBパッケージでインストール)しますので他のディストリビューションやFilebeatインストール方法の場合にはファイルの配置場所などを読みかえてください。

※実際の環境で運用するには、ネットワーク設定、個々のソフトウェアのインストール/初期設定や認証/通信の暗号、冗長構成や負荷分散などで相応の設定が必要となります。それぞれ個別のドキュメントをご参照ください。本記事ではログ設定に関係する基本的なコンフィグレーションにフォーカスして記載します。

利用するソフトウェア

  • OS: Ubuntu 18.04
  • メールサーバ: Postfix (3.3.0) / Dovecot (2.2.33.2)
  • DNSサーバ: Dnsmasq (2.79)
  • Elasticsearch (6.6.0)
  • Kibana (6.6.0)
  • Filebeat (6.6.0)
  • VMware Workstation Player等のVMソフトウェア
  • Windows 10 (クライアントPC)

ネットワーク構成例

ここでは「準備編」で説明した以下のようなシンプルなネットワーク構成を想定。
log_network_postfix.png

                            説明
メール Windows 10クライアントPC上のメールクライアントはdmz.example.comで動作するメールサーバ(Postfix)へアクセス
ログ dmz.example.com上で動作するメールサーバのログをFilebeatがElasticsearch(log.example.com)へ転送

作業内容

  1. ネットワーク構築および各ソフトウェアのインストールと設定
  2. Postfixログ設定およびフォーマット追加
  3. Postfix用のFilebeatモジュール作成
  4. Postfix用のFilebeatモジュールをdmz.example.comに配置し設定
  5. Kibanaで確認

JPCERT/CCのおすすめログ設定

「高度サイバー攻撃への対処におけるログの活用と分析方法」をもとに以下の情報を出力するように設定します。

  • メールヘッダのFromに含まれる情報
  • MIMEヘッダ(Content-Type/Content-Disposition)の添付ファイル名

smtp.png
Alice(alice\@example.com)からBob(bob\@example.com)へメール送信した例 (SMTP)

これらの情報より以下の攻撃を検出できる可能性があります。

  • 送信元を偽装したメールを送り付けて、その添付ファイルを開かせる、またはメッセージ中のURLをクリックさせる
  • マルウエアである実行ファイルを添付したメールを送り付ける

(JPCERT/CCの同資料より抜粋)

これらのログを利用した分析手法の詳細についても同資料に説明されていますのでぜひご参照ください。

またメールに添付されるファイルを利用した典型的な攻撃例(例えばMicrosoft Officeドキュメント(.docx, .xlsx)やWindowsショートカットファイル(.lnk)が添付される場合など)では、そのファイル開封後にマルウェアの実体がダウンロードされる処理が続けて実行される場合があります。その際にはHTTP/HTTPSトラフィックを偽装またはそれらをトランスポートにすることも多く、前回の記事で扱ったプロキシサーバログとの照合が重要になるかもしれません。
参考:
* IQYファイル(※)を悪用する攻撃手に関する注意点 (第二版) [IPA 2018/08]
* IQYファイルを利用するマルウェアスパム、日本のみを標的に 50 万通拡散 [Trend Micro 2018/09]

このような疑わしい添付ファイルも既知のものはvirustotalなどで無償でチェックできますが、ファイルハッシュで照合するのではなく、ファイルを検体としてアップロードする場合には情報漏洩につながらないように十分にご注意ください。
参考: ウイルスチェックのつもりで情報漏えい? VirusTotalの使い方に注意 [ITmediaエンタープライズ 2016/3/14]

メールサーバ(Postfix)のログ設定とフォーマット追加

Fromヘッダ情報の採取

送信元を偽装したメールを検出するためにメールヘッダのFromフィールドのdisplay nameと実際のメールアドレスの情報を採取します。以下のように設定ファイルを変更します。

/etc/postfix/main.cf
header_checks = regexp:/etc/postfix/header_checks

次にファイルheader_checksを作成し実際にログ採取するメールヘッダのフィールドパターンを指定します。

cd /etc/postfix
touch header_checks
nano header_checks

Fromヘッダのパターンを設定します。

/etc/postfix/header_checks
/^From:/ WARN

この設定により以下のようなPostfixログが採取されます。

/var/log/mail.log
Apr  21 08:01:14 dmz_server postfix/cleanup[6615]: 4B19A1000EB: warning: header From: alice <alice@example.com> from unknown[192.168.0.xx]; from=<alice@example.com> to=<bob@example.com> proto=ESMTP helo=<[192.168.0.xx]>
メールヘッダの情報
header From: alice <alice@example.com>
エンビロープの情報
from=<alice@example.com> to=<bob@example.com>

MIMEヘッダ情報の採取

以下のMIMEヘッダ情報を採取します。
* Content-Type
* Content-Disposition

/etc/postfix/main.cf
mime_header_checks = regexp:/etc/postfix/mime_header_checks

ファイルmime_header_checksを作成し実際にログ採取するメールヘッダのフィールドパターンを指定します。

cd /etc/postfix
touch mime_header_checks
nano mime_header_checks

MIMEヘッダのパターンを設定します。

/etc/postfix/mime_header_checks
/^\s*Content-(Disposition|Type).*name\s*=\s*"?(.+)"?\s*$/ WARN

この設定により以下のようなPostfixログが採取されます。

/var/log/mail.log
Apr  21 08:01:14 dmz_server postfix/cleanup[6615]: 4B19A1000EB: warning: header Content-Type: image/png;? name="Test.png" from unknown[192.168.0.xx]; from=<alice@example.com> to=<bob@example.com> proto=ESMTP helo=<[192.168.0.xx]>
Apr  21 08:01:14 dmz_server postfix/cleanup[6615]: 4B19A1000EB: warning: header Content-Disposition: attachment;? filename="Test.png" from unknown[192.168.0.xx]; from=<alice@example.com> to=<bob@example.com> proto=ESMTP helo=<[192.168.0.xx]>

Test.pngというファイル名を採取。この値はBase64エンコードされている場合があります。

PostfixログメッセージのJSON変換

「プロキシサーバ編」と同様にPostfixログメッセージはFilebeatによりJSON形式へ変換されてElasticsearchへ転送されます。

/var/log/mail.log(処理前)
Apr  21 08:01:14 dmz_server postfix/cleanup[6615]: 4B19A1000EB: warning: header Content-Type: image/png;? name="Test.png" from unknown[192.168.0.xx]; from=<alice@example.com> to=<bob@example.com> proto=ESMTP helo=<[192.168.0.xx]>

このログメッセージはFilebeatにより以下のようにJSON形式へ変換されます。

Filebeatによる変換処理後
{
  "_index": "filebeat-6.6.0-2019.xx.xx",
  "_type": "doc",
  "_id": "ge2SdmoBsFF1POM-ajN-",
  "_version": 1,
  "_score": null,
  "_source": {
    "offset": 23700,
    "log": {
      "file": {
        "path": "/var/log/mail.log"
      }
    },
    "prospector": {
      "type": "log"
    },
    "source": "/var/log/mail.log",
    "fileset": {
      "module": "postfix",
      "name": "mail"
    },
    "message" : "Apr  21 08:01:14 dmz_server postfix/cleanup[6615]: 4B19A1000EB: warning: header Content-Type: image/png;? name=\"Test.png\" from unknown[192.168.0.xx]; from=<alice@example.com> to=<bob@example.com> proto=ESMTP helo=<[192.168.0.xx]>",
    "input": {
      "type": "log"
    },
    "@timestamp": "2019-04-20T23:01:31.000Z",
    "beat": {
      "hostname": "dmz_server",
      "name": "dmz_server",
      "version": "6.6.0"
    },
    "host": {
      "os": {
        "codename": "bionic",
        "name": "Ubuntu",
        "family": "debian",
        "version": "18.04.1 LTS (Bionic Beaver)",
        "platform": "ubuntu"
      },
      "containerized": false,
      "name": "dmz_server",
      "id": "39557a23335243cb9d4740a1a210ae3d",
      "architecture": "x86_64"
    },
    "event": {
      "dataset": "postfix.mail"
    }
  },
  "fields": {
    "@timestamp": [
      "2019-04-20T23:01:31.000Z"
    ]
  },
  "sort": [
    1556767467095
  ]
}

その後Elasticsearch/Ingestノードにより_source.messageフィールドがパーシングおよびパイプライン処理され以下のように変換されます(詳細は後述)。

Elasticsearc/Ingestノードによる変換処理後
{
  "_index": "filebeat-6.6.0-2019.xx.xx",
  "_type": "doc",
  "_id": "ge2SdmoBsFF1POM-ajN-",
  "_version": 1,
  "_score": null,
  "_source": {
    "offset": 23700,
    "log": {
      "file": {
        "path": "/var/log/mail.log"
      }
    },
    "prospector": {
      "type": "log"
    },
    "source": "/var/log/mail.log",
    "fileset": {
      "module": "postfix",
      "name": "mail"
    },
    "input": {
      "type": "log"
    },
    "@timestamp": "2019-04-20T23:01:31.000Z",
    "beat": {
      "hostname": "dmz_server",
      "name": "dmz_server",
      "version": "6.6.0"
    },
    "host": {
      "os": {
        "codename": "bionic",
        "name": "Ubuntu",
        "family": "debian",
        "version": "18.04.1 LTS (Bionic Beaver)",
        "platform": "ubuntu"
      },
      "containerized": false,
      "name": "dmz_server",
      "id": "39557a23335243cb9d4740a1a210ae3d",
      "architecture": "x86_64"
    },
    "postfix": {
      "mail": {
        "process": "cleanup",
        "to_email": "bob@example.com",
        "remote_ip": "192.168.0.xx",
        "from_email": "alice@example.com",
        "mime_type": "image/png",
        "header": "Content-Type",
        "pid": "2368",
        "mime_name": "Test.png",
        "time": "2019-04-20T23:01:14.000Z",
        "mail_server": "dmz_server",
        "queue_id": "304A6101243",
        "remote_host": "unknown"
      }
    },
    "event": {
      "dataset": "postfix.mail"
    }
  },
  "fields": {
    "@timestamp": [
      "2019-04-20T23:01:31.000Z"
    ]
  },
  "sort": [
    1556767467095
  ]
}

ご覧の通り_soruce/messageフィールドが_source.postfixフィールドへオブジェクトとして展開されています。こうすることでKibanaで各情報単位で検索や集計したり、自作ツール等で扱いやすくなります。

Postfix用Filebeatモジュールの作成

(現状)FilebeatのパッケージにはPostfix用モジュールが含まれていないようです。そのためPostfixログ用のモジュールを作成します。

Filebeatのモジュール作成方法はこちらの公式サイトで解説されていますが(テンプレートファイルを生成するMakeファイルも用意されています)、前回同様にFilebeatのパッケージに同梱されているApache用のモジュールを雛形にして作成してみます。

基本的な作業は前回の「プロキシサーバ編」とほぼ同様ですので詳細についてはあわせて参照してください。

Apache用モジュールをコピー
cd /usr/share/filebeat/module
cp -r ./apache2 ./postfix

error.log用の設定は必要ないので削除する
cd postfix
rm -rf error

(logファイル名による)ディレクトリ名を変更する
mv access mail

Postfix用モジュールのファイル構成

準備編」にて説明しました通り以下のような構成でモジュールのファイルを配置します。

/usr/share/filebeat/
   `- module/
        `- postfix/
             |- module.yml
             `- mail/
                  |- manifest.yml
                  |- config/
                  |    `- mail.yml
                  `- ingest/
                       `- default.json 
                                        説明
manifest.yml モジュール関連のファイルパスつまりingest/default.jsonなどの設定を記述します
config/mail.yml Filebeatへの入力ファイル設定(Postfixのログファイルパス)を生成するテンプレートを記述。Filebeatの開発言語であるGOのテンプレート機能を利用します。今回は特に変更しません
module.yml ダッシュボード(Kibana)の設定を記述するファイルですが今回はダッシュボードは扱わないのでフィールドの名前だけ変更します
ingest/default.json Elasticsearch/Ingestノードへ注入するPipeline設定(プロセッサの設定)を記述します。PostfixモジュールではGrok、Date、Remove、Dropプロセッサを利用しますのでその設定を行います

manifest.ymlの設定

manifest.yml
module_version: 1.0

var:
  - name: paths
    default:
      # Postfixのログファイルパス(FilebeatへのInputソース)
      - /var/log/mail.log*

# Ingestノードのパイプライン設定ファイルパス
ingest_pipeline: ingest/default.json

# 入力ソースの設定ファイルパス
input: config/mail.yml

requires.processors:

config/mail.ymlの設定

Apache用モジュールからコピーしたまま変更しません。

config/mail.yml
type: log
paths:
{{ range $i, $path := .paths }}
 - {{$path}}
{{ end }}
exclude_files: [".gz$"]

module.yml

ID値だけ変更しておきます。

module.yml
dashboards:
- id: Filebeat-Postfix-Dashboard

ingest/default.json

Ingestノードに注入するPipeline設定を記述します。

Ingestノードのパイプライン(プロセッサ)の設定

Postfix用のログメッセージをパーシングしてJSON形式へ変換します。以下のプロセッサを利用します。
filebeat_json5.png

                                       説明
Grokプロセッサ ログメッセージのテキストデータをパーシングしてJSON形式へ変換するプロセッサ。
パース形式を正規表現を組み合わせたパターンで記述するだけでOKです
Dateプロセッサ PostfixログのSyslog形式タイムスタンプからISO8601形式へ変換します
Removeプロセッサ 不要な情報を削除。
Grokによってパーシングされた後で不要なログメッセージ情報をElasticsearchへ保存する前に削除します
Dropプロセッサ 採取対象外のログをElasticsearchへ保存する前に削除します

設定の全体は以下の通りとなります。それぞれのプロセッサ設定について説明していきます。

ingest/default.json
{
  "description": "Pipeline for parsing postfix mail.log.",
  "processors": [{
    "grok": {
      "field": "message",
      "patterns":[
        "%{SYSLOGTIMESTAMP:postfix.mail.time} %{DATA:postfix.mail.mail_server} postfix/%{DATA:postfix.mail.process}\\[%{NUMBER:postfix.mail.pid}\\]: %{BASE16NUM:postfix.mail.queue_id}: %{LOGLEVEL}: header %{DATA:postfix.mail.header}: %{DATA:postfix.mail.header_display_name} <%{DATA:postfix.mail.header_from_email}> from %{DATA:postfix.mail.remote_host}\\[%{IP:postfix.mail.remote_ip}\\]; from=<%{DATA:postfix.mail.from_email}> to=<%{DATA:postfix.mail.to_email}>",
        "%{SYSLOGTIMESTAMP:postfix.mail.time} %{DATA:postfix.mail.mail_server} postfix/%{DATA:postfix.mail.process}\\[%{NUMBER:postfix.mail.pid}\\]: %{BASE16NUM:postfix.mail.queue_id}: %{LOGLEVEL}: header %{DATA:postfix.mail.header}: %{DATA:postfix.mail.mime_type};(\\?)* name=\"%{DATA:postfix.mail.mime_name}\" from %{DATA:postfix.mail.remote_host}\\[%{IP:postfix.mail.remote_ip}\\]; from=<%{DATA:postfix.mail.from_email}> to=<%{DATA:postfix.mail.to_email}>",
        "%{SYSLOGTIMESTAMP:postfix.mail.time} %{DATA:postfix.mail.mail_server} postfix/%{DATA:postfix.mail.process}\\[%{NUMBER:postfix.mail.pid}\\]: %{BASE16NUM:postfix.mail.queue_id}: %{LOGLEVEL}: header %{DATA:postfix.mail.header}: %{DATA:postfix.mail.mime_type};(\\?)* filename=\"%{DATA:postfix.mail.mime_filename}\" from %{DATA:postfix.mail.remote_host}\\[%{IP:postfix.mail.remote_ip}\\]; from=<%{DATA:postfix.mail.from_email}> to=<%{DATA:postfix.mail.to_email}>"
        ],
      "ignore_missing": false,
      "ignore_failure": false
    }
  }, {
      "date": {
        "field": "postfix.mail.time",
        "target_field": "postfix.mail.time",
        "formats": [
            "MMM  d HH:mm:ss",
            "MMM dd HH:mm:ss"
        ],
        "ignore_failure": true
      }
  }, {
      "remove": {
        "field": "message",
        "ignore_missing": true,
        "ignore_failure": true
      }
  }],
  "on_failure" : [{
    "drop" : {
      "ignore_failure" : true
    }
  }]
}

GrokプロセッサによるログメッセージのJSON変換

GrokプロセッサによりFilebeatから転送された(b)JSONドキュメント内の_source.messageフィールドのログメッセージは、(c)JSONドキュメントのようにパーシングされ_source.postfixのJSONオブジェクト形式へ変換されます。

(b)JSON(変換処理前)
{
  "_index" : "filebeat-6.6.0-2019.xx.xx",
  "_type" : "doc",
  "_id" : "SKMrAmoB5yTtiEEfLG6k",
  "_score" : 1.0,
  "_source" : {
  ......
    "message" : "Apr  21 08:01:14 dmz_server postfix/cleanup[6615]: 4B19A1000EB: warning: header Content-Type: image/png;? name=\"Test.png\" from unknown[192.168.0.xx]; from=<alice@example.com> to=<bob@example.com> proto=ESMTP helo=<[192.168.0.xx]>",
  ......
  }
}
(c)JSON(変換処理後)
{
  "_index" : "filebeat-6.6.0-2019.xx.xx",
  "_type" : "doc",
  "_id" : "SKMrAmoB5yTtiEEfLG6k",
  "_score" : 1.0,
  "_source" : {
  ......
    "postfix": {
      "mail": {
        "process": "cleanup",
        "to_email": "bob@example.com",
        "remote_ip": "192.168.0.xx",
        "from_email": "alice@example.com",
        "mime_type": "image/png",
        "header": "Content-Type",
        "pid": "2368",
        "mime_name": "Test.png",
        "time": "2019-04-20T23:01:14.000Z",
        "mail_server": "dmz_server",
        "queue_id": "304A6101243",
        "remote_host": "unknown"
      }
    },
  ......
  }
}

変換先のテンプレート定義

まずGrokプロセッサがインデクスへ格納するログ情報のJSON形式(_source.postfixオブジェクト)を定義します。

テンプレートはデフォルトでは/etc/filebeat/fields.ymlに定義されています。このファイルをmy_fields.ymlとしてコピーしPostfixモジュール用の定義を追加します(前回Squidモジュールの作業を行っている場合には同じファイルを利用してください)。

cd /etc/filebeat
cp fields.yml my_fields.yml

モジュール本体と同様にここでもApache用のテンプレート定義(- key: apache2)を雛形にして作業します。詳細については前回の「プロキシサーバ編」に説明していますのであわせて参照してください。

Postfix用モジュールのテンプレート定義

Postfix用モジュールの定義を/etc/filebeat/my_fields.ymlへ追加します。

/etc/filebeat/my_fields.yml
- key: postfix
  title: "postfix"
  description: >
    Postfix Module
  short_config: true
  fields:
    - name: postfix
      type: group
      description: >
        Postfix fields.
      fields:
        - name: mail
          type: group
          description: >
            Contains fields for the Postfix mail log.
          fields:
            - name: time
              type: keyword
              description: >
                log_time.
            - name: mail_server
              type: text
              description: >
                mail_server.
            - name: process
              type: keyword
              description: >
                process.
            - name: pid
              type: long
              description: >
                PID.
            - name: queue_id
              type: keyword
              description: >
                queue_id.
            - name: header
              type: keyword
              description: >
                header.
            - name: header_display_name
              type: text
              description: >
                header_display_name.
            - name: header_from_email
              type: text
              description: >
                header_from_email.
            - name: remote_host
              type: text
              description: >
                remote_host.
            - name: remote_ip
              type: keyword
              description: >
                remote_ip.
            - name: from_email
              type: text
              description: >
                from_email.
            - name: to_email
              type: text
              description: >
                to_email.
            - name: mime_type
              type: text
              description: >
                mime_type.
            - name: mime_name
              type: text
              description: >
                mime_name.
            - name: mime_filename
              type: text
              description: >
                mime_filename.

Grokプロセッサの詳細

Grokプロセッサによるログメッセージのパーシング結果を変換するJSON形式を定義できました。次にプロセッサの設定を以下の通り行います。

ingest/default.json
{
  "description": "Pipeline for parsing postfix mail.log.",
  "processors": [{
    "grok": {
      "field": "message",
      "patterns":[
        "%{SYSLOGTIMESTAMP:postfix.mail.time} %{DATA:postfix.mail.mail_server} postfix/%{DATA:postfix.mail.process}\\[%{NUMBER:postfix.mail.pid}\\]: %{BASE16NUM:postfix.mail.queue_id}: %{LOGLEVEL}: header %{DATA:postfix.mail.header}: %{DATA:postfix.mail.header_display_name} <%{DATA:postfix.mail.header_from_email}> from %{DATA:postfix.mail.remote_host}\\[%{IP:postfix.mail.remote_ip}\\]; from=<%{DATA:postfix.mail.from_email}> to=<%{DATA:postfix.mail.to_email}>",
        "%{SYSLOGTIMESTAMP:postfix.mail.time} %{DATA:postfix.mail.mail_server} postfix/%{DATA:postfix.mail.process}\\[%{NUMBER:postfix.mail.pid}\\]: %{BASE16NUM:postfix.mail.queue_id}: %{LOGLEVEL}: header %{DATA:postfix.mail.header}: %{DATA:postfix.mail.mime_type};(\\?)* name=\"%{DATA:postfix.mail.mime_name}\" from %{DATA:postfix.mail.remote_host}\\[%{IP:postfix.mail.remote_ip}\\]; from=<%{DATA:postfix.mail.from_email}> to=<%{DATA:postfix.mail.to_email}>",
        "%{SYSLOGTIMESTAMP:postfix.mail.time} %{DATA:postfix.mail.mail_server} postfix/%{DATA:postfix.mail.process}\\[%{NUMBER:postfix.mail.pid}\\]: %{BASE16NUM:postfix.mail.queue_id}: %{LOGLEVEL}: header %{DATA:postfix.mail.header}: %{DATA:postfix.mail.mime_type};(\\?)* filename=\"%{DATA:postfix.mail.mime_filename}\" from %{DATA:postfix.mail.remote_host}\\[%{IP:postfix.mail.remote_ip}\\]; from=<%{DATA:postfix.mail.from_email}> to=<%{DATA:postfix.mail.to_email}>"
        ],
      "ignore_missing": false,
      "ignore_failure": false
    }
  ......
}
                                       説明
field: message Grokプロセッサが処理するフィールド名。ログメッセージが設定されている(b)JSONドキュメントのmessageフィールドを指定します
patterns:[...] fieldで指定されたフィールド値のパーシング規則を正規表現を利用して記述します(詳細については前回の「プロキシサーバ編」を参照)
ignore_missing: false フィールドが存在しない場合にはログ採取の対象外としてDropプロセッサへ渡します
ignore_failure: false パーシング等に失敗した場合にはログ採取の対象外としてDropプロセッサへ渡します

設定の詳細についてはこちらを参照。

Grok patterns(パターン)の説明

Grokプロセッサの詳細については前回の「プロキシサーバ編」に説明していますので参照してください。

Postfixログパーシング用のGrok patterns(パターン)

Squidモジュールと同様にKibanaのGrok Debuggerを利用して作成したパターンが以下です。

%{SYSLOGTIMESTAMP:postfix.mail.time} %{DATA:postfix.mail.mail_server} postfix/%{DATA:postfix.mail.process}\\[%{NUMBER:postfix.mail.pid}\\]: %{BASE16NUM:postfix.mail.queue_id}: %{LOGLEVEL}: header %{DATA:postfix.mail.header}: %{DATA:postfix.mail.header_display_name} <%{DATA:postfix.mail.header_from_email}> from %{DATA:postfix.mail.remote_host}\\[%{IP:postfix.mail.remote_ip}\\]; from=<%{DATA:postfix.mail.from_email}> to=<%{DATA:postfix.mail.to_email}>
%{SYSLOGTIMESTAMP:postfix.mail.time} %{DATA:postfix.mail.mail_server} postfix/%{DATA:postfix.mail.process}\\[%{NUMBER:postfix.mail.pid}\\]: %{BASE16NUM:postfix.mail.queue_id}: %{LOGLEVEL}: header %{DATA:postfix.mail.header}: %{DATA:postfix.mail.mime_type};(\\?)* name=\"%{DATA:postfix.mail.mime_name}\" from %{DATA:postfix.mail.remote_host}\\[%{IP:postfix.mail.remote_ip}\\]; from=<%{DATA:postfix.mail.from_email}> to=<%{DATA:postfix.mail.to_email}>
%{SYSLOGTIMESTAMP:postfix.mail.time} %{DATA:postfix.mail.mail_server} postfix/%{DATA:postfix.mail.process}\\[%{NUMBER:postfix.mail.pid}\\]: %{BASE16NUM:postfix.mail.queue_id}: %{LOGLEVEL}: header %{DATA:postfix.mail.header}: %{DATA:postfix.mail.mime_type};(\\?)* filename=\"%{DATA:postfix.mail.mime_filename}\" from %{DATA:postfix.mail.remote_host}\\[%{IP:postfix.mail.remote_ip}\\]; from=<%{DATA:postfix.mail.from_email}> to=<%{DATA:postfix.mail.to_email}>
  • '['および']'は'\'でエスケープします。
  • ingest/default.jsongrok/patternsは配列型ですので複数パターンを同時に記述できます。
  • フィールド名は前回「プロキシサーバ編」のテンプレート定義で説明した通り、階層(ネスト)構造で指定します。
  • ingest/default.jsonへ設定する場合には'"'および'\'をさらに'\'でエスケープします。

DateプロセッサによるISO8601形式タイムスタンプの追加

Postfixのログで記録されるSyslog形式のタイムスタンプからISO8601形式タイムスタンプを生成し追加します。

{
  "description": "Pipeline for parsing postfix mail.log.",
  "processors": [{
  ......
  }, {
      "date": {
        "field": "postfix.mail.time",
        "target_field": "postfix.mail.time",
        "formats": [
            "MMM  d HH:mm:ss",
            "MMM dd HH:mm:ss"
        ],
        "ignore_failure": true
      }
  ......
  }],
  ......
}
                                       説明
field Syslogタイムスタンプのフィールド名を指定します
target_field 変換結果を書き込むフィールド名を指定します
formats 変換元のSyslog形式フォーマットを指定します
ignore_failure: true パーシング等でエラーが発生した場合に処理をスキップします

Removeプロセッサによる不要な情報の削除

不要または冗長な情報を削除します。

Removeプロセッサの設定

パーシングしたmessageフィールドは不要なため削除します。

ingest/default.json
{
  "description": "Pipeline for parsing postfix mail.log.",
  "processors": [{
  ......
  }, {
    "remove": {
      "field": "message",
      "ignore_missing": true,
      "ignore_failure": true
    }
  ......
  }],
  ......
}
                                       説明
field 削除するフィールド名を指定します
ignore_missing: true フィールド値が見つからない場合に処理をスキップします
ignore_failure: true エラーが発生した場合に処理をスキップします

詳細についてはこちらを参照。

Dropプロセッサによって採取対象外のログメッセージを削除

本記事の設定例では採取対象外のログメッセージを削除します。

Dropプロセッサの設定

ingest/default.json
{
  "description": "Pipeline for parsing postfix mail.log.",
  "processors": [{
  ......
  ......
  }],
  "on_failure" : [{
    "drop" : {
      "ignore_failure" : true
    }
  }]
}
                                       説明
ignore_failure: true エラーが発生した場合に処理をスキップします

詳細についてはこちらを参照。

Filebeatモジュールの設定手順

Postfix用のモジュールが完成しましたのでそれをdmz.example.comへデプロイします。

モジュールの設定ファイル作成

/etc/filebeat/
   `- modules.d/
       `- postfix.yml.disabled

こちらもApache用の設定ファイルを雛形にして多少変更するだけです。

cd /etc/filebeat/modules.d
cp apache2.yml.disabled postfix.yml.disabled
/etc/modules.d/postfix.yml.disabled
- module: postfix
  # Access logs
  mail:
    enabled: true

    # Set custom paths for the log files. If left empty,
    # Filebeat will choose the paths depending on your OS.
    #var.paths:

モジュールのテンプレート設定を追加

前回「プロキシサーバ編」で設定している場合には必要ありません。

/etc/filebeat/
   `- my_fields.yml

さきほど作成したmy_fields.ymlのパスをFilebeatの設定ファイル(/etc/filebeat/filebeat.yml)で変更します。以下のsetup.template.fieldsで説明します。

Filebeatの設定ファイルを修正

こちらも前回「プロキシサーバ編」で設定している場合には必要ありません。

/etc/filebeat/
   `- filebeat.yml
                           説明
hosts: ["log.example.com:9200"] Elasticsearchが動作するホストアドレスとポート番号を指定
filebeat.overwrite_pipelines: true Elasticsearchへの接続毎にIngestノードのパイプライン設定を注入(デバッグ用)
setup.template.enabled: true テンプレート設定の注入を有効化
setup.template.fields: "/etc/filebeat/my_fields.yml" テンプレート設定ファイルの場所を変更
setup.template.overwrite: true 既存のテンプレート設定を更新

詳細は/etc/filebeat/filebeat.reference.ymlを参照してください。

/etc/filebeat/filebeat.yml
hosts: ["log.example.com:9200"]

#運用時にはコメントアウト
filebeat.overwrite_pipelines: true

setup.template.enabled: true
setup.template.fields: "/etc/filebeat/my_fields.yml"
setup.template.overwrite: true

Filebeatを再起動します。

systemctl restart filebeat.service

モジュールの有効化

以上の設定作業が終わったらSquid用のモジュールを有効化します。

filebeat modules enable postfix

モジュールのテンプレート設定をElasticsearchへ注入

filebeat setup --template

モジュールのパイプライン設定をElasticsearchへ注入

filebeat setup --pipelines -modules postfix

補足

テンプレートの参照
curl -XGET http://log.example.com:9200/_template/filebeat-*?pretty 

テンプレートの削除
curl -XDELETE http://log.example.com:9200/_template/filebeat-*

パイプライン設定の参照
curl -XGET http://log.example.com:9200/_ingest/pipeline/filebeat-*?pretty 

パイプライン設定の削除
curl -XDELETE http://log.example.com:9200/_ingest/pipeline/filebeat-*

ログの取得
curl -XGET http://log.example.com:9200/filebeat-*/_search?pretty -H 'Content-Type: application/json' -d 
'{
  "query": {
    "match_all":{}
  },
  "size":100
}'

インデクスのリスト
curl http://log.example.com:9200/_cat/indices?v

registryファイルのクリア
rm /var/lib/filebeat/registry

Kibanaでログを確認

  • Management/Create Index Patternにて filebeat-*を指定してインデクスパターンを生成または更新(Refresh field list)。
  • Discoverにてsquid.access.*フィールドへパーシングされたログを確認できます。 kibana_postfix1.png kibana_postfix2.png

まとめ

JPCERT/CCによる「高度サイバー攻撃への対処におけるログの活用と分析方法」で推奨されるメールサーバのログ設定をもとにPostfixおよびElasticsearchを利用したログ解析基盤を構築してみました。

次回の記事ではWinlogbeatを利用してエンドポイントログ採取(Windows 10 PC)のコンフィグレーションを追加していきます。

「エンドポイントログ編(その1- 概要/Sysmon)」へ続く

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2