ApacheログをSIEM on Amazon OpenSearch Service で可視化してみた

皆さん、こんにちは。突然ですが、最近ログ分析という言葉をよく耳にしませんか?
IoTやセキュリティ対策の需要が増える昨今、ログデータから不正アクセスなどを検知し、 被害を最小限に抑えるためには、ログ分析は不可欠なソリューションとなります。 SIEM on Amazon OpenSearch Serviceは、そのソリューションの1つです。

基本的にはSIEM on Amazon OpenSearch Serviceが対応しているログであれば、比較的簡単に取り込むことができますが、 Apacheログなどはデフォルトでは対応していません。

今回は、カスタムで取り込む方法がありますので、共有させていただきたいと思います。

初めて SIEM on Amazon OpenSearch Serviceを利用される方を対象としています。

SIEM on Amazon OpenSearch Serviceについて

SIEM on Amazon OpenSearch Serviceの概要

SIEM on Amazon OpenSearch Serviceはセキュリティインシデントを調査するためのソリューションです。 Amazonのマルチアカウント環境下で、複数のログをSIEM on Amazon OpenSearch Serviceに集約し、下記のようにログ相関分析及び可視化することができます。 f:id:binrii:20220117152915p:plain

ログはAWS S3バケットに集約しておくだけで、自動的にSIEM on OpenSearch Serviceに取り込まれます。デフォルトで対応しているログデータの種類は、下記サイトにてご確認ください。

参考サイト:
siem-on-amazon-opensearch-service/README_ja.md at main · aws-samples/siem-on-amazon-opensearch-service · GitHub

今回は、デフォルトで対応していないApache(httpd)のアクセスログをSIEM on OpenSearch Serviceに取り込むために、若干のカスタマイズが必要となりました。

本記事で解説する内容

本記事では、EC2上で起動しているWebアプリケーションのApacheアクセスログをSIEM on Amazon OpenSearch Serviceに取り込む手順を記載します。解説する内容は、下記赤い枠部分となります。 水色部分は、SIEM on Amazon OpenSearch Serviceをデプロイした際に自動的に構築される部分です。

データの流れ: EC2アクセスログKinesis Data Firehose⇒S3⇒OpenSearch Service f:id:binrii:20220119154841p:plain

作業手順

1.前提条件

なお、作業手順はこちらのドキュメントをベースにご説明いたします。 github.com

2.CloudFormationデプロイ用のテンプレートをS3にアップロード

テンプレートアップロードの詳細手順について、上記サイトにてご確認ください。

2-1. AWSコンソール画面からテンプレートを格納するS3バケットを作成します。今回はバケット名を「aes-siem-output」にします。 f:id:binrii:20220116134904p:plain 2-2. S3へファイルをアップロードできる権限をEC2に付与します。 f:id:binrii:20220116135000p:plain 2-3. Tera TermでEC2にログインし、下記を実行します。

sudo yum groups mark install -y "Development Tools"  
sudo yum install -y amazon-linux-extras  
sudo amazon-linux-extras enable python3.8  
sudo yum install -y python38 python38-devel git jq  
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1

2-4.GitHubレポジトリから関連ソースコードをcloneします。

git clone https://github.com/aws-samples/siem-on-amazon-opensearch-service.git

下記のようにテンプレート一式がEC2にcloneされたことを確認できます。

[ec2-user@ip-10-0-0-50 ~]$ ls
siem-on-amazon-opensearch-service

2-5.環境変数を設定します。

export TEMPLATE_OUTPUT_BUCKET=aes-siem-output
export AWS_REGION=ap-northeast-1

2-6.AWS Lambda 関数のパッケージとテンプレートを作成します。

cd siem-on-amazon-opensearch-service/deployment/cdk-solution-helper
chmod +x ./step1-build-lambda-pkg.sh && ./step1-build-lambda-pkg.sh && cd ..
chmod +x ./build-s3-dist.sh && ./build-s3-dist.sh $TEMPLATE_OUTPUT_BUCKET

2-7.Amazon S3バケットへアップロードします。

aws s3 cp ./global-s3-assets s3://$TEMPLATE_OUTPUT_BUCKET/ --recursive --acl bucket-owner-full-control
aws s3 cp ./regional-s3-assets s3://$TEMPLATE_OUTPUT_BUCKET/ --recursive --acl bucket-owner-full-control

