【IAM】MFA 強制ポリシーの注意点【多要素認証】

記事タイトルとURLをコピーする

クラウドインテグレーション部 柿﨑です。

MFA強制ポリシーと向き合う機会がありましたので、そのときに私が抱いた疑問について書いていきます。

MFA強制ポリシーとは

IAMユーザーに対してMFAを有効化しない限り、AWSの操作権限を与えないIAMポリシーです。
とはいえ、最低限MFAを有効化させる権限などは予め与える必要がありますので、一部の権限を例外的に許可させます。
本記事ではMFA強制ポリシーの詳細については解説せず、私の抱いた疑問にフォーカスして記述します。
そのため、MFA強制ポリシーの詳細な解説は以下の公式ドキュメントをご参照ください。

IAM チュートリアル: ユーザーが自分の認証情報および MFA 設定を管理できるようにする

MFA強制ポリシーのあるある

公式ドキュメントのMFA強制ポリシーをコピペし、以下のIAMポリシーを作成したとします。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowViewAccountInfo",
            "Effect": "Allow",
            "Action": [
                "iam:GetAccountPasswordPolicy",
                
                "iam:ListVirtualMFADevices"
            ],
            "Resource": "*"
        },       
        {
            "Sid": "AllowManageOwnPasswords",
            "Effect": "Allow",
            "Action": [
                "iam:ChangePassword",
                "iam:GetUser"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnAccessKeys",
            "Effect": "Allow",
            "Action": [
                "iam:CreateAccessKey",
                "iam:DeleteAccessKey",
                "iam:ListAccessKeys",
                "iam:UpdateAccessKey"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnSigningCertificates",
            "Effect": "Allow",
            "Action": [
                "iam:DeleteSigningCertificate",
                "iam:ListSigningCertificates",
                "iam:UpdateSigningCertificate",
                "iam:UploadSigningCertificate"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnSSHPublicKeys",
            "Effect": "Allow",
            "Action": [
                "iam:DeleteSSHPublicKey",
                "iam:GetSSHPublicKey",
                "iam:ListSSHPublicKeys",
                "iam:UpdateSSHPublicKey",
                "iam:UploadSSHPublicKey"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnGitCredentials",
            "Effect": "Allow",
            "Action": [
                "iam:CreateServiceSpecificCredential",
                "iam:DeleteServiceSpecificCredential",
                "iam:ListServiceSpecificCredentials",
                "iam:ResetServiceSpecificCredential",
                "iam:UpdateServiceSpecificCredential"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnVirtualMFADevice",
            "Effect": "Allow",
            "Action": [
                "iam:CreateVirtualMFADevice",
                "iam:DeleteVirtualMFADevice"
            ],
            "Resource": "arn:aws:iam::*:mfa/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnUserMFA",
            "Effect": "Allow",
            "Action": [
                "iam:DeactivateMFADevice",
                "iam:EnableMFADevice",
                "iam:ListMFADevices",
                "iam:ResyncMFADevice"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "DenyAllExceptListedIfNoMFA",
            "Effect": "Deny",
            "NotAction": [
                "iam:CreateVirtualMFADevice",
                "iam:EnableMFADevice",
                "iam:GetUser",
                "iam:ListMFADevices",
                "iam:ListVirtualMFADevices",
                "iam:ResyncMFADevice",
                "sts:GetSessionToken"
            ],
            "Resource": "*",
            "Condition": {
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": "false"
                }
            }
        }
    ]
}

ここで新規にIAMユーザーを作成する際に「パスワードのリセットが必要」にチェックを入れ、

f:id:swx-kakizaki:20210610225647j:plain

MFA強制ポリシー(Force_MFA)を付与してIAMユーザーを作成します。

f:id:swx-kakizaki:20210610225757j:plain

その後、このIAMユーザーでマネジメントコンソールからログインをしてパスワードを変更しようとするのですが、以下のエラーが出るわけです。

f:id:swx-kakizaki:20210610230015j:plain

こうなるとIAMユーザーは初回ログイン時にパスワードの変更権限がないのにパスワードの変更を強制され、前に進めなくなります。
そこで公式ドキュメントを確認すると、以下のような記述があります。

注記 このポリシー例では、ユーザーが初めてサインインするときにパスワードをリセットすることはできません。AWS では、新しいユーザーがサインインするまで、当該ユーザーにアクセス許可を付与しないことを推奨しています。詳細については、「IAM ユーザーを安全に作成するにはどうすればよいですか?」をご参照ください。また、これにより、失効したパスワードを持つユーザーは、サインイン前にパスワードをリセットできなくなります。この操作を許可するには、iam:ChangePassword と iam:GetAccountPasswordPolicy をステートメント DenyAllExceptListedIfNoMFA に追加します。ただし、IAM ではこのようなアクセス許可をお勧めしません。ユーザーが MFA なしで自分のパスワードを変更できるようにすると、セキュリティ上のリスクが生じる可能性があります。

上記、AWS: MFA で認証された IAM ユーザーが [My Security Credentials] (マイセキュリティ資格情報) ページで自分の認証情報を管理できるようにするからの引用です。

要約するとIAMポリシーにパスワード変更権限を追加すれば解決するがリスクも伴う、と記載されています。
そこで私が抱いた疑問は、文末の「ただし、IAM ではこのようなアクセス許可をお勧めしません。ユーザーが MFA なしで自分のパスワードを変更できるようにすると、セキュリティ上のリスクが生じる可能性があります。」の部分となります。

仮説

MFA強制ポリシーが付与されている場合、基本的にはMFA認証を有効化していれば、第三者がプログラムによるアクセスを試みてもMFA認証の機能が働きます。
しかし、本警告を無視してIAMポリシーにパスワードの変更権限を追記すると、例外的にMFA認証なしでパスワード変更が可能となりそうです。

警告の内容を何となく理解したため、実際にMFA認証なしにパスワードが変更できてしまうのか検証してみます。

検証

以下のようにIAMポリシーの「DenyAllExceptListedIfNoMFA」ステートメントに「iam:ChangePassword」と「iam:GetAccountPasswordPolicy」を追記します。

        {
            "Sid": "DenyAllExceptListedIfNoMFA",
            "Effect": "Deny",
            "NotAction": [
                "iam:CreateVirtualMFADevice",
                "iam:EnableMFADevice",
                "iam:GetUser",
                "iam:ListMFADevices",
                "iam:ListVirtualMFADevices",
                "iam:ResyncMFADevice",
                "sts:GetSessionToken",
                "iam:ChangePassword",
                "iam:GetAccountPasswordPolicy"
            ],
            "Resource": "*",
            "Condition": {
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": "false"
                }
            }
        }

上記のIAMポリシーを付与したIAMユーザーにてMFAを有効化します。

f:id:swx-kakizaki:20210610232222j:plain

このIAMユーザーの認証情報を利用し、AWS CLIからパスワードの変更コマンドを実行すると、

# IAM Userのパスワード変更コマンド

aws iam change-password --old-password '変更前PW' \
--new-password '変更後PW'

ワンタイムパスワードを聞かれることもなく、AWS CLIによってパスワードの変更ができました。
※画像からは分かりづらいですが、コマンドに失敗したときはエラーが返ってきます。

f:id:swx-kakizaki:20210610232739j:plain

ということで、MFA強制ポリシーにパスワード変更権限を加えると、第三者が認証情報を利用してIAMユーザーのパスワードを変更できてしまうことが検証からも分かりました。
MFA強制ポリシーにパスワード変更権限を追記する際は、このようなことが起こり得ることを認識するとよさそうです。

公式ドキュメントに載っているIAMポリシーでの対応方法

公式ドキュメントに載っているIAMポリシーではどのように対応すればよいか、を以下に記載します。

まず、IAMユーザー作成時に「パスワードのリセットが必要」のチェックは入れません。
またアクセスキーの払い出しは、MFA認証後にIAMユーザー自身で設定可能なため、IAMユーザー作成時に設定をしない方がよりセキュアです。
理由としては、IAMユーザー作成時にアクセスキーを払い出してしまうと、当該IAMユーザーではない第三者がアクセスキーの情報を知り得るためです。
※以下のキャプチャではアクセスキーを利用してパスワード変更の検証をするため、ちゃちゃっと払い出しています。

f:id:swx-kakizaki:20210610233756j:plain

当該IAMユーザーでマネジメントコンソールにログインし、画面右上のプルダウンから「マイセキュリティ資格情報」を選択します。

f:id:swx-kakizaki:20210610235027j:plain

上図から遷移した画面にてMFAを有効化します。

f:id:swx-kakizaki:20210610235146j:plain

MFA有効化後は一度サインアウトし、改めてサインインします。

再度、サインインをするとパスワードの変更が可能となるため、パスワードを変更します。
※ここはIAMユーザー利用者の責任で実施することとなります。
ここから先は、IAMユーザーに付与されているMFA強制ポリシー以外のポリシーに従ってAWSを操作できるはずです。

f:id:swx-kakizaki:20210610235248j:plain

ここからは検証の続き的な内容です。
先ほどのIAMユーザーでMFA認証を有効化したあとに、以下のようにAWS CLIからパスワードを変更しようとすると失敗することが分かります。

f:id:swx-kakizaki:20210610234425j:plain

前述の検証内容と併せて、MFA強制ポリシーに例外を設けるとはどういうことか、というのが理解できたのではないかと思われます。

さいごに

なんやかんやでMFA強制ポリシーの設計を今までしてこなかったため、いざ自分で設計してみると新しい発見があるものだなと感じました。
少しはIAMと仲良くなれた気がします。

柿﨑 拓人 (記事一覧)

クラウドインテグレーション部

AWS移行案件の要件定義~構築をメインに担当。
最近ボルダリングをはじめました。