<-- mermaid -->

AWS Security HubとSlackを利用して、セキュリティ状況の監視運用を効率化したお話

はじめに

初めまして!ソーシャル経済メディア「NewsPicks」SREチーム・新卒エンジニアの樋渡です。今回は「AWS Security Hub」と「Slack」を用いて、弊社で利用しているAWSリソースの監視運用を効率化したお話です。

お話の内容

年々増加するサイバー攻撃に対抗するため、セキュリティ対策は日々重要度が増してきています。 そこで弊社で利用しているAWSのリソースに対して、各種セキュリティイベントの収集ができるAWS Security Hubを利用することで、セキュリティ状態の可視化と迅速な対応がしやすい運用を行い、セキュリティ状態の現状把握から始めることにしました。特にNIST CSFの「検知」部分の運用について整備した内容となっています。

NIST Cyber Security Frameworkについて

皆さん、「NIST Cyber Security Framework(CSF)」ってご存知でしょうか。

「NIST Cyber Security Framework(CSF)」とは、NIST(米国国立標準技術研究所)が公開している「重要インフラのサイバーセキュリティを向上させるためのフレームワーク」です。ここでいうフレームワークとは、決まった取り組みを指し、サイバーセキュリティ対策を行うにあたってのガイドラインとなります。つまり、セキュリティ対策を実行するにあたっての、参考書みたいなものです。 NIST CSF(2.0)では、サイバーセキュリティ対策とは以下の6つの機能で構成されています。

NIST CSF 2.0

  • 「識別」:保有している資産の洗い出しを行い、継続的な更新を行っている状態
  • 「防御」:洗い出した資産を保護するための具体的な防御策を実施している状態
  • 「検知」:サイバー攻撃の兆候や脆弱性を事前に検知できるようになっている状態
  • 「対応」:検知のフェーズで検出されたセキュリティインシデントへの対応が管理され、調査が実施されている状態
  • 「復旧」:インシデントが起こった際に、事業を継続させるべく早急な復旧ができる状態
  • 「統治」:現状から分析し各項目に対して取り組むべき優先度を決められているかどうか

サイバーセキュリティ対策では、これら6つの機能全てが実行・運用されていることが理想的なのです。

AWS Security Hubとは

Amazon Web Service(AWS)には、サイバーセキュリティ対策に役立つ様々なサービスが存在します。例えば、「Amazon GuardDuty」・「AWS Trusted Advisor」・「Amazon Inspector」などです。これらのサービスは総じてAWS上のリソースを監視し、リソース内に潜む脅威やパフォーマンス問題の検出を自動で行なってくれます。しかし、AWS Security Hubは脅威の検出を行うサービスではありません。では、AWS Security Hubは何をするのか…気になりますね。

AWS Security Hubは、AWSのセキュリティサービスが集めたセキュリティデータを集約し、一元的に可視化するサービスです。つまり、組織が抱える問題や脅威をダッシュボード上に集約し、見て分かりやすいようにまとめてくれているサービスです。また、集めたセキュリティデータから、セキュリティ基準のベストプラクティスに則った運用ができているのかを診断できる機能も持っています。Security Hubを使えば、それぞれのセキュリティサービスにアクセスして問題が起こっていないかを確認する手間から解放され、組織がセキュリティ対策をしっかり行えているかの参考にすることができます。

Security Hubについて

では、Security Hubを使えばセキュリティ対策が万全になるのかと言われたらそうではありません。NIST CSFを見ると、セキュリティ対策とはそれぞれの機能が運用され続けていないといけないのです。「検知」の次には「対策」があるように、ただ検知しただけでは対策にはなりません。Security Hubを利用し、適切に運用し「対策」に繋げてこそ意味をなします。

抱えていた課題

