コンテンツにスキップ

アプリケーションデータ安全性@AWS

はじめに

本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。


01. ネットワークレイヤー

OSI層とAWSリソースの対応関係

OSI層とAWSリソースの対応関係を以下に示す。

AWSリソースごとにセキュリティを考慮する。

OSI層 OSI層の番号 対応するAWSリソース
アプリケーション層 L7 ALB、AWS EC2、AWS RDS、AWS Route53、S3
プレゼンテーション層 L6 同上
セッション層 L5 同上
トランスポート層 L4 セキュリティグループ、NLB
ネットワーク層 L3 Internet Gateway、AWS NAT Gateway、Transit Gateway
データリンク層 L2 AWS VPC、サブネット
物理層 L1 仮想化のため、意識しなくても良い。


02. L2の防御

L2の防御方法

L2の攻撃をAWS VPCやプライベートサブネットで防御する。

例えば、システムのコンポーネントごとに異なるプライベートサブネット (アプリ、DB、外部オンプレシステムへのプロキシ) を設ける。

これにより、いずれかのコンポーネントに侵入されても、他コンポーネントへの侵入を最小限に防げる。

なお、パブリックサブネットにはAWS EC2は置かない。


推奨されるCIDRブロック

1個のAWS VPC内には複数のサブネットが入る。

そのため、サブネットのCIDRブロックは、サブネットの個数だけ含めなければならない。

また、AWS VPCが持つCIDRブロックから、AWS VPC内の各AWSリソースにIPアドレスを割り当てていかなければならず、AWS VPC内でIPアドレスが枯渇しないようにする。

RFC1918では、以下のCIDRブロックが推奨である。

RFC1918推奨のCIDRブロック IPアドレス 個数
10.0.0.0/8 10.0.0.010.255.255.255 16777216
172.16.0.0/12 172.16.0.0172.31.255.255 1048576
192.168.0.0/16 192.168.0.0192.168.255.255 65536


AWS VPCによる防御

▼ AWS VPC全体のCIDRブロック

あらかじめ、会社内の全てのアプリケーションのCIDRブロックをスプレッドシートなどで一括で管理しておく。

この時、CIDRブロックと、これの開始IPアドレスと終了IPアドレスをメモしておくと良い。

各アプリケーション間でTransit Gatewayやピアリング接続を実行する可能性がある場合は。

拡張性を考慮して、アプリケーション間のCIDRブロックは重ならないようにしておく必要がある。

例えば、以前に開発したアプリケーションが10.200.47.0までを使用していた場合、10.200.48.0から使用を始める。

また、AWS VPCで許可されるIPアドレスの個数は最多65536個 (/16) で最少16個 (*.*.*.*/28) であり、実際は512個 (*.*.*.*/23) ほどあれば問題ないため、10.200.48.0/23を設定する。


サブネットによる防御

▼ サブネット分割のメリット

サブネットを分割することにより、他のサブネットのネットワーク障害の影響を防いだり、サブネット間のアクセスを制限できる。

▼ 各サブネットのCIDRブロック

AWS VPCのIPアドレスの最初から、パブリックサブネットとプライベートサブネットを割り当てる。

この時、AWS VPC内の各AWSリソースの特徴に合わせて、CIDRブロックを割り当てる。

例えば、AWS VPCの最初のIPアドレスを10.0.0.0とした場合は、1つ目のパブリックサブネットのサブネットマスクは、10.0.0.0から始める。

パブリックサブネットとプライベートサブネットを冗長化する場合は、AWS VPCのIPアドレス数をサブネット数で割って各サブネットのIPアドレス数を算出し、CIDRブロックを設定する。

例えば、AWS VPCのサブネットマスクを/16としている場合は、各サブネットのサブネットマスクは/24とする。

一方で、AWS VPCを/23としている場合は、各サブネットは/27とする。

また、各サブネットのCIDRブロックを同じにする必要はなく、アプリケーションが稼働するサブネットにIPアドレス数がやや多くなるようにし、代わりに、DBの稼働するサブネットのIPアドレスを少なくするような設計でも良い。

AWSリソース 最低限のIPアドレス数
ALB ALB当たり8
AutoScaling 自動水平スケーリング時のAWS EC2最大数と同じ個数
AWS VPCエンドポイント AWS VPCエンドポイント当たり、IPアドレス1
AWS ECS、AWS EKS Elastic Network Interface 数と同じ個数
Lambda Elastic Network Interface 数と同じ個数

