TTechclick ⚡ XP 0% All lessons
AWS · S3 · S3 SecurityInteractive · L1 / L2 / L3

Securing Amazon S3: — How to Never Be the Next Public-Bucket Breach

Almost every "company leaks millions of records" headline traces back to one S3 bucket someone set public. This lesson shows you the four access layers, how to lock them with Block Public Access, how to encrypt and make data immutable, and how to PROVE a bucket isn't leaking — the way the AWS Security Specialty exam expects.

📅 2026-06-11 · ⏱ 13 min · 3 live demos · 4 infographics · 🏷 10-Q assessment + AI Tutor inline

⚡ Quick Answer

Secure Amazon S3 for L1/L2 engineers and AWS Security Specialty SCS-C02: Block Public Access, Object Ownership/ACLs-disabled, SSE-KMS + bucket keys, TLS enforcement, versioning/Object Lock, and Access Analyzer + Macie.

🎯 By the end you will be able to

Read as:

Pick where you want to start

1

Why S3 leaks

The four access layers and how they collide.

2

Block + Ownership

The 4 BPA toggles and ACLs-disabled.

3

Encrypt + protect

SSE choices, TLS-only, versioning, Object Lock.

4

Detect + verify

Access Analyzer, Macie, CloudTrail, the fix.

🧠 Warm-up — 3 questions, no score

Just notice which ones make you pause. We answer all three inside the lesson.

1. A bucket policy has "Principal": "*" with Allow s3:GetObject, but account-level Block Public Access is ON. Can an anonymous user read the objects?

Answered in Why S3 leaks.

2. You create a brand-new S3 bucket in 2026 and don't touch any settings. What is the default for ACLs?

Answered in Encrypt + protect.

3. Which tool tells you, in the S3 console, that a specific bucket is currently reachable by the public internet?

Answered in Block + Ownership.

Most engineers think…

Most engineers think "my data is in S3, so it must be safe — AWS is secure." They assume a bucket is private unless they deliberately share it, and that turning on encryption is the main thing.

Wrong — and it's the most expensive wrong belief in cloud. S3 buckets ARE private by default, but a single careless "Principal": "*" in a bucket policy, or an old public ACL, can expose every object — and encryption does nothing against a reader you authorised. Real S3 security is layered access control: turn on all four Block Public Access settings, disable ACLs, enforce encryption in transit and at rest by policy, make data immutable with Object Lock, and then prove none of it leaks with IAM Access Analyzer and Macie. The default is safe; humans make it unsafe.

① Why S3 leaks happen — the four access layers

Sneha is an L1 cloud engineer at Infosys. A teammate needs to share a few report files from an S3 bucket with a partner, gets frustrated by permissions, finds a Stack Overflow answer, and pastes a bucket policy with "Principal": "*". It works — the partner can read the files. It also means anyone on the internet can read them, including the customer PII sitting next to those reports. That one line is the shape of almost every S3 bucket breach you've read about.

Here's the reassuring part first: in S3, buckets and objects are private by default. A brand-new bucket grants access to nobody but the owner. Leaks happen because a human deliberately (or accidentally) opens one of four access layers. Understanding those four — and the order S3 checks them in — is the whole game.

Layer one is Block Public Access (BPA) — the master safety switch at the account and bucket level. Layer two is the bucket policy, a JSON document attached to the bucket. Layer three is ACLs — the legacy model AWS now tells you to switch off. Layer four is IAM identity policies attached to your users and roles.

👉 So far: buckets are private by default; leaks come from four layers — BPA, bucket policy, ACLs, IAM. Next: how they interact, and why an ACL can betray you even when your policy looks clean.

These layers don't vote politely — they stack. The dangerous combination is simple: if BPA is OFF and a bucket policy (or an old ACL) grants AllUsers read, the bucket is public, full stop. AWS considers an ACL public the moment it grants any permission to the predefined AllUsers or AuthenticatedUsers groups, and considers a bucket policy public if it allows a wildcard principal with no condition that pins it to a fixed account, IP range or VPC. Block Public Access exists precisely to catch these mistakes — it overrides the policy or ACL and rejects the request, regardless of what the policy says.