弊社では、以前よりAWS Security Hubを利用して各種セキュリティサービスの監視を行なっていました。以前の運用方法は、週に一度Security Hubのダッシュボードを確認し、前の週と比べて新しく検出された問題はないか等の確認を人力で行うものでした。しかし、この運用方法には以下のような問題があります。

  • 週に1度の定点観測なので、重要な問題が検知されても認識までにタイムラグが発生する
  • 運用にかかる時間などのコスト問題
  • 人力で内容を見比べていくので、人的なミスのリスクがある

これらの課題を抱えたままでは、NIST CSFで言うところの「対策」につなげることは難しく、検知されていたけど認識が遅れて手遅れになってしまったといったことが起こるかもしれません。この課題を解決し、適切に「検知」のフェーズを運用する運用方法を考える必要がありました。

どうやって課題を解決していくか

では、課題に対してどうやって課題を解決していくのかについてです。今回挙げた課題の中で、最も問題なのは問題の検知から認識までのタイムラグです。事業を継続的に運用していくにあたって、重要なインシデントやリスクは検知されたタイミングで即座に認識し、対策をしていくのが理想です。そこで、今回は検知されてから認識までのタイムラグの解決に焦点を当てて解決策を考えました。

どうやってタイムラグをなくすのか、シンプルに考えるなら週に一度の定点観測を毎日すれば良さそうです。ですが、定点観測を実施すればするほど人的なコストや時間的なコストが増えていきます、これではコスト的な観点から継続的な事業の運用に支障が出かねません。そこで、Security Hubの監視作業を人の手から離すことにしました。

具体的には、AWS EventBridgeを利用しSecurity Hubの検知結果が出たらSlackに通知するようにします。フロー図としては以下のような感じです。

Security Hub通知のフロー図

この仕組みを実装すれば、週一の定点観測の実施をする必要がなくなり、監視作業が人の手を離れるので人的なミス発生リスクが減り、かつSlackに即時通知されるので検知から認識までのタイムラグをなくすことができます!

利用するAWSサービス

今回の通知の仕組みを実装するために利用したAWSサービスは以下の通りです。

  • AWS Security Hub
  • AWS EventBridge
  • AWS Lambda
  • AWS Step Functions

AWS LambdaはEventBridgeから検出結果を受け取り、通知データを整形してSlackに送るために使用しました。AWS Step Functionsの利用目的は後述します。また、今回のリソースはAWS CDKを利用して実装・管理を行いました。

ここからは実装したリソースの実装方法についてお話しします。

EventBridgeの実装

まずは、EventBridgeの実装です。今回検出するEventの要件は以下のようになります。

  • 重要度ラベルが「CRITICAL」・「HIGH」の2つ
  • 過去に通知した内容は通知しない
  • ステータスが「FAILED」のもの

ここでのポイントは、ステータスを変更するStep FunctionsとSlack通知を行うLambda関数のそれぞれをトリガーしているところです。 Step FunctionsとLambda関数それぞれにEventが検知されたことを渡します。

この要件を満たすようにコード実装すると、コードは以下のようになります。

       new events.Rule(this, "NotifyTest", {
            ruleName: "Test_Notify_Rule",
            eventPattern: {
                source: ["aws.securityhub"],
                detailType: ["Security Hub Findings - Imported"],
                detail: {
                    findings: {
                        Compliance: { Status: ["FAILED"] },
                        Workflow: { Status: ["NEW"] },
                        Severity: { Label: ["HIGH", "CRITICAL"] },
                    },
                },
            },
            targets: [new eventtargets.SfnStateMachine(stateMachine), new eventtargets.LambdaFunction(notifyFunction)],
        });

AWS Step Functionsの実装

次にStep Functionsの利用目的と実装についてです。利用目的としては、Security Hubの通知済みステータスを「NEW」から「NOTIFIED」に変更してあげるためです。EventBridgeで検出し、Lambdaを通して通知しただけでは、通知済みステータスを変更することはできません。通知済みステータスが「NOTIFIED」のままだと、EventBridgeで何度も検出され続けることとなります。ここでは既に周知された脅威ではなく、新規で検出された脅威の認識を早めたいことを目的とするため、一度通知されたものは通知しないようにしてあげる必要があります。

