aws-s3-modify-policy
s3:PutBucketPolicy lets a principal rewrite the bucket policy in full, self-granting any S3 permission including making the bucket public.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?bucket) ==
ObjectStorage
?bucket.provider_type == 'AWS::S3::Bucket'
?principal has EFFECTIVE s3:PutBucketPolicy on ?bucket ARN
emit
| source type | Identity |
|---|---|
| target type | ObjectStorage |
| source | ?principal |
| target | ?bucket |
| permissions | s3:PutBucketPolicy |
| conditions | iam_permission scp_or_org_policy |
| state logic | ACTIVE when s3:PutBucketPolicy is confirmed EFFECTIVE on the bucket ARN (identity policy + any existing bucket policy allow; no SCP deny; no permission boundary deny). CONDITIONAL(iam_permission) when a resource policy or SCP may restrict but isn't resolved. BLOCKED when an SCP or permission boundary explicitly denies s3:PutBucketPolicy. Note: BlockPublicPolicy=true prevents writing a policy with Principal:* (the write call FAILS for public statements), but the principal can still write non-public policy modifications; if the goal is to write a public-grant statement AND BlockPublicPolicy=true, the attacker must first clear that BPA flag (s3:PutBucketPublicAccessBlock) — emit CONDITIONAL(iam_permission) for the public-grant goal when BlockPublicPolicy=true. |
Narrative
{principal.name} has s3:PutBucketPolicy on {bucket.name} and can rewrite the bucket policy - self-granting any S3 permission, including full public access (if BPA permits it) or cross-account access to a chosen principal.
Raw rule rules/derived/aws/s3.yaml
id: aws-s3-modify-policy
emits: CanModifyPolicy
description: s3:PutBucketPolicy lets a principal rewrite the bucket policy in full, self-granting any
S3 permission including making the bucket public.
match:
- - principal: null
- HasPermission
- bucket: null
where:
- node_type(?bucket) == ObjectStorage
- ?bucket.provider_type == 'AWS::S3::Bucket'
- ?principal has EFFECTIVE s3:PutBucketPolicy on ?bucket ARN
emit:
source_type: Identity
target_type: ObjectStorage
source: ?principal
target: ?bucket
permissions:
- s3:PutBucketPolicy
conditions:
- iam_permission
- scp_or_org_policy
state_logic: "ACTIVE when s3:PutBucketPolicy is confirmed EFFECTIVE on the bucket ARN (identity policy\
\ + any existing bucket policy allow; no SCP deny; no permission boundary deny). CONDITIONAL(iam_permission)\
\ when a resource policy or SCP may restrict but isn't resolved. BLOCKED when an SCP or permission\
\ boundary explicitly denies s3:PutBucketPolicy. Note: BlockPublicPolicy=true prevents writing a policy\
\ with Principal:* (the write call FAILS for public statements), but the principal can still write\
\ non-public policy modifications; if the goal is to write a public-grant statement AND BlockPublicPolicy=true,\
\ the attacker must first clear that BPA flag (s3:PutBucketPublicAccessBlock) \u2014 emit CONDITIONAL(iam_permission)\
\ for the public-grant goal when BlockPublicPolicy=true."
confidence: min(contributing_confidences) * 0.95
derived_from:
- ?principal HasPermission ?bucket (s3:PutBucketPolicy effective permission)
false_positive_note: "s3:PutBucketPolicy requires that the bucket policy does not have a Deny on the\
\ action for this principal \u2014 an existing bucket policy Deny on PutBucketPolicy itself blocks\
\ the modification (bucket-policy self-denial). BlockPublicPolicy=true causes the API to reject policy\
\ writes that contain Principal:* statements; this does not block non-public policy writes. An SCP\
\ mandating that bucket policies must include aws:PrincipalOrgID blocks the Principal:* self-grant\
\ path. Model the CanModifyPolicy edge as ACTIVE for any structural policy modification (the attacker\
\ CAN change the policy); the downstream ExposedToInternet / CrossAccountTrust depends on whether\
\ BPA and SCPs also allow the resulting policy to take effect."
narrative: "{principal.name} has s3:PutBucketPolicy on {bucket.name} and can rewrite the bucket policy\
\ \u2014 self-granting any S3 permission, including full public access (if BPA permits it) or cross-account\
\ access to a chosen principal."