▼ アクセスタイプ別の命名

パブリックネットワークとの通信の遮断具合から名前をつける。

名前 種類 役割 配置例
publicサブネット パブリック 非武装地帯として動作する。Internet Gatewayを介して、パブリックネットワークからのリクエストを待ち受ける。 ALB、AWS NAT Gateway
protectedサブネット プライベート 内部ネットワークとして動作する。パブリックネットワークからアクセスできず、同じAWS VPC内からのリクエストのみを待ち受ける。また、publicサブネットのAWS NAT Gatewayを介してリクエストを送信する。 AWS EC2、Fargate
privateサブネット プライベート 内部ネットワークとして動作する。パブリックネットワークからアクセスできず、前述のprotectedサブネット内からのリクエストのみを待ち受ける。また、リクエストを送信しない。 AWS RDS、Redis

subnet_accsess-type

▼ コンポーネントタイプ別の命名

subnet_component-type

配置するコンポーネントの種類に関する名前をつける。

名前 種類 役割 配置例
frontendサブネット パブリック 非武装地帯として動作する。L7ロードバランサー、ルーター、踏み台サーバー、を配置する。 ALB、AWS NAT Gateway
applicationサブネット プライベート 内部ネットワークとして動作する。appサーバー、リバースプロキシサーバー、を配置する。 AWS EC2、Fargate
datastoreサブネット プライベート 内部ネットワークとして動作する。dbサーバーを配置する。 AWS RDS、Redis


ルートテーブルによる防御

route-table

▼ プライベートサブネットのリクエストをパブリックネットワークに公開する場合

上の図中で、サブネット3にはルートテーブル2が紐付けられている。

サブネット3内の宛先のプライベートIPアドレスが、10.0.0.0/16の範囲内にあれば、リクエストと見なし、local (AWS VPC内の他サブネット) を宛先に選択する。

一方で、0.0.0.0/0 (local以外の全IPアドレス) の範囲内にあれば、リクエストと見なし、Internet Gatewayを宛先に選択する。

Destination (プライベートCIDRブロック) Target
10.0.0.0/16 (AWS VPCのCIDRブロック) local
0.0.0.0/0 Internet Gateway

▼ プライベートサブネットのリクエストをAWS VPC内に閉じる場合

上の図中で、サブネット2にはルートテーブル1が紐付けられている。

サブネット2内の宛先のプライベートIPアドレスが、10.0.0.0/16の範囲内にあれば、リクエストと見なし、local (AWS VPC内の他サブネット) を宛先に選択する。

一方で、範囲外にあれば通信を破棄する。

Destination (プライベートCIDRブロック) Target
10.0.0.0/16 (AWS VPCのCIDRブロック) local

▼ プライベートサブネットのリクエストを同一サブネット内に閉じる場合

プライベートサブネットでネットワークを完全に閉じる場合、ルートテーブルにサブネットのCIDRブロックを設定する。

Destination (プライベートCIDRブロック) Target
10.0.0.0/24 (サブネット1のCIDRブロック) local


03. L3の防御

L3の防御方法

L3の攻撃をセキュリティグループやTransit Gatewayで防御する。


03-02. セキュリティグループ

セキュリティグループによる防御

L3の攻撃をセキュリティグループで防御する。

例えば、AWS EKSのNodeグループごとに異なるセキュリティグループを紐づけている。

ネットワークに公開するNodeグループのセキュリティグループでは、特定の送信元IPアドレスからのアクセスのみを許可する。

公開しないNodeグループでは、他のNodeグループのAWS EC2からのみアクセスを許可する。

これらにより、インターネットからは信頼できるクライアントからのアクセスのみを受信し、Nodeグループ間でも最小限のアクセスのみに制限できる

なお、ACLでもL3を防御できるが、ネットワークが複雑になることを防ぐためにACLでは通信制限は採用しなくてもよい。

セキュリティグループ (インバウンド) による防御

▼ アプリケーションAWS EC2の場合

ALBに割り振られる可能性のあるIPアドレスを許可するために、ALBのセキュリティグループID、またはサブネットのCIDRブロックを設定する。

タイプ プロトコル ポート ソース 説明
HTTP TCP 80 ALBのセキュリティグループID HTTP access from ALB
HTTPS TCP 443 踏み台AWS EC2のセキュリティグループID SSH access from bastion AWS EC2

▼ 踏み台AWS EC2の場合