なのでStep Functionsを使用しステータス変更を行うAPIを呼び出してあげます。

       const changeStatusTask = new sfn.CustomState(this, "change securityhub state", {
            stateJson: {
                Type: "Task",
                Resource: "arn:aws:states:::aws-sdk:securityhub:batchUpdateFindings",
                Parameters: {
                    FindingIdentifiers: [
                        { "Id.$": "$.detail.findings[0].Id", "ProductArn.$": "$.detail.findings[0].ProductArn" },
                    ],
                    Workflow: { Status: "NOTIFIED" },
                },
                ResultPath: "$.results.batchUpdateFindings",
            },
        });

完成したStep Functionsのステートマシン

Lambdaの実装

最後にLambdaの実装についてです。Lambdaでは、Event BridgeからSecurity Hubの検出結果を受け取り、必要なデータを抜き取ってSlack通知するデータを作成していきます。

//EventBridgeから受けるjsonデータの項目を指定します。
type SecurityHubNotifyEvent = EventBridgeEvent<
    "Security Hub Notify",
    // see https://docs.aws.amazon.com/ja_jp/securityhub/latest/userguide/securityhub-findings-format-syntax.html
    {
        findings: {
            AwsAccountId: string;
            CreatedAt: string;
            Description: string;
            Severity: { Normalized: number; Label: string; Original: string };
            Compliance: { SecurityControlId: string };
            UpdatedAt: string;
            Title: string;
            Region: string;
            Resources: { Id: string }[];
        }[];
    }
>;
//メッセージを生成する関数
function createSecurityHubfindingsMessage(args: {
    accountId: string;
    controlId: string;
    createdAt: string;
    description: string;
    label: string;
    region: string;
    resourceIds: string;
    title: string;
    updatedAt: string;
}): IncomingWebhookSendArguments {
    const { accountId, controlId, createdAt, description, region, resourceIds, label, title, updatedAt } = args;

    return {
        username: `${process.env.AWS_LAMBDA_FUNCTION_NAME}`,
        icon_emoji: ":aws-security-hub:",
        attachments: [
            {
                color: "warning",
                author_name: "Security Hub Error Notify",
                title: `:eyes: Security Hub Findings | ${region} | Account: ${accountId}`,
                title_link: `得られたデータからSecurity Hubのダッシュボード画面へと遷移するLinkを生成して記述`,
                fields: [
                    { title: "", value: title, short: false },
                    { title: "詳細:", value: description, short: false },
                    { title: "First Seen", value: createdAt, short: false },
                    { title: "Last Seen", value: updatedAt, short: false },
                    { title: "Affected Resource", value: resourceIds, short: false },
                    { title: "Severity", value: label, short: false },
                ],
                footer: "send from Lambda Function triggered by EventBridge",
            },
        ],
    };
}

上記のコードでメッセージを生成したら、Slack に通知してあげるだけですね!

実装後の運用

実際にSecurity Hub通知を実装した後の運用についてです。今回実装してみて以下のような変化がありました。

  • セキュリティーリスクのあるリソースの検知→認識までの時間が減少
  • 認識までの時間が減少したので、結果として対応までの速度が上がった

この通知により、以前と比べてより効率よくタイムラグの少ない監視運用ができるようになり、SREチームでも毎日の朝会でSlackチャンネルを確認するだけでチェックできるようになりました!週次のチェックが日次になったことでコンプライアンス違反の対象リソースが作成されてから間を開けずに担当チームにエスカレーションできるようになったため、『対応』についても初動のフットワークが軽くなりました。

まとめ

今回はセキュリティ対策の「検知」を担う部分としてAWS Security Hubを活用してセキュリティ状況の監視運用を効率化したお話でした。 あくまで一例のためこの運用が正しいと言っている内容ではありません。 事業の継続的な運用のためにまだまだ改善していきたいと思います!最後まで読んでいただきありがとうございました!

Page top