DEF CON 29 で発表された「Alexandre Sieira - Attack Vectors for APIs w AWS API
はじめに
本記事は、DEF CON 29 Cloud Village で Alexandre Sieira 氏が発表した「Attack Vectors for APIs w AWS API Gateway Lambda Auth」に基づき、API Gateway と Lambda Authorizer を利用する際に陥りがちな設定ミス(特にIAMポリシーのワイルドカード利用)について解説します。
API Gateway と Lambda Authorizer の概要
認証・認可の仕組み
API Gatewayでは、Lambdaを利用して独自の認可機能を実装(このLambdaのことをLambda Authorizerと呼びます)できます。Lambda Authorizerは、クライアントからのリクエストに含まれる認証情報(headers、query、Token等)を元に、IAM Policyを生成して返却します。API Gatewayは返却されたIAM Policyを評価することでエンドポイントのアクセス制御を行います。下記の画像は、この一連の認証・認可全体の流れを示しています(https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html より抜粋)。
API Gatewayの特定のエントリーポイントを許可する例
Lambda Authorizerによって生成されるIAM Policyは以下のような形式となります (https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html より抜粋)。
{
"principalId": "yyyyyyyy", // The principal user identification associated with the token sent by the client.
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow|Deny",
"Resource": "arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]"
}
]
},
"context": {
"stringKey": "value",
"numberKey": "1",
"booleanKey": "true"
},
"usageIdentifierKey": "{api-key}"
}
例えば特定のAPI Gateway(apiId1
)におけるprod
ステージに対しGET
メソッドを利用して/product/list
というエンドポイントのみを許可する場合は、以下のようなIAM Policyとなります(context及びusageIdentifierKeyは省略)。
{
"principalId": "user|12345",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": "arn:aws:execute-api:us-east-1:123456789012:apiId1/prod/GET/product/list"
}
]
}
}
3. IAMポリシーとワイルドカードの仕様および注意点
IAMポリシーの基本仕様
IAM Policyは、リソースへのアクセス権限を定義します。リソース指定において、ワイルドカード(*
)を利用することで柔軟なマッチングが可能です。
ワイルドカード(*)の挙動
IAMポリシーにおいて/
は特別扱いされないため、ワイルドカード *
は、/
の区切りを超えてマッチングします。このため、作成するIAMポリシーによっては意図しないパスにも一致してしまう可能性があります。
4. 意図しないパスに一致する例
以下のようなAPIエンドポイントに対するカスタム認証を考えます。
管理者用のAPI
-
GET /admin/product/list
(商品一覧を取得) -
PUT /admin/product/{productId}
(商品詳細を更新) -
DELETE /admin/product/{productId}
(商品を削除)
一般ユーザ用のAPI
-
GET /product/list
(商品一覧を取得) -
GET /product/{productId}
(特定の商品詳細を取得) GET /product/favorites
POST /product/{productId}/favorites
DELETE /product/{productId}/favorites
誤った許可ポリシーの例
一般ユーザ向けに/product
以下のパスに対してどのようなメソッドでも許可するIAMポリシーを返す実装することを考えます。
この時、どのようなメソッド(GET, PUT, DELETE, POSTなど)でのアクセスも許可するために*
を利用し以下のようなIAM PolicyをLambaAuthrizerから返却すると、管理者用API用の/admin
以下へのエントリーポイントへの意図しないアクセスを許可しています。
これは管理者用の商品一覧を取得するAPIであれば"arn:aws:execute-api:us-west-2:123456789012:ymy8tbxw7b/prod/GET/admin/product/list"
というリソースのパスになるため最初の*
が /GET/admin/
にマッチしてしまいアクセスを許可してしまいます。
{
"principalId": "user",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": "arn:aws:execute-api:us-west-2:123456789012:ymy8tbxw7b/prod/*/product/*"
}
]
}
}
対策
発表では以下のような対策が示されていました。
限定的なワイルドカード利用の設計
- ワイルドカードを使用する際は、パスの末尾部分のみを対象とする設計にすることで、不要なパスまでマッチングしないようにします。
明示的なDenyポリシーの導入
- 特定のリソース(例:
/admin/*
)に対してDenyルールを明示的に設定することで、意図しないアクセスを防止できます。これはIAM Policyにおいて同一リソースにAllowとDenyが存在する場合、Denyが優先されるためです。
多層防御による認可チェックの強化
- Lambda Authorizerだけでなく、アプリケーション層など複数のレイヤーで認可チェックを実装することで、セキュリティ対策を強化します。
おわりに
Lambda Authroizerを利用する場合、作成するIAM Policyがどのようなリソースへのアクセスを許可するのかに注意が必要となります。AWSの公式ドキュメント等を参照しつつ、今回紹介しているような観点も踏まえ設計することが大切です。
Cloudbaseでは、noteでも様々な記事を公開しておりますので、ぜひご覧ください。
Discussion