下記の通り、S3へアップされていることを確認できます。 f:id:binrii:20220116143852p:plain

3.SIEM on OpenSearch Serviceのデプロイ

3-1.CloudFormation作成へ移動し、「スタックの作成」をクリックします。 f:id:binrii:20220116151135p:plain 3-2.Amazon S3 URLにテンプレートsiem-on-amazon-opensearch-service.template「https://aes-siem-output.s3.ap-northeast-1.amazonaws.com/siem-on-amazon-opensearch-service.template」(※手順2.7)を記入し、「次へ」をクリックします。 f:id:binrii:20220116151214p:plain 3-3.スタックの名前とパラメータを記入し、「次へ」をクリックします。

項目名 説明
スタックの名前 aes-siem
AllowedSourceIpAddresses アクセスを許可するIPアドレス。複数アドレスはスペース区切り
GeoLite2LicenseKey Maxmindのライセンスキー。IP アドレスに国情報を付与
ReservedConcurrency es-loaderの同時実行数の上限値。今回はデフォルト10のまま
SnSEmail SIEM on OpenSearch Service で検知したアラートを SNS 経由で送信するメールアドレス

f:id:binrii:20220116150617p:plain 3-4. スタックオプションの設定は、デフォルトのままで、「次へ」をクリックします。 f:id:binrii:20220116151242p:plain 3-5. 確認画面で特に問題なければ、画面一番下のチェックを入れ、「スタック作成」をクリックします。 f:id:binrii:20220116151428p:plain f:id:binrii:20220116151437p:plain 大体30分前後で、スタックがcompleteになります。その間に、上記パラメータに記載したSnSEmailの宛先に、下記メールが届きます。メール本文の「Confirm subscription」をクリックすると、SNSサブスクリプションが作成されます。
▼承認メール f:id:binrii:20220116151515p:plain   ▼作成されたSNS サブスクリプション f:id:binrii:20220117153823p:plain ▼Completeになったスタック「aes-siem」
f:id:binrii:20220116151727p:plain
スタック「aes-siem」が完成後、計43個リソースが作成されます。そのうち、本記事の解説内容と関連しているリソースは下記の通りです。
▼S3バケット

ファイル名 説明
aes-siem-アカウントID-geo GeoIPダウンロード用 S3 バケット
aes-siem-アカウントID-log ログ用 S3 バケット
aes-siem-アカウントID-snapshot スナップショット用 S3 バケット

▼Lambda: f:id:binrii:20220116152959p:plainOpenSearch Service: f:id:binrii:20220116153031p:plain

4.Kinesis Data Firehoseの作成

4-1. S3バケット「aes-siem-アカウントID-log」(※手順3-5.)配下に、配信先のフォルダー(UserLogs/apache/httpd/)とエラー(error/)フォルダーを作成します。

4-2. Kinesis Data Firehose からS3にアクセスするIAMロール作成します。Kinesis Data Firehoseを作成する際に自動生成されますが、今回は事前にIAMロールを作成します。   ロール名:FirehosetoS3Role f:id:binrii:20220116153139p:plain ユースケースをEC2で作成した場合、信頼関係のServiceを「ec2.amazonaws.com」から「firehose.amazonaws.com」に編集します。 f:id:binrii:20220116153155p:plain

4-3. Kinesis Data Firehos作成に移動し、「配信ストリームを作成」をクリックします。 f:id:binrii:20220116153235p:plain

4-4. 作成画面で、下記内容を設定します。 それ以外の項目は、デフォルトのままで「Create delivery stream」をクリックします。

項目名 記入内容
Source Direct PUT
Destination Amazon S3
Delivery stream name PUT-S3-test
S3 bucket 「Browse」クリックし、aes-siem-アカウントID-logを選択
S3 bucket prefix – optional UserLogs/apache/httpd/
S3 bucket error output prefix – optional error/
Permissions existing IAM roleを選択し、「FirehosetoS3Role」を指定 |  

数分後、配信ストリーム「PUT-S3-test」が作成されていることを確認できます。 f:id:binrii:20220117141258p:plain

5.ログの取り込み

5-1. EC2のIAMロールに、下記権限を付与します。 f:id:binrii:20220116154328p:plain 5-2. Tera TermでEC2にログインし、下記2点を確認します。
httpdサービスが起動されていること
 もし起動されていなければ、httpdサービスを起動します。

sudo service httpd status

ApacheアクセスログがCombine形式になっていること

grep "access_log" /etc/httpd/conf/httpd.conf

5-3. Kinesisエージェントをインストールします。

sudo yum install –y aws-kinesis-agent

5-4. エージェント設定を編集します。

sudo vi /etc/aws-kinesis/agent.json

初期の状態は下記のようになっていると思います。 f:id:binrii:20220116154534p:plain 編集後:

{
  "cloudwatch.emitMetrics": false,
  "firehose.endpoint": "https://firehose.ap-northeast-1.amazonaws.com",

  "flows": [
    {
      "filePattern": "/var/log/httpd/access_log",
      "deliveryStream": "PUT-S3-test"
    }
  ]
}
項目名 記入内容
Firehose.endpoint 東京リージョンの場合、「https://firehose.ap-northeast-1.amazonaws.com」
filePattern Apacheアクセスログの対象ファイル
deliveryStream PUT-S3-test (※手順4-4.)

また、logFormatの設定もできますが、今回は元のフォーマットのままにします。
詳細設定は、下記にてご確認ください。 https://docs.aws.amazon.com/ja_jp/firehose/latest/dev/writing-with-agents.html#agent-config-settings

5-5. Kinesisエージェントサービスを起動し、ステータスを確認します。

sudo service aws-kinesis-agent start
sudo service aws-kinesis-agent status

5-6. Webからアクセスし、エージェントの実行ログからストリームへ配信状況を確認します。
「*** records sent successfully to destinations」ログが表示されていれば、正常に配信されています。

tail /var/log/aws-kinesis-agent/aws-kinesis-agent.log

f:id:binrii:20220116155516p:plain

数分後に、aes-siem-アカウントID /UserLogs/apache/httpd/配下にyyyy/mm/dd/unique-IDフォルダが作成され、「PUT-S3-test-」から始まるファイルが格納されます。 f:id:binrii:20220124143106p:plain

6.Lambdaにカスタマイズ用のファイルの作成

6-1. Lambdaコンソールを開き、「aes-siem-es-loader」を選択します。
6-2. 新規user.ini を作成します。 オリジナルファイルは下記からコピーできますが、今回は実際の環境に合わせてコードを少し変更しました。

https://security-log-analysis-platform.workshop.aws/ja/05-ingest-and-process-application-logs/05-6-ingest-logs-opensearch.html

今回デプロイしたコードは、下記となります。

[apache]
# S3の保存場所
s3_key = UserLogs/apache/httpd/.*/PUT-S3-test-*
# ファイルフォーマット
file_format = text
# ESのインデックス名
index_name = log-web-apache
# 名前付き正規表現でフィールドの抽出
log_pattern = ^(?P<remotehost>[^ ]+) (?P<rfc931>[^ ]+) (?P<authuser>[^ ]+) \[(?P<http_timestamp>[^\[\]]+)\] \"(?P<request_method>[^ ]+) (?P<request_path>.*) (?P<request_version>HTTP/.*)\" (?P<http_status>[^ ]+) (?P<http_bytes>[^ ]+) \"(?P<http_referer>.+)\" \"(?P<http_user_agent>.+)\"
# " ログの生成時刻を抽出
timestamp_key = http_timestamp
timestamp_format = %d/%b/%Y:%H:%M:%S %z
# ECS への正規化
# 正規化後のフィールドを列挙
ecs = source.ip user.name http.request.method url.path http.version http.response.status_code http.response.bytes
# 「正規化後 = オリジナルフィールド」 で定義
source.ip = remotehost
user.name = authuser
http.request.method = request_method
url.path = request_path
http.version = request_version
http.response.status_code = http_status
http.response.bytes = http_bytes
# GeoIP
geoip = source

f:id:binrii:20220116155743p:plain

コード内のS3_keyは取り込み対象ログを定義します。AWSログ以外のログ(例:今回Apacheアクセス)を取り込む場合、対象ファイルを自動的に認識しないため、ファイル名のフォーマットまで指定します。
また、index_nameには、OpenSearch Dashboardsに表示するインデックス名を指定します。

6-3. 「deploy」ボタンをクリックし、Lambdaを更新します。  

