S3 Bucket Allows Delete Action From All Principals
- Query id: ffdf4b37-7703-4dfe-a682-9d2e99bc6c09
- Query name: S3 Bucket Allows Delete Action From All Principals
- Platform: Terraform
- Severity: Critical
- Category: Access Control
- CWE: 732
- URL: Github
Description¶
S3 Buckets must not allow Delete Action From All Principals, as to prevent leaking private information to the entire internet or allow unauthorized data tampering / deletion. This means the 'Effect' must not be 'Allow' when the 'Action' is Delete, for all Principals.
Documentation
Code samples¶
Code samples with security vulnerabilities¶
Positive test num. 1 - tf file
resource "aws_s3_bucket_policy" "positive1" {
bucket = aws_s3_bucket.b.id
policy = <<POLICY
{
"Version": "2012-10-17",
"Id": "MYBUCKETPOLICY",
"Statement": [
{
"Sid": "IPAllow",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:DeleteObject",
"Resource": "arn:aws:s3:::my_tf_test_bucket/*",
"Condition": {
"IpAddress": {"aws:SourceIp": "8.8.8.8/32"}
}
}
]
}
POLICY
}
Positive test num. 2 - tf file
resource "aws_s3_bucket_policy" "positive2" {
bucket = aws_s3_bucket.b.id
policy = <<POLICY
{
"Version": "2012-10-17",
"Id": "MYBUCKETPOLICY",
"Statement": [
{
"Sid": "IPAllow",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:DeleteObject",
"Resource": "arn:aws:s3:::my_tf_test_bucket/*",
"Condition": {
"IpAddress": {"aws:SourceIp": "8.8.8.8/32"}
}
}
]
}
POLICY
}
Positive test num. 3 - tf file
module "s3_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "3.7.0"
bucket = "my-s3-bucket"
acl = "private"
versioning = {
enabled = true
}
policy = <<POLICY
{
"Version": "2012-10-17",
"Id": "MYBUCKETPOLICY",
"Statement": [
{
"Sid": "IPAllow",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:DeleteObject",
"Resource": "arn:aws:s3:::my_tf_test_bucket/*",
"Condition": {
"IpAddress": {"aws:SourceIp": "8.8.8.8/32"}
}
}
]
}
POLICY
}
Positive test num. 4 - tf file
# test action "s3:Delete*"
resource "aws_s3_bucket_public_access_block" "positive4" {
count = length(var.positive4)
bucket = var.positive4[count.index]
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
data "aws_iam_policy_document" "positive4" {
statement {
principals {
type = "AWS"
identifiers = ["*"]
}
effect = "Allow"
actions = [
"s3:Delete*",
]
resources = [
var.positive4,
"${var.positive4}/*",
]
}
}
# "Action": "s3:Delete", "Principal":"*" and "Type":"AWS"
resource "aws_s3_bucket_policy" "positive4" {
depends_on = [aws_s3_bucket_public_access_block.positive4]
bucket = var.positive4
policy = data.aws_iam_policy_document.positive4.json
}
Positive test num. 5 - tf file
# test action "s3:*"
resource "aws_s3_bucket_public_access_block" "positive5" {
count = length(var.positive5)
bucket = var.positive5[count.index]
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
data "aws_iam_policy_document" "positive5" {
statement {
principals {
type = "AWS"
identifiers = ["*"]
}
effect = "Allow"
actions = [
"s3:*",
]
resources = [
var.positive5,
"${var.positive5}/*",
]
}
}
# "Action": "s3:Delete", "Principal":"*" and "Type":"AWS"
resource "aws_s3_bucket_policy" "positive5" {
depends_on = [aws_s3_bucket_public_access_block.positive5]
bucket = var.positive5
policy = data.aws_iam_policy_document.positive5.json
}
Positive test num. 6 - tf file
# test action "*"
resource "aws_s3_bucket_public_access_block" "positive6" {
count = length(var.positive6)
bucket = var.positive6[count.index]
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
data "aws_iam_policy_document" "positive6" {
statement {
principals {
type = "AWS"
identifiers = ["*"]
}
effect = "Allow"
actions = [
"*",
]
resources = [
var.positive6,
"${var.positive6}/*",
]
}
}
# "Action": "s3:Delete", "Principal":"*" and "Type":"AWS"
resource "aws_s3_bucket_policy" "positive6" {
depends_on = [aws_s3_bucket_public_access_block.positive6]
bucket = var.positive6
policy = data.aws_iam_policy_document.positive6.json
}
Code samples without security vulnerabilities¶
Negative test num. 1 - tf file
resource "aws_s3_bucket_policy" "negative1" {
bucket = aws_s3_bucket.b.id
policy = <<POLICY
{
"Version": "2012-10-17",
"Id": "MYBUCKETPOLICY",
"Statement": [
{
"Sid": "IPAllow",
"Effect": "Deny",
"Action": "s3:*",
"Resource": "arn:aws:s3:::my_tf_test_bucket/*",
"Condition": {
"IpAddress": {"aws:SourceIp": "8.8.8.8/32"}
}
}
]
}
POLICY
}
Negative test num. 2 - tf file
module "s3_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "3.7.0"
bucket = "my-s3-bucket"
acl = "private"
versioning = {
enabled = true
}
policy = <<POLICY
{
"Version": "2012-10-17",
"Id": "MYBUCKETPOLICY",
"Statement": [
{
"Sid": "IPAllow",
"Effect": "Deny",
"Action": "s3:*",
"Resource": "arn:aws:s3:::my_tf_test_bucket/*",
"Condition": {
"IpAddress": {"aws:SourceIp": "8.8.8.8/32"}
}
}
]
}
POLICY
}
Negative test num. 3 - tf file
# test principal type not AWS
resource "aws_s3_bucket_public_access_block" "negative3" {
count = length(var.negative3)
bucket = var.negative3[count.index]
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
data "aws_iam_policy_document" "negative3" {
statement {
principals {
type = "Service"
identifiers = ["*"]
}
effect = "Allow"
actions = [
"s3:Delete*",
]
resources = [
var.negative3,
"${var.negative3}/*",
]
}
}
# "Action": "s3:Delete", "Principal":"*" and "Type":"Service"
resource "aws_s3_bucket_policy" "negative3" {
depends_on = [aws_s3_bucket_public_access_block.negative3]
bucket = var.negative3
policy = data.aws_iam_policy_document.negative3.json
}