OWASP Top 10 Guide

OWASP Top 10 — 2021

A01: Broken Access Control

Failures allowing users to act outside intended permissions. Prevent: enforce least privilege, deny by default, log access control failures.

A02: Cryptographic Failures

Weak encryption exposes sensitive data. Prevent: use TLS 1.2+, AES-256, avoid MD5/SHA1 for passwords, use bcrypt/Argon2.

A03: Injection

SQL, NoSQL, OS, LDAP injection via untrusted data. Prevent: parameterized queries, input validation, ORMs.

A04: Insecure Design

Missing or ineffective security controls by design. Prevent: threat modeling, secure design patterns, defense in depth.

A05: Security Misconfiguration

Default credentials, verbose error messages, open cloud storage. Prevent: hardening guides, automated config scanning.

A06: Vulnerable and Outdated Components

Using libraries with known CVEs. Prevent: SCA tools (Dependabot, Snyk), regular updates, SBOM.

A07: Identification and Authentication Failures

Weak passwords, credential stuffing, missing MFA. Prevent: strong password policy, MFA, brute-force protection.

A08: Software and Data Integrity Failures

Insecure deserialization, unsigned updates. Prevent: verify signatures, use trusted repositories, CI/CD integrity checks.

A09: Security Logging and Monitoring Failures

Insufficient logging allows attackers to persist. Prevent: log all security events, use SIEM, alert on anomalies.

A10: Server-Side Request Forgery (SSRF)

App fetches remote resource without validating URL. Prevent: allowlist target URLs, block internal IP ranges, disable unnecessary URL schemes.

SQL Injection — Secure vs Insecure

// INSECURE - Direct string concatenation query := "SELECT * FROM users WHERE email = '" + email + "'" // Attacker input: ' OR '1'='1 // SECURE - Parameterized query (Go) row := db.QueryRow("SELECT * FROM users WHERE email = $1", email) // SECURE - Prepared statement stmt, _ := db.Prepare("SELECT * FROM users WHERE email = ?") row := stmt.QueryRow(email)

XSS Prevention

// INSECURE - Direct HTML injection innerHTML = userInput; // SECURE - Escape output element.textContent = userInput; // SECURE - DOMPurify for rich content import DOMPurify from 'dompurify'; element.innerHTML = DOMPurify.sanitize(userInput); // Content Security Policy header Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{random}';