お疲れ。最近、クラウドインフラの設計レビューをいくつか回したが、相変わらず「とりあえず動く」を優先したガバガバなIAM(Identity and Access Management)設計が多い。
「開発効率のためにワイルドカード(*)を許可しました」「EC2から他のリソースを操作させたいので権限を大きくしました」——こういう言い訳を現場で聞くたびに、私の頭痛の種が増える。攻撃者にとって、過剰に権限が付与されたIAMロールは、クラウド環境という広大な城の「正門の鍵が開きっぱなしになっている状態」に他ならない。
今回は、ペネトレーションテストの現場で私が真っ先に突く、「IAMロールの過剰な権限付与と権限昇格メカニズム」について徹底的に解説する。なぜそれが危険なのか、どうやって悪用されるのか、そしてどう防ぐのか。私の背中を見て、しっかり実務に落とし込んでほしい。
—
1. 現場で蔓延する「ワイルドカードの罠」とリスク
クラウドの初期設定や、ネット上のコピペ記事によくあるのが、次のような「全許可」のIAMポリシーだ。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
「まさか本番環境でこれを設定するバカはいないだろう」と思うかもしれないが、サービスごとのスコープダウンをサボった結果、"Action": "s3:*" や "Action": "iam:*" のように、必要以上のサービス権限を付与しているケースは後を絶たない。
攻撃者がWebアプリケーションの脆弱性(RCEやSSRFなど)を突いてクラウドインスタンスのメタデータサービス(IMDS)から一時クレデンシャルを窃取した瞬間、このワイルドカードが牙をむく。最小権限の原則(Principle of Least Privilege)を無視した設計は、侵入された後の「被害の爆風(Blast Radius)」を不必要に広げるだけなのだ。
—
2. 権限昇格の常道:iam:PassRole とサービス連携の悪用
ペネトレーションテストにおいて、単なるデータ読み取り権限(例えば s3:GetObject)だけでは満足しない。我々が狙うのは「権限昇格(Privilege Escalation)」だ。
AWSなどのクラウド環境において、最も古典的かつ強力な権限昇格ベクターの一つが iam:PassRole と iam:CreateLambdaFunction(あるいは ec2:RunInstances)の組み合わせだ。
攻撃シナリオのメカニズム
1. 初期潜入: 攻撃者は権限の弱いIAMロール(例: ログ収集用の限定ロール)がアタッチされたコンテナやインスタンスのクレデンシャルを入手する。
2. 権限の確認: そのロールが iam:PassRole と、新しいリソース(Lambda等)を作成する権限を持っていることに気づく。
3. 悪用の実行: 攻撃者は、自分よりもはるかに強い権限(例: AdministratorAccess)を持ったIAMロールを指定して、新しいLambda関数を作成する。
4. コードの実行: 管理者ロールを付与したLambda関数に、自分用のバックドアユーザーを作成するスクリプトを仕込んで実行する。
これで、攻撃者はインフラ全体の完全な支配権(Godモード)を手に入れる。これが iam:PassRole が持つ本質的なリスクだ。誰にでも「強いロールを他のサービスに渡す権限」を与えてはならない。
—
3. 対策:セキュアなIAMポリシー設計と実装
では、このリスクをどう封じ込めるか。口うるさく言うよりも、実際のコードと設定で示そう。
A. 過剰な権限を排除した最小限のIAMポリシー例
特定のS3バケットに対する特定の操作のみを許可し、かつ Resource を厳密に絞り込んだセキュアなポリシーの例だ。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SpecificS3BucketAccess",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::my-company-secure-bucket-prod/*"
]
},
{
"Sid": "DenyDangerousActions",
"Effect": "Deny",
"Action": [
"iam:*",
"organizations:*"
],
"Resource": "*"
}
]
}
*ポイント: ワイルドカードを排除し、アクセス先のリソースARNを完全に固定している。さらに明示的な Deny を挟むことで、万が一のミスを防ぐ多層防御にしている。*
B. アプリケーション層(Python / Boto3)からの安全なリソース操作
バックエンドのPythonアプリケーションからAWSリソースを叩く際も、無駄な権限エラーを出さないための例外処理と、安全なクライアント初期化の実装例を共有する。
import boto3
from botocore.exceptions import ClientError
import logging
# ロガーの設定
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def secure_s3_file_upload(bucket_name, file_name, file_data):
"""
最小権限の原則に基づき、指定されたバケットへ安全にファイルをアップロードする。
過剰な権限を持つクライアントセッションの使い回しを避ける。
"""
# セッションの初期化(環境変数やIAMロールから自動的に最小限のクレデンシャルを取得)
s3_client = boto3.client('s3')
try:
# アップロード実行
s3_client.put_object(
Bucket=bucket_name,
Key=file_name,
Body=file_data,
ServerSideEncryption='AES256' # 保存時の暗号化を強制
)
logger.info(f"Successfully uploaded {file_name} to {bucket_name}.")
return True
except ClientError as e:
error_code = e.response['Error']['Code']
if error_code == 'AccessDenied':
logger.error("権限エラー: この操作を行うためのIAM権限が不足しています。管理者に確認してください。")
else:
logger.error(f"予期せぬAWSエラーが発生しました: {e}")
return False
# 実行例
if __name__ == "__main__":
# テストデータ
target_bucket = "my-company-secure-bucket-prod"
target_file = "reports/2023_audit.txt"
data_content = b"Confidential Security Report Data"
secure_s3_file_upload(target_bucket, target_file, data_content)
—
4. IAM Access Analyzer による継続的な権限最適化
人間が手作業でIAMポリシーを監査するのには限界がある。そこで活用すべきなのが AWS IAM Access Analyzer だ。
これを使うことで、外部のプリンシパル(別のアカウントや匿名ユーザー)から自分のリソースへアクセス可能になっていないかを自動検知できる。また、CloudTrailのログを分析して「過去90日間に実際に使用されたアクション」に基づき、過剰な権限を削ぎ落としたポリシーのテンプレートを自動生成することも可能だ。
ペネトレーションテストやセキュリティ監査を単発のイベントで終わらせるな。CI/CDパイプラインの中にIAMlintやAccess Analyzerの検証ステップを組み込み、「デプロイ前に過剰な権限を検知してビルドを落とす仕組み」を構築すること。これが、現代のクラウドセキュリティエンジニアリングの基本だ。
—
チーフエンジニアからのメッセージ
セキュリティは「機能」ではなく「状態」だ。今日ガリガリ書いたコードや設定が、明日にはレガシーになり、新たな脆弱性の温床になるかもしれない。
だからこそ、常に攻撃者の視点(Offensive Mindset)を持ち、「自分がこのシステムをハックするならどこを突くか?」を自問自答し続けろ。甘いIAM設計を見かけたら、面倒くさがらずにその場でコードを修正し、プルリクエストを飛ばすこと。それが、君たちの作るシステムを真に堅牢なものにする唯一の道だ。頼んだぞ。
コメント