意図せず公開しているS3オブジェクトはありませんか?〜S3アクセス権限設定を再確認しよう!〜

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

意図せず公開しているS3バケット(パブリックアクセスのバケット)を確認する方法を以下のにしざわさんのブログにてご紹介しています。

意図せず公開しているS3バケットはありませんか?〜S3アクセス権限設定を見直そう〜

S3バケットがパブリックアクセスになっているかは、バケットの一覧から簡単に「パブリック」であることを確認できます。

しかし、一覧の一番下に以下のメッセージが表示されています。つまり、パブリックアクセスのバケットはないけど、パブリックアクセスのオブジェクトがあるかも...ということです。

オブジェクトのパブリックアクセス

オブジェクトのパブリックアクセス設定

マネジメントコンソールからパブリックアスセス設定しようとすると、下記のように警告が表示されますので、気が付かないうちにパブリックアスセスになることはないでしょう。でも、API(AWSCLI、AWS SDK等)からだと、警告なしてPUTされてしまいます。

オブジェクトのパブリックアクセスのパターン

オブジェクトにパブリックアクセスを片っ端に設定して、オブジェクトACLがどうなってるか確認します。

パブリックアクセスなし

$ aws s3api get-object-acl --bucket cm-public-xx --key owner.txt
{
    "Owner": {
        "DisplayName": "cm-user",
        "ID": "fce0966cbbd0ef9ea076003f08669f4ea8d2e9910fc7817beeeae3869633ed70"
    },
    "Grants": [
        {
            "Grantee": {
                "Type": "CanonicalUser",
                "DisplayName": "cm-user",
                "ID": "fce0966cbbd0ef9ea076003f08669f4ea8d2e9910fc7817beeeae3869633ed70"
            },
            "Permission": "FULL_CONTROL"
        }
    ]
}

オブジェクトの読み取り

$ aws s3api get-object-acl --bucket cm-public-xx --key everyone-read_object.txt
{
    "Owner": {
        "DisplayName": "cm-user",
        "ID": "fce0966cbbd0ef9ea076003f08669f4ea8d2e9910fc7817beeeae3869633ed70"
    },
    "Grants": [
        {
            "Grantee": {
                "Type": "CanonicalUser",
                "DisplayName": "cm-user",
                "ID": "fce0966cbbd0ef9ea076003f08669f4ea8d2e9910fc7817beeeae3869633ed70"
            },
            "Permission": "FULL_CONTROL"
        },
        {
            "Grantee": {
                "Type": "Group",
                "URI": "http://acs.amazonaws.com/groups/global/AllUsers"
            },
            "Permission": "READ"
        }
    ]
}

オブジェクトの読み取りアクセス権限

$ aws s3api get-object-acl --bucket cm-public-xx --key everyone-read_object_permissions.txt
{
    "Owner": {
        "DisplayName": "cm-user",
        "ID": "fce0966cbbd0ef9ea076003f08669f4ea8d2e9910fc7817beeeae3869633ed70"
    },
    "Grants": [
        {
            "Grantee": {
                "Type": "CanonicalUser",
                "DisplayName": "cm-user",
                "ID": "fce0966cbbd0ef9ea076003f08669f4ea8d2e9910fc7817beeeae3869633ed70"
            },
            "Permission": "FULL_CONTROL"
        },
        {
            "Grantee": {
                "Type": "Group",
                "URI": "http://acs.amazonaws.com/groups/global/AllUsers"
            },
            "Permission": "READ_ACP"
        }
    ]
}

オブジェクトの書き込みアクセス権限

$ aws s3api get-object-acl --bucket cm-public-xx --key everyone-write_object_permission.txt
{
    "Owner": {
        "DisplayName": "cm-user",
        "ID": "fce0966cbbd0ef9ea076003f08669f4ea8d2e9910fc7817beeeae3869633ed70"
    },
    "Grants": [
        {
            "Grantee": {
                "Type": "CanonicalUser",
                "DisplayName": "cm-user",
                "ID": "fce0966cbbd0ef9ea076003f08669f4ea8d2e9910fc7817beeeae3869633ed70"
            },
            "Permission": "FULL_CONTROL"
        },
        {
            "Grantee": {
                "Type": "Group",
                "URI": "http://acs.amazonaws.com/groups/global/AllUsers"
            },
            "Permission": "WRITE_ACP"
        }
    ]
}

