目次
AWS Lambda Web FunctionsとDynamoDBで構築したリバースプロキシは、リクエストがアプリケーションに届く前に、セッションの接続元を確認し、不審なセッションを失効させ、指定した攻撃フィンガープリントをブロックできます。提供されたテストレポートでは、サーバー待機時間の中央値が約12 ms増加し、コールドスタート時には大きな遅延が発生しました。
要点#
- DynamoDBは、CloudFront KVSで報告されている5 MBの容量制限を受けずに、セッション単位の失効と強い整合性のある読み取りに対応します。
- プロキシは、アプリケーションコードにデータベース呼び出しを追加せずに、ログイン成功レスポンスからセッションを登録できます。
- 国やASNの変化はリスクの兆候となり、JA4とJA4Hのフィンガープリントは追加のブロック判断材料になります。
- 保護対象のルートではCloudFrontのキャッシュを無効にし、プロキシとアプリケーションの両方で直接アクセスを拒否する必要があります。
アプリケーションの手前で検査する#
リクエスト経路をCloudFront → Web Function → アプリケーションとします。Web Functionはリージョン内のHTTPリバースプロキシとして動作し、保護対象のリクエストを転送する前にDynamoDBを照会します。
ログイン時に、セッションの国、任意でASN、有効期限を保存します。以降のリクエストでは、CloudFrontが示す閲覧者の接続元と登録情報を比較します。不一致があれば、登録情報の削除とログインへのリダイレクトを実行できます。これによりプロキシ経由のアクセスは失効しますが、アプリケーション側の元のセッション自体が無効になるとは限りません。
元の実装はNode.js 24とDynamoDBの強い整合性のある読み取りを使用しています。これにより、登録成功直後に古いデータを読み取ることを防ぎます。ただし、ここでいう「Impossible Location」は国またはASNの不一致を意味し、物理的に不可能な移動を計算するものではありません。
正しく登録・失効させる#
ログインパスを明示的に設定します。レスポンスが許可した成功ステータスを持ち、Set-CookieでセッションCookieを発行した場合にのみ、セッションを登録します。受信リクエストのセッションIDは決して登録しないでください。攻撃者が盗んだCookieをログインエンドポイントに送信し、記録された接続元の置き換えを試みる可能性があります。
次のルールを適用します。
- ログイン時の登録に失敗したら、
503を返し、アプリケーションの成功レスポンスとセッションCookieは返さないでください。 - セッションの照会に失敗したら、アクセスを拒否します。ログと監視では、インフラのエラーと通常のログイン失敗を区別してください。
- DynamoDB TTLによる削除は非同期のため、照会のたびに有効期限を確認し、登録の有効期間をアプリケーションのセッションの絶対タイムアウトに合わせてください。
- ログアウト時と接続元の不一致時には登録情報を削除し、セッションのローテーション時にも新しいCookieが登録されることを確認してください。
登録情報を削除すると、正規ユーザーも再認証が必要になります。モバイル回線の切り替え、VPNの利用、旅行によって不一致が起こる場合があります。まずは国の確認から始め、ASNの変化による制限を適用する前に誤検知を測定してください。
フィンガープリントによるブロックを追加する#
JA4はTLSクライアントの特性を表します。JA4Hは、ヘッダー名やその順序を含むHTTPリクエストの構造を表します。報告された実装では、CloudFrontがJA4を提供し、プロキシが閲覧者のヘッダー順序とHTTPバージョンのメタデータを使ってJA4Hを計算します。セッション固有のCookie値に依存しないよう、JA4Hのa_b部分を照合します。
提供されたテストでは、Python 3.13上で動作するsqlmap 1.10.10から観測されたフィンガープリントをブロックしました。sqlmapのUser-AgentをFirefoxに似せて変更した後も、報告された90件のリクエストすべてに403が返されました。これは、テストしたリクエストパターンをブロックできたことを示します。あらゆるsqlmap構成を確実に検出できることを示すものではありません。フィンガープリントは変化し、正規のクライアントと共通する場合もあります。
セッション照会と並行して、BatchGetItemでフィンガープリントのレコードを照会します。照会失敗時にリクエストを許可するか拒否するかを定義し、UnprocessedKeysがある場合は結果が不完全であると扱ってください。適用予定のルールは、強制適用する前に観測モードでテストします。
迂回経路を塞ぐ#
元の設計では、CloudFront OAC、IAM認証、対象ディストリビューションに限定したリソースポリシーでWeb Functionを保護します。アプリケーションは別途、プロキシが上書きし、アプリケーション、ALB、またはAWS WAFが検証するシークレットヘッダーで保護します。シークレットは安全に保存し、ローテーション中は新旧の値を併用できるようにします。
保護対象のルートにはCachingDisabledを設定します。CloudFrontのキャッシュにヒットすると、オリジン側のプロキシを迂回するためです。接続元とフィンガープリントのメタデータ、Cookie、クエリ文字列、アプリケーションヘッダーの転送を明示的に設定します。Authorization、Origin、CSRFの要件も確認してください。閲覧者のHostは転送対象から除外します。公開URLを組み立てるアプリケーションでは、転送されたホスト情報を信頼するための設定も必要になる場合があります。
提供されたレポートには、ポリシーのヘッダー数上限が10、WebSocket非対応、Web FunctionsとLambda OACに対するTerraformの対応不足が記載されています。デプロイ前に、これらの詳細、リージョンごとの提供状況、認証の動作を最新のAWSドキュメントで確認してください。提供資料だけでは、2026年10月20日時点の状況を独立に確認できません。
遅延と障害を見込む#
東京リージョンのテストでは、構成を交互に切り替えて各100件のリクエストを送信した結果、サーバー待機時間の中央値はプロキシなしで51.9 ms、ありで64.4 msでした。強い整合性のあるセッション読み取りの中央値は3.5 ms、フィンガープリント照会は4.4 msでした。これらは特定のワークロードでの測定値であり、遅延を保証するものではありません。
アイドル状態からの初回リクエストでは、1.3~1.5秒の追加時間がかかったと報告されています。アイドル状態後の最初の並行実行では、プロキシ経由のサーバー待機時間のp99が335.1 msに達し、プロキシなしでは96.9 msでした。ウォーム状態での実行では改善しましたが、テールレイテンシは依然として高くなりました。
DynamoDBはKVSの小さなストレージ上限を解消しますが、キャパシティ計画は必要です。保護対象リクエストごとの読み取り、データベース障害、リージョン間の距離を見込んでください。マルチリージョン構成には、整合性に関する明示的な設計も必要です。単一リージョンでの失効動作が、そのまま引き継がれると考えてはいけません。
次のステップ#
ステージング環境で1つの保護対象ルートをデプロイし、ログイン → 接続元の不一致 → 元のCookieで再試行、というテストを実行して、登録情報が削除され、両方のユーザーに再認証が必要になることを確認してください。
出典: https://zenn.dev/cscloud_blog/articles/f4ce99ffeb8ee3
目次