Figure 1 — The four access layers — one mis-set layer is an open door
One mis-set bucket policy turns a private S3 bucket into an open door the whole internet can read The four S3 access layers stacked as gates an internet request must pass: Block Public Access at the account and bucket level, then the bucket policy, then ACLs (legacy), then IAM identity policies. On the left the gates are open because Block Public Access is off and a wildcard star-principal bucket policy is attached, so an anonymous internet reader walks straight to the objects. On the right Block Public Access is on, so even a public policy is overridden and the request is rejected. Red marks the public path, blue the private bucket, amber the policy decision points, green the safe outcome. Four access layers — public is almost never what you want Anonymous reader203.0.113.7 · no AWS creds Gate 1 · Block Public Accessaccount + bucket · 4 togglesOFF on the left → request passes Gate 2 · Bucket policy (Principal "*") Gate 3 · ACLs (legacy — disabled) Gate 4 · IAM identity policies S3 buckettcs-payroll-prod objects (PII, salary CSV) ← if Gate 1 is OFF, a "*" policy in Gate 2 = public Turn Gate 1 ON →S3 overrides the policy & rejectsthe anonymous read (HTTP 403) untrusted / publictrusted / privatepolicy / decisionkey insightallowed / safe
Read the gates top to bottom. With Gate 1 (Block Public Access) OFF, a wildcard bucket policy in Gate 2 lets an anonymous reader walk straight to the objects. Turn Gate 1 ON and S3 overrides the policy — the read becomes a 403.

The four layers, one tap each

Tap each card — every S3-security interview and the SCS-C02 exam starts from these four and the order they're evaluated.

🛡️
Block Public Access
tap to flip

Account + bucket master switch (4 toggles). Overrides any public policy or ACL. So: turn it on and a careless '*' can't leak you.

📜
Bucket policy
tap to flip

Resource JSON on the bucket. Where 'Principal: *' lives. So: this is the layer most public-bucket breaches come from.

🪪
ACLs (legacy)
tap to flip

Old coarse model granting AllUsers/AuthenticatedUsers. So: AWS now disables these by default — keep them off.

👤
IAM identity policies
tap to flip

Attached to your users/roles, says what THAT identity may do. So: least-privilege here controls your own people, not the public.

Daily-life analogy — the society gate-pass register

Think of your housing society. Block Public Access is the main gate guard who can refuse anyone, no matter what pass they wave. The bucket policy is the visitor register at your flat door — write "let everyone in" there and strangers walk up. ACLs are the old paper chits the previous owner left lying around. IAM policies are the resident ID cards your own family carries. A leak is leaving the flat-door register on "everyone" while the main gate guard is asleep. Keep the guard awake (BPA on) and the careless register entry stops mattering.

Quick check · Q1 of 10

Rahul at TCS finds a bucket with an old ACL granting READ to the AllUsers group, but the account has all four Block Public Access settings turned ON. Is the object public right now?

