Политика 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
Первопричина
Вот что происходит:
Анонимный пользователь загружает объект
- Анонимный пользователь становится владельцем объекта
Проверяется путем получения объекта 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.
- Быть владельцем объекта имеет следующее влияние:
- Анонимный пользователь имеет FULL_CONTROL (см. Acl выше)
- Анонимный пользователь не может удалить - это похоже на общее правило AWS, которое нельзя изменить - анонимному пользователю никогда не разрешено ничего удалять, даже если у него есть FULL_CONTROL
- Анонимный пользователь, однако, может положить пустой объект поверх существующего объекта, в результате FULL_CONTROL
- Когда корзина содержит объект, принадлежащий пользователю, который не является частью учетной записи корзины:
- Владелец ведра не имеет прав доступа к объекту (не указан в acl)
- Владелец ведра не может прочитать объект
- Владелец ведра может видеть объект в операции со списком ведра благодаря ACL ведра
- Владелец ведра может удалить объект - это общее правило, которое нельзя изменить - как человек, оплачивающий счет, вы всегда оставляете за собой право удалить объект - даже если вы не можете его прочитать
разрешение
Есть способ достичь желаемого результата - к сожалению, вы должны ссылаться на арн конкретной сущности 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, выполняющей роль - но принципал должен удержаться. Удачи!
Следующие статьи были полезны для понимания происходящего - каждая из них представляет сценарий, похожий, но не совсем такой, как у вас, но методы, которые они использовали для решения своих сценариев, определили путь: