Политика S3 Bucket - GET Implicitly Allowed

При использовании следующей политики сегментов я вижу, что она ограничивает доступ по протоколу PUT, как и ожидалось - однако GET разрешен для созданного объекта, даже если нет ничего, что могло бы разрешить эту операцию.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowPut",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::<BUCKET>/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "<IP ADDRESS>"
                    ]
                }
            }
        }
    ]
}

Я могу положить файлы в <BUCKET> от <IP ADDRESS> используя curl следующим образом:

curl https://<BUCKET>.s3-<REGION>.amazonaws.com/ --upload-file test.txt

Файл успешно загружен и отображается в консоли S3. Теперь я по какой-то причине могу получить файл из любого места в Интернете.

curl https://<BUCKET>.s3-<REGION>.amazonaws.com/test.txt -XGET

Это относится только к файлам, загруженным с использованием вышеуказанного метода. При загрузке файла в веб-консоль S3 я не могу использовать curl для его получения (доступ запрещен). Поэтому я предполагаю, что это проблема разрешения на уровне объекта. Хотя я не понимаю, почему политика корзины не будет неявно запрещать такой доступ.

При просмотре разрешений на уровне объекта в консоли, единственные различия между файлом, загруженным через консоль (метод 1), и файлом, загруженным из разрешенного <IP ADDRESS> (метод 2) заключается в том, что файл в методе 2 не имеет "Владельца", "Разрешения" или "Метаданные", в то время как файл метода 1 имеет все это.

Более того - при попытке получить объекты, используя лямбда-скрипт (boto3 download_file()), которая берет на себя роль с полным доступом к корзине, она не работает для объектов, загруженных с помощью метода 2. Хотя это успешно выполняется для объектов, загруженных с помощью метода 1.

1 ответ

Решение

Краткое описание проблемы

Чтобы подвести итог вопроса:

  • у вас есть политика, которая разрешает анонимную загрузку объектов с данного IP-адреса источника
  • эти объекты не будут читаться вашими аутентифицированными пользователями (в частности, роль Iam, принятая вашей лямбда-функцией)
  • эти объекты читаются с ЛЮБОГО IP-адреса неаутентифицированными пользователями

Другие наблюдения

  • неаутентифицированный пользователь не может удалить объект

Желаемый результат:

  • объекты могут быть загружены неаутентифицированным пользователем с известного IP-адреса
  • объекты не могут быть загружены неаутентифицированными пользователями с любого IP-адреса
  • объекты могут быть получены авторизованным пользователем Iam

Первопричина

Вот что происходит:

  1. Анонимный пользователь загружает объект

    1. Анонимный пользователь становится владельцем объекта
    2. Проверяется путем получения объекта acl (выполнить запрос GET для объекта со строкой запроса ?acl) - вы получите:

      <?xml version="1.0" encoding="UTF-8"?>
      <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
          <Owner>
              <ID>65a011a29cdf8ec533ec3d1ccaae921c</ID>
          </Owner>
          <AccessControlList>
              <Grant>
                  <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser"><ID>65a011a29cdf8ec533ec3d1ccaae921c</ID></Grantee>
                  <Permission>FULL_CONTROL</Permission>
              </Grant>
          </AccessControlList>
      </AccessControlPolicy>
      

      Идентификатор владельца - это универсальный идентификатор анонимного пользователя. Я видел такой же идентификатор, на который ссылаются в некоторых обсуждениях на форуме AWS.

  2. Быть владельцем объекта имеет следующее влияние:
    1. Анонимный пользователь имеет FULL_CONTROL (см. Acl выше)
    2. Анонимный пользователь не может удалить - это похоже на общее правило AWS, которое нельзя изменить - анонимному пользователю никогда не разрешено ничего удалять, даже если у него есть FULL_CONTROL
    3. Анонимный пользователь, однако, может положить пустой объект поверх существующего объекта, в результате FULL_CONTROL
  3. Когда корзина содержит объект, принадлежащий пользователю, который не является частью учетной записи корзины:
    1. Владелец ведра не имеет прав доступа к объекту (не указан в acl)
    2. Владелец ведра не может прочитать объект
    3. Владелец ведра может видеть объект в операции со списком ведра благодаря ACL ведра
    4. Владелец ведра может удалить объект - это общее правило, которое нельзя изменить - как человек, оплачивающий счет, вы всегда оставляете за собой право удалить объект - даже если вы не можете его прочитать

разрешение

Есть способ достичь желаемого результата - к сожалению, вы должны ссылаться на арн конкретной сущности Iam (пользователя, роли, группы), которую вы хотите иметь, чтобы иметь возможность прочитать объект в списке ACL.

Ключевые элементы решения:

  • Требовать от анонимного пользователя полного доступа владельца корзины
    • Это гарантирует, что владелец корзины и учетная запись владельца Iam не будут лишены доступа к объекту acl.
  • Явно запретить любой доступ без PUT всем пользователям, которые не являются назначенными вами пользователем / ролью
    • Это гарантирует, что анонимные пользователи не смогут прочитать объект

Пример политики:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "allow-anonymous-put",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::<BUCKETNAME>/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "<IPADDRESS>"
                },
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }

        },
        {
            "Sid": "deny-not-my-user-everything-else",
            "Effect": "Deny",
            "NotPrincipal": {
                "AWS": "arn:aws:iam::<ACCOUNTNUMBER>:role/<ROLENAME>"
            },
            "NotAction": [
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::<BUCKETNAME>/*"
        }
    ]
}

Ключом ко второму утверждению является использование NotPrincipal а также NotAction,

Я проверил это локально, но только с обычным пользователем Iam, которому предоставлен доступ, а не с функцией Lamba, выполняющей роль - но принципал должен удержаться. Удачи!

Следующие статьи были полезны для понимания происходящего - каждая из них представляет сценарий, похожий, но не совсем такой, как у вас, но методы, которые они использовали для решения своих сценариев, определили путь:

Другие вопросы по тегам