数分後にアクセスログがSIEMに取り込まれます。 CloudWatchの/aws/lambda/aes-siem-es-loader配下のログから正常処理されるかどうかも確認できます。

f:id:binrii:20220116160116p:plain

▼正常に取り込まれた場合、下記のログ情報が出力されます。 f:id:binrii:20220124143504p:plain

▼取込を失敗した場合、下記のログ情報が出力されます。 f:id:binrii:20220116160215p:plain

7.OpenSearch Service Dashboardsでログの可視化

7-1. OpenSearch Dashboardsにログインします。 CloudFormationの「出力」タブに表示されているURLをクリックし、ユーザー名とパスワードでログインします。 f:id:binrii:20220117142833p:plain

f:id:binrii:20220118203234p:plain

7-2. Indexを作成します。 左ペインのManagementからStack Managementをクリックします。 f:id:binrii:20220124145413p:plain メニューからIndex Patternsをクリックすると、SIEM on Amazon OpenSearch Serviceがデフォルトで作られたIndex一覧が表示されます。「Create index pattern」をクリックします。 f:id:binrii:20220116160659p:plain Index作成Step1画面で、「log-web*」を記入し、「log-web-apache-2022-01」(※手順6-2.)が表示されます。「Next step」をクリックします。 f:id:binrii:20220116160714p:plain Step2画面で、Time fieldで「@timestamp」を選択し、「Create index pattern」をクリックします。 f:id:binrii:20220116160730p:plain 7-3. Discover画面で作成されたindex pattern「log-web*」を選択し、転送されたログが正しく表示されていることを確認できます。 今週のお題「現時点での今年の漢字

f:id:binrii:20220124142422p:plain 7-4. メニューからVisualizationsを作成します。 f:id:binrii:20220116160803p:plain 下記はVisualizationsサンプルです。 f:id:binrii:20220117144405p:plain 7-5. メニューDashboardsから上記作成したVisualizationsを追加し、ダッシュボードを作成します。 f:id:binrii:20220117145341p:plain

以上、ApacheログをSIEM on Amazon OpenSearch Service で可視化作業が完了しました。

番外編

  • クリーンアップ
    • CloudFormationからスタックaes-siemを削除します。
    • OpenSearch Serviceドメインを削除します。
    • Amazon S3バケットを削除します。
    • Kinesis 配信ストリーム「PUT-S3-test」を削除します。
    • その他、EC2など停止or終了します。
    • 再デプロイする予定がある場合、手順2で用意したS3バケット「aes-siem-output」及び中身の一式をそのまま残した方が良いかと思います。そうすると、再デプロイする場合、直接手順3からスタートできます。
    • KMSカスタマーマネジメントを削除します、 KMS削除はスケジュール(7~30日)設定でしか削除できないため、すぐに再デプロイする場合、下記コマンドでKMS CMKのエイリアスを削除し、その後、スケジュールを設定すれば問題ありません。 f:id:binrii:20220116161439p:plain
export AWS_DEFAULT_REGION=ap-northeast-1
aws kms delete-alias --alias-name "alias/aes-siem-key"
  • エラー対処
    エラーメッセージ:Caused by: java.nio.file.AccessDeniedException: /var/log/httpd
    対処1:IAMロールの権限付与問題ないか確認
        Kinesis関連権限は何種類かありますが、本記事に指定されているのは、
       「AmazonKinesisFirehoseFullAccess」です。
    対処2:権限変更
sudo chmod 755 /var/log/httpd/
sudo chmod 644 /var/log/httpd/*

最後に

ログ分析について、EC2⇒CloudWatch⇒Lambda⇒OpenSearchや、EC2⇒CloudWatch⇒Kinesis Data Firehose⇒S3などのパターンも検証しましたが、本記事内容の実装は、最も簡単でシンプルだと感じています。 また、AWSサービス以外のログデータを他のログと相関分析する必要がある場合、本記事のように、対象ログを一旦S3に取り込めば、自動的にOpenSearch Serviceに取り込むこともできます。

引き続きデータの活用とログ分析基盤の構築を楽しみつつ、当該ブログにて発信していきますのでよろしくお願いします。

また、もし、AWSおよびデータ・セキュリティ関連でお困り、ご相談がありましたら、弊社JTPまでご連絡いただけますと幸いです。

www.jtp.co.jp