タイプ プロトコル ポート ソース 説明
SSH TCP 22 社内のグローバルIPアドレス SSH access from global ip address

▼ EFSの場合

AWS EC2に割り振られる可能性のあるIPアドレスを許可するために、AWS EC2のセキュリティグループID、またはサブネットのCIDRブロックを設定する。

タイプ プロトコル ポート ソース 説明
NFS TCP 2049 AWS EC2のセキュリティグループID NFS access from app AWS EC2

▼ AWS RDSの場合

AWS EC2に割り振られる可能性のあるIPアドレスを許可するために、AWS EC2のセキュリティグループID、またはサブネットのCIDRブロックを設定する。

タイプ プロトコル ポート ソース 説明
MYSQL/Aurora TCP 3306 AWS EC2のセキュリティグループID MYSQL access from app AWS EC2

▼ Redisの場合

AWS EC2に割り振られる可能性のあるIPアドレスを許可するために、AWS EC2のセキュリティグループID、またはサブネットのCIDRブロックを設定する。

タイプ プロトコル ポート ソース 説明
カスタムTCP TCP 6379 AWS EC2のセキュリティグループID TCP access from app AWS EC2

▼ ALBの場合

AWS CloudFrontと連携する場合、AWS CloudFrontに割り振られる可能性のあるIPアドレスを許可するために、全てのIPアドレスを許可する。

代わりに、AWS CloudFrontにAWS WAFを紐付け、ALBの前でIPアドレスを制限する。

AWS CloudFrontとは連携しない場合、ALBのセキュリティグループでIPアドレスを制限する。

タイプ プロトコル ポート ソース 説明
HTTP TCP 80 0.0.0.0/0 HTTP access from AWS CloudFront
HTTPS TCP 443 0.0.0.0/0 HTTPS access from AWS CloudFront

▼ NLBの場合

NLBはセキュリティグループをサポートしていない。

そのため、NLBのルーティング先 (AWS EC2など) でファイアーウォールを設定する必要がある。

▼ AWS VPCエンドポイント

AWS VPC内からAWS VPC外への通信は、AWS VPCエンドポイントで安全に通信する。

例えば、AWS EC2 NodeからAWS VPC外AWSリソースへの通信では、AWS VPCエンドポイントを使用する。

AWS VPCエンドポイントのセキュリティグループでは、AWS VPCのCIDRからのアウトバウンド通信のみを許可するとよい。


セキュリティグループ (アウトバウンド) による防御

▼ ALBの場合

ALBからAWS EC2にリクエストをルーティングする場合、特定のAWS EC2のみへのルーティングを許可するために、アウトバウンドのルールでAWS EC2のセキュリティグループIDを設定する。

タイプ プロトコル ポート 宛先 説明
HTTPS TCP 443 宛先のAWS EC2のセキュリティグループID Full access


03-03. Transit Gateway

Transit Gatewayによる防御

AWSデータセンター間の通信で使用するTransit Gatewayであれば、パケットの物理レイヤーを暗号化できる。


04. L7の防御

L7の防御方法

L7の攻撃をAWS WAFやCertificate Managerで防御する。

代わりに、アプリケーションの実装で防御しても良い。


04-02. AWS WAF

AWS WAFによる防御

L7の攻撃を防御する。


AWS WAFルールによる防御

▼ ユーザーエージェント拒否

*例*

悪意のあるユーザーエージェントを拒否する。

ルール:block-user-agents

Statementの順番 If a request Inspect Match type Regex pattern set Then 挙動
0 matches URI path Matches pattern from regex pattern set 文字列セット Block 指定した文字列を含むユーザーエージェントの場合、アクセスすることを拒否する。
Default Action 説明
Allow 指定したユーザーエージェントでない場合、全てのパスにリクエストを送信することを許可する。

▼ CIツールのアクセスを許可

*例*

社内の送信元IPアドレスのみ許可した状態で、CIツール (例:GitHub Actions、CircleCI、GitLab CI、Argo Workflows、Tektonなど) が社内サービスにリクエストを送信できるようにする。

ルール:allow-request-including-access-token

Statementの順番 If a request Inspect Header field name Match type String to match Then 挙動
0 matches Header Authorization Exactly matched string Bearer <トークン文字列>』で文字列を設定する Allow authorizationヘッダーに指定した文字列を含むリクエストの場合、アクセスすることを拒否する。
Default Action 説明
Block 正しいトークンを持たないアクセスの場合、全てのパスにリクエストを送信することを拒否する。