Correct: b. With Block Public Access on, S3 ignores public ACLs and rejects public access regardless of what the ACL says — so the object is not public. The ACL still exists (BPA doesn't delete it), which is why you should ALSO disable ACLs; but right now the request is blocked. Encryption is unrelated to whether something is publicly readable.

Pause & Predict

Predict: a bucket policy has BOTH a statement allowing a specific partner account AND a statement with "Principal": "*". You enable RestrictPublicBuckets. What happens to the partner's cross-account access? Type your guess.

Answer: It gets cut off too. Once any statement makes the policy 'public' (the '*' one), RestrictPublicBuckets treats the WHOLE policy as public and restricts the bucket to AWS service principals and the owner account only — so even the legitimately-named partner account loses access until you remove the public '*' statement. One bad statement poisons the whole policy. This is a classic SCS-C02 gotcha.

② Block Public Access + Ownership — the master switch

Now the controls. Block Public Access is four independent settings you can mix in any combination. You almost always want all four ON, and you want them ON at the account level so they apply to every current and future bucket — AWS Security Hub control S3.8 checks exactly this.

The four settings, in plain words. BlockPublicAcls rejects any new request that tries to attach a public ACL. IgnorePublicAcls makes S3 ignore every public ACL that already exists. BlockPublicPolicy rejects any attempt to attach a bucket policy that would grant public access. RestrictPublicBuckets limits a bucket that already has a public policy to AWS service principals and the owner account only. The first two are about ACLs; the last two are about policies — together they cover both leak paths.

🖥️ This is the panel you'll use — S3 Console → Buckets → (your bucket) → Permissions tab → Block public access (bucket settings) → Edit. (Recreated for clarity — your console matches this.)
console.aws.amazon.com · S3 · Buckets · Permissions
1
Block all public access
On (master — ticks the 4 below)
2
Block public access granted through new ACLs
On (BlockPublicAcls)
3
Block public access granted through any ACLs
On (IgnorePublicAcls)
Block public access granted through new bucket/AP policies
On (BlockPublicPolicy)
Block public + cross-account access via any policies
On (RestrictPublicBuckets)
4
Confirm
type 'confirm'
Save changes

Layer two of this section is S3 Object Ownership. Set it to Bucket owner enforced and ACLs are disabled entirely — the bucket owner automatically owns every object and you control everything with policies, not ACLs. Since April 2023, new buckets are created with this setting by default. With ACLs disabled, a PutObject that tries to set a custom ACL fails with AccessControlListNotSupported — which is good: it means nobody can sneak a public grant in through an ACL again.

AWS CLI — turn on all four BPA settings at the bucket level, then disable ACLs
aws s3api put-public-access-block \
  --bucket tcs-payroll-prod \
  --public-access-block-configuration \
  BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true

aws s3api put-bucket-ownership-controls \
  --bucket tcs-payroll-prod \
  --ownership-controls 'Rules=[{ObjectOwnership=BucketOwnerEnforced}]'
Expected output
# (both commands return no output on success — exit code 0)
$ aws s3api get-public-access-block --bucket tcs-payroll-prod \
    --query PublicAccessBlockConfiguration
{
    "BlockPublicAcls": true, "IgnorePublicAcls": true,
    "BlockPublicPolicy": true, "RestrictPublicBuckets": true
}
Common mistake — "BPA is on for the bucket, so we're safe" (but the account is off)

Symptom: a security scan still flags buckets as public even though Aditya turned on Block Public Access for the one bucket he cares about. Cause: BPA at the bucket level only protects that bucket — every other bucket someone spins up tomorrow starts unprotected. Fix: set Block Public Access at the account level (aws s3control put-public-access-block --account-id 123456789012 ...) so all current and future buckets inherit it. S3 applies the most restrictive of account + bucket settings, so account-level ON can't be undone by a single bucket.

Quick check · Q2 of 10

Priya wants to be sure no future bucket in her Wipro account can ever be made public by an ACL, even ones her teammates create next month. What's the strongest single move?

Correct: a. Account-level Block Public Access applies to all current AND future buckets and access points, and S3 enforces the most restrictive combination — so a teammate can't expose a new bucket. Per-bucket BPA misses future buckets; deleting policies doesn't stop ACLs and breaks legitimate access; encryption protects data at rest but does nothing about public reachability.

Pause & Predict

Predict: you set Object Ownership to 'Bucket owner enforced' (ACLs disabled), but an app still does PutObject with --acl bucket-owner-full-control. Does the upload succeed or fail? Type your guess.

Answer: It succeeds. When ACLs are disabled, S3 still accepts PUTs that specify NO ACL or the bucket-owner-full-control canned ACL (since that matches the enforced ownership). It only rejects PUTs that try to set a DIFFERENT ACL (e.g. a custom grant to another account or to AllUsers) with error AccessControlListNotSupported. So well-behaved apps keep working; only the ones trying to grant away access break — which is exactly the point.

③ Encryption + data protection — at rest, in transit, immutable

Public access controls decide who can reach the data; encryption decides who can read it if they get the bytes, and immutability decides whether they can destroy it. Start with at-rest. S3 gives you three server-side options. SSE-S3 uses an AES-256 key AWS owns — free, zero config. SSE-KMS uses a KMS key you control, with a CloudTrail trail of every decrypt — the right pick for PII or regulated data. SSE-C means you supply the key on every request and AWS never stores it.

Since 5 January 2023, S3 automatically applies SSE-S3 as the base encryption on every new object in every bucket, at no cost — so "is my data encrypted at rest?" is now answered "yes" by default. The remaining decision is whether you need the control and audit trail of SSE-KMS. If you do, turn on the S3 Bucket Key: it can cut your KMS request cost by up to 99% by reducing per-object KMS calls. Forgetting the bucket key is how teams get a surprise KMS bill on a high-traffic bucket.

Figure 2 — SSE-S3 vs SSE-KMS vs SSE-C — who holds the key decides everything
Three encryption-at-rest choices for S3 — who holds the key decides who can read, audit, and ransom you A three-column comparison of S3 server-side encryption. SSE-S3 uses AES-256 keys AWS owns and manages, free, no audit trail per object. SSE-KMS uses a KMS key you control with CloudTrail audit and a bucket key option that cuts KMS cost up to ninety-nine percent. SSE-C uses a key the customer supplies that AWS never stores, which is powerful but is also exactly what the Codefinger ransomware abused. Blue marks the trusted AWS-managed paths, amber the decision of who holds the key, red the SSE-C danger, green the recommended default. SSE-S3 vs SSE-KMS vs SSE-C — who holds the key? SSE-S3 (AES256) 🔑 key: owned + managed by AWS 💸 cost: free 📜 audit: no per-object CloudTrail 👤 you control rotation: no ⭐ since Jan 5 2023 this is theautomatic base on every bucket Default everyone gets free.Fine for non-regulated data. SSE-KMS 🔑 key: KMS key YOU own + scope 💸 cost: KMS API $ — use aBucket Key (cuts calls ≤99%) 📜 audit: every decrypt in CloudTrail 👤 you control rotation + grants 🚪 second lock: deny ≠ key access Pick for PII / regulated data.Always enable the Bucket Key. SSE-C 🔑 key: YOU send it per request 🚫 AWS never stores the key 📜 audit: only an HMAC is logged ⚠ lose the key = data gone 🦠 Codefinger ransomware (Jan2025) abused exactly this Rare. Deny SSE-C by policyunless you truly need it. untrusted / publictrusted / privatepolicy / decisionkey insightallowed / safe
Compare the three columns on key ownership, cost, and audit. SSE-S3 is the free default; SSE-KMS is your pick for PII (always with a bucket key); SSE-C is rare — and is exactly what the 2025 Codefinger ransomware abused.

At-rest isn't enough on its own. Enforce encryption in transit too, with a bucket policy that denies any request where aws:SecureTransport is false — that blocks plain HTTP and forces TLS. You can also deny PutObject unless the right s3:x-amz-server-side-encryption header is present, so nobody uploads unencrypted or with the wrong key. These two policy statements are a standard SCS-C02 answer for "enforce encryption."

Bucket policy — enforce TLS-only (deny non-HTTPS) and deny non-KMS uploads
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyInsecureTransport",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::tcs-payroll-prod",
        "arn:aws:s3:::tcs-payroll-prod/*"
      ],
      "Condition": { "Bool": { "aws:SecureTransport": "false" } }
    },
    {
      "Sid": "DenyWrongEncryption",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::tcs-payroll-prod/*",
      "Condition": {
        "StringNotEquals": { "s3:x-amz-server-side-encryption": "aws:kms" }
      }
    }
  ]
}
Expected output
# apply it, then test plain HTTP is blocked:
$ aws s3api put-bucket-policy --bucket tcs-payroll-prod --policy file://policy.json
$ curl http://tcs-payroll-prod.s3.amazonaws.com/test.txt
AccessDeniedAccess Denied
# 403 over HTTP — TLS now mandatory

Last, defend against deletion and ransomware. Turn on Versioning so an overwrite or delete never truly loses the old copy. Add Object Lock (WORM): in Governance mode only users with a special permission can remove the lock; in Compliance mode nobody — not even the account root — can delete the version until retention expires. Top it with MFA Delete so wiping versions needs a physical second factor.

▶ Watch a ransomware wipe hit a protected bucket vs an unprotected one

An attacker has stolen an IAM key with s3:PutObject and s3:DeleteObject on the bucket. Follow what happens when they try to encrypt-and-delete your objects. Press Play for the healthy path, then Break it to see the failure.

① Stolen keyattacker uses leaked key AKIA…7Q → targets flipkart-invoices
② Overwritethey re-PUT each object encrypted with THEIR key (SSE-C) to lock you out
③ Delete originalsthey call DeleteObject on the old versions to remove your copies
④ Extortthey demand ransom; recovery depends entirely on whether you had protection
Press Play to step through the healthy path. Then press Break it.

Karthik at PhonePe faces this

Karthik gets paged: a finance bucket's objects are suddenly unreadable and a 'pay-to-decrypt' text file appeared. CloudTrail shows PutObject calls with SSE-C from an IAM key that belongs to a former contractor.

Likely cause

A long-lived access key was never rotated and leaked. The attacker (Codefinger-style) re-uploaded every object encrypted with their own SSE-C key — which S3 happily accepts and never stores the key for — then set a 7-day delete lifecycle to pressure payment.

Diagnosis

Karthik separates 'reachable' from 'recoverable': access wasn't public, so this is a credential + data-protection failure, not a public-bucket one. He checks whether prior object versions still exist and whether Object Lock is set.

S3 Console > (bucket) > Properties > Bucket Versioning + Object Lock; and CloudTrail > Event history filtered on PutObject/DeleteObject for the contractor's key
Fix

Because versioning was ON, he restores the previous (unencrypted-by-attacker) object versions; revokes and deletes the leaked key; adds a policy to Deny SSE-C uploads (Deny if s3:x-amz-server-side-encryption-customer-algorithm is present); and enables Object Lock + MFA Delete so a future delete is refused outright.

Verify

Old versions are restored and readable; the leaked key is gone from IAM; a test SSE-C PutObject now returns AccessDenied; and Object Lock shows Compliance mode with a retention period.

Quick check · Q3 of 10

Meera must guarantee that quarterly audit logs in S3 cannot be deleted by ANYONE — including a rogue admin with root — for seven years. Which combination does that?

Correct: c. Only Object Lock in Compliance mode makes a version undeletable by every user including the account root for the retention period — exactly the WORM guarantee auditors need. Governance mode can be overridden by a user with the bypass permission, so a rogue admin could still delete. Encryption and Block Public Access protect confidentiality/reachability, not immutability.

Pause & Predict

Predict: your bucket already has default SSE-S3 (the free 2023 base). Why might a security reviewer STILL flag it for a PII workload and ask for SSE-KMS instead? Type your guess.

Answer: Because SSE-S3's key is owned and managed by AWS, you get no per-object audit trail and no ability to scope, rotate, or revoke the key yourself. For PII or regulated data you want SSE-KMS: every decrypt is logged in CloudTrail (who/when/which key), you can deny key use to specific principals as a SECOND lock independent of the bucket policy, and you control rotation. Encryption-at-rest is satisfied either way — but control and auditability are not, and that's what the reviewer (and SCS-C02) cares about.

④ Detect + verify — Access Analyzer, Macie, CloudTrail

Configuring controls is half the job; proving they hold is the other half — and it's where the exam and real audits live. Three tools do the proving. IAM Access Analyzer for S3 tells you which buckets are public or shared cross-account. Amazon Macie tells you which buckets actually contain sensitive data like PAN/Aadhaar-style PII. CloudTrail S3 data events tell you who read or changed which object.

Start with Access Analyzer, because it directly answers "is anything public?". In the S3 console, open General purpose buckets and expand the External access summary — it shows active public and cross-account findings per Region (you first create an external-access analyzer once per Region in the IAM console). For each public bucket it shows whether the access comes from a bucket policy, an ACL, or an access-point policy, and gives you a one-click Block all public access button to fix it.

🖥️ This is where you confirm nothing is public — S3 Console → General purpose buckets → External access summary (powered by IAM Access Analyzer). (Recreated for clarity — your console matches this.)
console.aws.amazon.com · S3 · General purpose buckets
1
Region
ap-south-1 (Mumbai)
2
Bucket
flipkart-invoices
3
Access type
Public
Source
Bucket policy (Principal: *)
4
Recommended action
Block all public access
Block all public access

Then layer in Macie to find the data that actually matters. A sensitive-data discovery job (Macie console → Jobs → Create job) scans selected buckets and reports objects containing credit-card numbers, credentials, passport/PII patterns and more, using built-in managed data identifiers. Automated discovery samples your whole estate daily; targeted jobs go deep on the buckets you choose. The point: a public bucket full of cat photos is a shrug; a public bucket Macie flags as full of PII is a fire.

Figure 3 — The worked fix — flip Block Public Access ON
Same bucket, one toggle: Block Public Access OFF leaks to the world; ON makes the leak instantly 403 A before-and-after of a single S3 bucket. On the left Block Public Access is off and a wildcard bucket policy is attached, so an anonymous internet user reads the objects over plain HTTP and the bucket shows the red Public badge. On the right all four Block Public Access settings are on, ACLs are disabled, a TLS-only deny policy is added, so the same anonymous request returns HTTP 403 and the bucket shows the green Not public badge. Red is the leaking state, green is the locked-down state. The worked fix — flip Block Public Access ON BEFORE · 🔴 Public flipkart-invoices ✗ BPA: all 4 OFF✗ bucket policy: Principal "*" Allow Get✗ plain HTTP allowed internet objects (read!) curl returns 200 OK — anyone reads the PDFs AFTER · 🟢 Not public flipkart-invoices ✓ BPA: all 4 ON (account + bucket)✓ public "*" statement removed✓ Deny if aws:SecureTransport=false internet 403 ✋ curl returns 403 — Access Analyzer finding clears
Before: BPA off + a wildcard policy = a curl returns 200 and anyone reads the PDFs. After: all four BPA on, the '*' statement removed, TLS-only deny added = the same curl returns 403 and the Access Analyzer finding clears.
AWS CLI — verify a bucket is NOT public, then turn on S3 data events in CloudTrail
# 1) Ask S3 directly whether the bucket policy is public
aws s3api get-bucket-policy-status --bucket flipkart-invoices

# 2) Record object-level reads/writes (who-read-what) for the bucket
aws cloudtrail put-event-selectors --trail-name org-trail \
  --event-selectors '[{"ReadWriteType":"All","IncludeManagementEvents":false,\
  "DataResources":[{"Type":"AWS::S3::Object",\
  "Values":["arn:aws:s3:::flipkart-invoices/"]}]}]'
Expected output
{
    "PolicyStatus": { "IsPublic": false }
}
# IsPublic:false after the fix.  Data events now on:
{ "TrailName": "org-trail",
  "EventSelectors": [ { "ReadWriteType": "All",
    "DataResources": [ { "Type": "AWS::S3::Object" } ] } ] }
Figure 4 — How S3 decides allow vs deny — the evaluation order
S3 checks Block Public Access first, then any explicit Deny, then looks for an Allow — default is deny A decision flow for one S3 request. Step 1: does a Block Public Access setting or explicit Deny apply? If yes the request is rejected immediately. Step 2: is there an explicit Allow in an IAM policy, bucket policy, or ACL? If yes, allow. Step 3: if nothing allows, the implicit default deny rejects the request. Amber diamonds are decision points, red is reject, green is allow, the lime tile is the key takeaway that an explicit Deny and Block Public Access beat any Allow. How S3 decides: BPA / Deny → Allow → default deny Request to S3GetObject / PutObject BPA or explicitDeny applies? Explicit Allowanywhere? ALLOW200 OK REJECT (403)Deny / BPA wins, always REJECT (403)implicit default deny no yes yes → stop no → stop Key insight — order mattersBlock Public Access and any explicit Deny are checked FIRST and override every Allow.Same-account: an Allow in IAM OR the bucket policy is enough. Cross-account: you need Allow in BOTH.
The order to memorise for SCS-C02: Block Public Access and any explicit Deny are checked FIRST and beat every Allow; then an explicit Allow; otherwise the implicit default deny rejects. Same-account needs Allow in one place; cross-account needs it in both.
Prove the lockdown in 60 seconds

Run the checklist out loud: (1) get-public-access-block shows all four true at account AND bucket; (2) Object Ownership = BucketOwnerEnforced (ACLs off); (3) default encryption = SSE-KMS with the bucket key on; (4) bucket policy denies aws:SecureTransport=false; (5) versioning on (+ Object Lock for immutable data); (6) IAM Access Analyzer External access summary = 0 public; (7) Macie shows no PII sitting in a shared bucket. If all seven pass, that bucket will not be the next headline.

Figure 5 — Amazon S3 security cheat-sheet
Amazon S3 security on one card — the 4 BPA toggles, encryption picks, the deny-policies, and the verify tools A nine-tile cheat sheet covering the four Block Public Access settings, S3 Object Ownership bucket-owner-enforced, the encryption choice, the bucket key, the two enforce-by-policy conditions aws:SecureTransport and deny-unencrypted-puts, versioning with Object Lock and MFA delete, the detect tools IAM Access Analyzer, Macie and CloudTrail data events, and the lockdown checklist. Each tile has a one-line role. Securing Amazon S3 — your one-glance card 4 Block-Public-Access togglesBlockPublicAcls · IgnorePublicAclsBlockPublicPolicy · RestrictPublicBucketsturn ON all 4 at account + bucket Object OwnershipBucket owner enforced → ACLs OFFdefault on new buckets (Apr 2023)use bucket policy, not ACLs Encryption pickSSE-S3 free base (since Jan 2023)SSE-KMS for PII · SSE-C = rareturn on the Bucket Key (−99% KMS) Enforce in transitDeny if aws:SecureTransport=falseblocks any plain-HTTP requestpair with deny-unencrypted PUTs Ransomware brakesVersioning + Object Lock (WORM)Compliance mode = even root can't+ MFA Delete on the bucket Detect + verifyIAM Access Analyzer → public findsMacie → PII discovery jobsCloudTrail S3 data events = who-read Decision order1 · Block Public Access / explicit Deny2 · explicit Allow (IAM/bucket/ACL)3 · else implicit default deny Lockdown checklist☑ BPA all-4 on · ☑ ACLs disabled☑ SSE-KMS+bucket key · ☑ TLS-only☑ versioning · ☑ Analyzer = 0 public Console pathsBucket ▸ Permissions ▸ Block public accessPermissions ▸ Default encryption / EditS3 ▸ General purpose buckets ▸ Ext. access
Your one-card map of the whole lesson — the four BPA toggles, Object Ownership, the encryption picks + bucket key, the two deny-policies, the ransomware brakes, the detect tools, the decision order, and the console paths. Keep it open in week one and before any S3 interview.

For the cert: this maps straight onto AWS Certified Security – Specialty (SCS-C02). Domain 2 (Security Logging and Monitoring) is your CloudTrail data events and Macie; Domain 4 (Identity and Access Management) is the bucket-policy / BPA / cross-account evaluation; Domain 5 (Data Protection) is SSE-S3/KMS/C, the bucket key, TLS enforcement and Object Lock. S3 questions show up across all three — get this lesson solid and you've covered a meaningful slice of the blueprint.

Quick check · Q4 of 10

An interviewer at ICICI asks Arjun: "A bucket is NOT public, but how do you find out whether it contains customer Aadhaar/PAN data you didn't know about?" Best answer?

Correct: b. Macie's sensitive-data discovery jobs scan object CONTENT with managed data identifiers and report PII like passport/financial/credential data — that's the tool that answers 'what sensitive data is in here?'. Access Analyzer answers 'is it reachable?', not 'what's inside'; Block Public Access and encryption are controls, not discovery.

🤖 Ask the AI Tutor

Tap any question — instant, scoped to this lesson. No login, no waiting.

Pre-curated from AWS docs + community Q&A, scoped to this lesson. For a live prod issue, paste your export into chat.techclick.in.

📝 Wrap-up assessment — six more

You've answered 4 inline. Six left. 70% (7 of 10) marks the lesson complete on your profile. Tap Submit all answers at the end.

Q5 · Remember

Which Amazon S3 feature provides four account- and bucket-level toggles that override any bucket policy or ACL granting public access?

Correct: a. S3 Block Public Access provides the four settings (BlockPublicAcls, IgnorePublicAcls, BlockPublicPolicy, RestrictPublicBuckets) that override public grants. Object Lock is about immutability, Macie is sensitive-data discovery, and the Bucket Key reduces KMS cost — none of those block public access.
Q6 · Apply

You create a new S3 bucket in 2026 to store PII and want strong, auditable encryption at rest plus low cost on a high-traffic bucket. What do you enable?

Correct: d. SSE-KMS gives you a key you control with CloudTrail audit (right for PII), and the S3 Bucket Key cuts KMS API calls by up to 99% to control cost. SSE-C means you manage/lose keys and get no real audit; SSE-S3 lacks per-object auditability; and Block Public Access is reachability, not encryption.
Q7 · Apply

Your team must enforce that NO request to a bucket is ever accepted over plain HTTP. Which bucket-policy element does that?

Correct: c. A Deny statement triggered when aws:SecureTransport is false rejects every non-TLS request (403) — the standard HTTPS-only pattern. An Allow on the true case doesn't deny the false case; default encryption is at-rest, not in-transit; and Object Ownership controls ACLs, not transport.
Q8 · Analyze

A bucket policy grants access to partner account 210987654321 AND has a separate "Principal": "*" Allow statement. You enable RestrictPublicBuckets. What happens to the partner's access, and why?

Correct: b. Once any statement renders the policy public, S3 treats the entire policy as public, so RestrictPublicBuckets restricts the bucket to AWS service principals and the owner account — cutting even the explicitly-named partner. Remove the '*' statement and the partner regains access. The exemption/no-change options misread how 'public policy' poisons the whole document.
Q9 · Analyze

An attacker with a stolen IAM key (s3:GetObject + s3:PutObject + s3:DeleteObject) re-encrypts your objects with SSE-C and deletes the originals. Your bucket had versioning + Object Lock in Compliance mode. What is the outcome?

Correct: a. Object Lock in Compliance mode makes existing versions undeletable by anyone for the retention period, so the attacker's DeleteObject fails and your clean prior versions survive — you restore and ignore the ransom. SSE-C only matters if originals are gone (they aren't); Block Public Access wouldn't help because access wasn't public (it was a leaked key).
Q10 · Evaluate

Two ways to assure leadership that S3 is secure: (A) "every bucket has SSE-S3 default encryption on, so our data is encrypted"; (B) "all four Block Public Access settings are on account-wide, ACLs are disabled, PII buckets use SSE-KMS + TLS-only policies and Object Lock, and IAM Access Analyzer shows zero public buckets." Which is the stronger assurance and why?

Correct: d. B is a layered, verified posture: Block Public Access + disabled ACLs stop exposure, SSE-KMS + TLS protect confidentiality with audit, Object Lock stops ransomware/deletion, and Access Analyzer PROVES nothing is public. A is dangerously incomplete — default encryption does nothing against an authorised or public reader, which is exactly how public-bucket breaches leak encrypted-at-rest data.
Lesson complete — saved to your profile.
Almost! You need 70% (7 of 10) — re-read the path that tripped you up and tap "Try again".

🧠 In your own words

Type one line: In one line: why does turning ON account-level Block Public Access protect you even from a bucket policy that says "Principal": "*"? Then compare to the expert version.

Expert version: Because Block Public Access is evaluated before the policy and overrides it — S3 rejects any request that public-access settings prohibit, regardless of what the bucket policy or ACL grants, and account-level BPA applies that protection to every current and future bucket.

🗣 Teach a friend

Best way to lock it in — explain it in one line to a teammate. Tap to generate a paste-ready summary.

📖 Glossary

S3 bucket
A storage container in Amazon S3 that holds objects (files). Globally named and private by default.
Block Public Access (BPA)
Account- and bucket-level settings (4 toggles) that override any policy or ACL granting public access. The master safety switch.
BlockPublicAcls / IgnorePublicAcls
BPA toggles for ACLs: reject NEW public ACLs, and ignore ALL existing public ACLs, respectively.
BlockPublicPolicy / RestrictPublicBuckets
BPA toggles for policies: reject a policy that would grant public access, and restrict a bucket that already has a public policy to AWS services + the owner account.
Object Ownership (bucket-owner-enforced)
Bucket setting that disables ACLs entirely; the owner controls every object via policies. Default on new buckets since April 2023.
ACL
Access Control List — the legacy, coarse S3 permission model (grant to AllUsers/AuthenticatedUsers). Discouraged; disabled by default.
Bucket policy
A resource-based JSON policy on the bucket stating which principals may perform which actions. Where 'Principal: *' leaks happen.
SSE-S3 / SSE-KMS / SSE-C
Server-side encryption with: an AWS-managed AES-256 key (free, default), a KMS key you control + audit, or a customer-supplied key AWS never stores.
S3 Bucket Key
Bucket setting that uses one bucket-level data key to cut SSE-KMS API calls — reducing KMS cost by up to 99%.
aws:SecureTransport
Policy condition key; Deny when it is false to force TLS (HTTPS-only) and block plain-HTTP requests.
Versioning / MFA Delete
Keep every object version (delete adds a marker); MFA Delete requires a second factor to permanently remove versions or change versioning.
Object Lock (WORM)
Write-Once-Read-Many protection. Governance mode = override with a permission; Compliance mode = nobody (even root) can delete until retention ends.
IAM Access Analyzer for S3
Reports buckets reachable by the public internet or other accounts, shown as the 'External access summary' in the S3 console.
Amazon Macie
Scans S3 object content for sensitive data (PII, credentials, financial info) via automated discovery or targeted jobs.

📚 Sources

  1. AWS Documentation — Amazon S3 User Guide, "Blocking public access to your Amazon S3 storage" (the four BPA settings BlockPublicAcls/IgnorePublicAcls/BlockPublicPolicy/RestrictPublicBuckets, account vs bucket level, the meaning of "public" for ACLs and policies, most-restrictive evaluation). docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-block-public-access.html
  2. AWS Documentation — Amazon S3 User Guide, "Controlling ownership of objects and disabling ACLs" (bucket-owner-enforced disables ACLs; default on new buckets; AccessControlListNotSupported error) + "Setting default server-side encryption behavior" (SSE-S3 base, bucket keys). docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html · docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-encryption.html
  3. AWS News — "Amazon S3 now automatically encrypts all new objects" (SSE-S3 base encryption on every bucket at no cost, effective 5 January 2023). aws.amazon.com/about-aws/whats-new/2023/01/amazon-s3-encrypts-new-objects-default/
  4. AWS Documentation — "Reviewing bucket access using IAM Access Analyzer for S3" + Amazon Macie User Guide "Discovering sensitive data with Macie" / "Creating a sensitive data discovery job" (External access summary console path; managed data identifiers; discovery jobs). docs.aws.amazon.com/AmazonS3/latest/userguide/access-analyzer.html · docs.aws.amazon.com/macie/latest/user/discovery-jobs-create.html
  5. Halcyon Threat Research — "Abusing AWS Native Services: Ransomware Encrypting S3 Buckets with SSE-C" (Codefinger campaign, disclosed 13 Jan 2025: leaked keys with s3:GetObject/s3:PutObject + SSE-C to encrypt objects AWS can't recover; only an HMAC is logged) + Amazon S3 Object Lock feature page (WORM, Governance/Compliance, Cohasset SEC 17a-4 assessment). halcyon.ai/blog/abusing-aws-native-services-ransomware-encrypting-s3-buckets-with-sse-c · aws.amazon.com/s3/features/object-lock/
  6. AWS Certified Security – Specialty (SCS-C02) exam guide — Domain 2 (Logging & Monitoring: CloudTrail data events, Macie), Domain 4 (IAM: bucket policy / BPA / cross-account), Domain 5 (Data Protection: SSE-S3/KMS/C, bucket key, aws:SecureTransport, Object Lock). aws.amazon.com/certification/certified-security-specialty/

What's next?

You've locked S3 down and proved it isn't public. But who's poking at your account RIGHT NOW — the leaked-key reads, the recon API calls, the impossible-travel logins? Next we turn on the threat-detection layer that watches all of it.