上記全ての権限付与

$ aws s3api get-object-acl --bucket cm-public-xx --key everyone-all.txt
{
    "Owner": {
        "DisplayName": "cm-user",
        "ID": "fce0966cbbd0ef9ea076003f08669f4ea8d2e9910fc7817beeeae3869633ed70"
    },
    "Grants": [
        {
            "Grantee": {
                "Type": "CanonicalUser",
                "DisplayName": "cm-user",
                "ID": "fce0966cbbd0ef9ea076003f08669f4ea8d2e9910fc7817beeeae3869633ed70"
            },
            "Permission": "FULL_CONTROL"
        },
        {
            "Grantee": {
                "Type": "Group",
                "URI": "http://acs.amazonaws.com/groups/global/AllUsers"
            },
            "Permission": "READ"
        },
        {
            "Grantee": {
                "Type": "Group",
                "URI": "http://acs.amazonaws.com/groups/global/AllUsers"
            },
            "Permission": "WRITE_ACP"
        },
        {
            "Grantee": {
                "Type": "Group",
                "URI": "http://acs.amazonaws.com/groups/global/AllUsers"
            },
            "Permission": "READ_ACP"
        }
    ]
}

アクセスコントロールリスト(ACL)の概要 - 被付与者とはに記載がある通り、パブリックアクセスが付与されているオブジェクトには、URLにhttp://acs.amazonaws.com/groups/global/AllUsersが含まれていることがわかりました。

オブジェクトのパブリックアクセスがないかスキャンする

さすがに何千とあるファイルをマネジメントコンソールからポチポチ確認できないので、スクリプトを書きました。下記のスクリプトは、実行したAWSアカウントの全てのバケットの全てのオブジェクトからGrantee.URIの値を表示します。実行環境のPythonはVersion 2.7.xなので、AWSCLIで日本語オブジェクト名が文字化けしないようにexport PYTHONIOENCODING=UTF-8を実行しています。また、JSONのパースはjqを使っています。

#!/bin/sh

export PYTHONIOENCODING=UTF-8

for bucket in $(aws s3 ls | awk '{print $3}');
do
  echo "---------- $bucket ----------"
  for key in $(aws s3 ls s3://$bucket --recursive | awk '{print $4}');
  do
    echo "[Object URL: s3://$bucket/$key]"
    aws s3api get-object-acl --bucket $bucket --key $key | jq '.Grants[].Grantee.URI'
    echo ""
  done
done

exit 0

実行結果の一部抜粋です。パブリックアクセスのオブジェクトは、http://acs.amazonaws.com/groups/global/AllUsersが表示されています。この文字列がないことが確認できればOKです。でも、aws s3api get-object-aclは応答が返るのが遅いので、バケット全てに掛けたら5時間ほどかかったので、時間は余裕を見たほうが良いです。

$ /bin/sh s3-public-scan.sh
 :
 :
---------- cm-public-xx ----------
[Object URL: s3://cm-public-xx/everyone-all.txt]
null
"http://acs.amazonaws.com/groups/global/AllUsers"
"http://acs.amazonaws.com/groups/global/AllUsers"
"http://acs.amazonaws.com/groups/global/AllUsers"

[Object URL: s3://cm-public-xx/everyone-read_object.txt]
null
"http://acs.amazonaws.com/groups/global/AllUsers"

[Object URL: s3://cm-public-xx/everyone-read_object_permissions.txt]
null
"http://acs.amazonaws.com/groups/global/AllUsers"

[Object URL: s3://cm-public-xx/everyone-write_object_permission.txt]
null
"http://acs.amazonaws.com/groups/global/AllUsers"

[Object URL: s3://cm-public-xx/owner.txt]
null
 :
 :

最後に

にしざわさんの説明を再掲します。私も改めて声を大にしてお伝えします。

誤解の無いように声を大にしてお伝えしたいのですが、これらについてAWSサービス側には何ら問題はありません。いずれもアクセス権限を不適切な状態に設定したユーザ側の責任による事故です。適切な設定をしているのにも関わらず、外部に情報が漏れてしまうようなことはありませんので、くれぐれもS3やAWSサービスそのものに対して無用なご不安による不適切な評価を行わないようにお願いします。

相次ぐAmazon S3の設定ミスによる情報漏えい事故(大元隆志) - 個人 - Yahoo!ニュース