▼ 特定のパスを社内アクセスに限定

*例*

アプリケーションでは、特定のURLパスにリクエストを送信できる送信元IPアドレスを社内だけに制限する。

2個のルールを作成する必要がある。

ルール:allow-access--to-url-path

Statementの順番 If a request Inspect IP set Match type Regex pattern set Then 挙動
0 matches (AND) Originates from an IP address in 社内IPセット - - - 社内の送信元IPアドレスの場合、指定したパスにリクエストを送信することを許可する。
1 matches URI path - Matches pattern from regex pattern set 文字列セット Allow 0番目かつ、指定した文字列を含むURLパスアクセスの場合、アクセスすることを許可する。

ルール:block-access-to-url-path

Statementの順番 If a request Inspect Match type Regex pattern set Then 挙動
0 matches URI path Matches pattern from regex pattern set 文字列セット Block 指定した文字列を含むURLパスアクセスの場合、アクセスすることを拒否する。
Default Action 説明
Allow 指定したURLパス以外のアクセスの場合、そのパスにリクエストを送信することを許可する。

▼ 社内アクセスに限定

*例*

アプリケーション全体にリクエストを送信できる送信元IPアドレスを、特定のIPアドレスだけに制限する。

ルール:allow-global-ip-addresses

Statementの順番 If a request Inspect IP set Originating address Then 挙動
0 matches (OR) Originates from an IP address in 社内IPセット Source IP address - 社内の送信元IPアドレスの場合、全てのパスにリクエストを送信することを許可する。
1 matches Originates from an IP address in 協力会社IPセット Source IP address Allow 0番目あるいは、協力会社の送信元IPアドレスの場合、全てのパスにリクエストを送信することを許可する。
Default Action 説明
Block 指定した送信元IPアドレス以外の場合、全てのパスにリクエストを送信することを拒否する。

▼ ALBを直接的に指定することを防ぐ

*例*

AWS Route53のドメイン経由ではなく、ALBの直接的に指定して、リクエストとを送信することを防ぐ。

ALBのIPアドレスは定期的に変化するため、任意のIPアドレスを指定できる正規表現を定義する必要がある。

^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$

ルール:block-direct-access-to-lb

Statementの順番 If a request Inspect Match type Regex pattern set Then 挙動
0 matches Header Matches pattern from regex pattern set 文字列セット Block 指定したHostヘッダーに対するアクセスの場合、アクセスすることを拒否する。
Default Action 説明
Allow 指定したHostヘッダー以外に対するアクセスの場合、アクセスすることを許可する。


AWS WAFマネージドルールによる防御

▼ マネージドルールの動作確認の必要性

マネージドルールを導入する時は、事前にルールのカウントを使用することが推奨である。

カウントで検知されたリクエストのほとんどが悪意のないものであれば、設定したマネージドルールの使用をやめる必要がある。

▼ ブラウザを送信元とした場合

ブラウザを送信元とした場合、リクエストのヘッダーやボディはブラウザによって作成されるため、これに基づいた判断が必要である。

  • ブラウザからのリクエスト自体が悪意判定されているか否か
  • サイトのURLの記法によって、悪意判定されているか否か
  • 送信元の国名が『日本』であるのにも関わらず、悪意判定されているか否か
  • サイトに送信された全リクエストのうち、カウントで検知されたリクエスト数が多すぎないか否か

▼ 連携するアプリケーションを送信元とした場合

アプリケーションを送信元とした場合、リクエストのヘッダーやボディは連携するアプリケーションによって作成されるため、これに基づいた判断が必要である。


04-03. Certificate Manager

Certificate Managerによる防御

アプリケーションデータの暗号化のために、Certificate Manager (L7) を使用する。

リクエストを受信するAWSリソース (例:ALB、Aurora AWS RDS、AWS CloudFront、AWS EC2/AWS ECS/AWS EKSなど) に紐づけられる。

安全性と利便性から、パブリックネットワークと信頼できるネットワーク (例:データセンター、プライベートネットワークなど) の境界をSSL/TLS終端とすることが多い。


04-04. AWS Systems Manager

AWS Systems Managerによる防御

開発者がAWS EC2へリモート接続する方法として、AWS Systems Managerのセッションマネージャーを採用する。

SSH公開鍵認証を採用しないことにより、SSH公開鍵を管理する負荷や漏洩のリスクを低減する。