๐Ÿƒ Web Security: OWASP Top 10

Injection, XSS, CSRF, broken auth, misconfig & secure coding

Card 0 of 19 flipped
overview

What is the OWASP Top 10?

A regularly updated list of the 10 most critical web application security risks. Published by the Open Web Application Security Project. Standard awareness document for developers and security teams.

#1
A01

A01: What is Broken Access Control?

Users acting beyond their permissions. Includes: accessing other users' data by changing IDs, privilege escalation, CORS misconfiguration, forced browsing to admin pages. #1 risk in OWASP 2021.

# Vulnerable โ€” direct object reference
GET /api/users/42/orders  # attacker changes to 43

# Fix โ€” verify ownership
@app.get("/api/users/{id}/orders")
def get_orders(id, current_user):
    if id != current_user.id and not current_user.is_admin:
        raise HTTPException(403)
    return db.get_orders(id)
#2
A02

A02: What are Cryptographic Failures?

Sensitive data exposed due to weak/missing encryption. Includes: plaintext passwords, weak algorithms (MD5, SHA1), missing TLS, hardcoded keys, insufficient key management.

# BAD
password_hash = md5(password)        # weak hash
conn = http://api.example.com        # no TLS
SECRET_KEY = "hardcoded-in-source"   # exposed

# GOOD
password_hash = bcrypt.hash(password, rounds=12)
conn = https://api.example.com       # TLS
SECRET_KEY = os.environ['SECRET_KEY'] # from env
#3
A03

A03: What is Injection?

Untrusted data sent as part of a command or query. SQL injection, NoSQL injection, OS command injection, LDAP injection. Always use parameterized queries, never string concatenation.

# VULNERABLE โ€” SQL injection
query = f"SELECT * FROM users WHERE name = '{user_input}'"
# Input: ' OR '1'='1  โ†’ dumps all users

# SAFE โ€” parameterized query
cursor.execute(
    "SELECT * FROM users WHERE name = %s",
    (user_input,)
)
#4
A04

A04: What is Insecure Design?

Flaws in architecture and design, not implementation bugs. Missing threat modeling, insecure business logic, no rate limiting on sensitive operations. Fix: threat model early, secure design patterns.

# Insecure design examples:
- No rate limit on password reset โ†’ brute force
- No purchase limit โ†’ bot buying all stock
- Security questions as only 2FA
- No re-auth for sensitive changes

# Fix: design-level controls
- Rate limiting on all auth endpoints
- CAPTCHA on registration
- Re-authentication for profile changes
- Threat modeling during design phase
#5
A05

A05: What is Security Misconfiguration?

Default credentials, unnecessary features enabled, missing security headers, verbose error messages, unpatched systems. Most common in cloud, containers, and frameworks.

# Common misconfigs:
- Default admin:admin credentials
- Directory listing enabled
- Stack traces in production errors
- Unnecessary ports open
- Missing security headers

# Security headers to set:
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Content-Security-Policy: default-src 'self'
Strict-Transport-Security: max-age=31536000
#6
A06

A06: What are Vulnerable and Outdated Components?

Using libraries, frameworks, or software with known vulnerabilities. Includes: outdated dependencies, unmaintained packages, not monitoring CVEs. Automate dependency scanning.

# Check for vulnerabilities
npm audit                    # Node.js
pip-audit                    # Python
bundle audit                 # Ruby

# Automate with CI/CD
- GitHub Dependabot
- Snyk
- OWASP Dependency-Check

# Keep updated
npm update
pip install --upgrade package
#7
A07

A07: What are Identification and Authentication Failures?

Weak passwords allowed, no brute-force protection, session IDs in URL, missing MFA, credential stuffing attacks. Previously called 'Broken Authentication'.

# Vulnerabilities:
- Permits weak passwords (password123)
- No account lockout after failed attempts
- Session token in URL parameters
- Missing multi-factor authentication

# Fixes:
- Enforce strong passwords + check breached lists
- Rate limit login attempts
- Secure session management (HttpOnly, Secure cookies)
- Implement MFA (TOTP, WebAuthn)
#8
A08

A08: What are Software and Data Integrity Failures?

Code or data from untrusted sources without verification. Includes: insecure CI/CD pipelines, auto-update without signature checks, insecure deserialization, compromised dependencies.

# Vulnerable โ€” unsigned updates
update_url = "http://example.com/update.zip"
# No integrity check, HTTP not HTTPS

# Secure โ€” verify integrity
import hashlib
expected_hash = "a1b2c3..."
actual_hash = hashlib.sha256(data).hexdigest()
assert actual_hash == expected_hash

# Use SRI for CDN scripts
<script src="cdn.js"
  integrity="sha384-abc123..."
  crossorigin="anonymous">
#9
A09

A09: What are Security Logging and Monitoring Failures?

Insufficient logging of security events, no alerting on attacks, logs not protected. Attackers average 200+ days undetected. Log auth events, access control failures, input validation failures.

# What to log:
- Login attempts (success + failure)
- Access control failures
- Input validation failures
- Server-side errors
- Admin actions

# Log format (structured)
{"timestamp": "2025-01-15T10:30:00Z",
 "level": "WARN",
 "event": "auth.login_failed",
 "ip": "1.2.3.4",
 "user": "admin",
 "reason": "invalid_password"}
#10
A10

A10: What is Server-Side Request Forgery (SSRF)?

Attacker tricks the server into making requests to internal resources. Can access metadata services, internal APIs, or private networks. Always validate and whitelist destination URLs.

# Vulnerable โ€” user controls URL
@app.post("/fetch")
def fetch_url(url: str):
    return requests.get(url).text
# Attacker: url=http://169.254.169.254/metadata
# โ†’ leaks cloud credentials!

# Fix โ€” validate and whitelist
ALLOWED_HOSTS = ["api.example.com"]
def fetch_url(url: str):
    parsed = urlparse(url)
    if parsed.hostname not in ALLOWED_HOSTS:
        raise ValueError("Host not allowed")
#11
XSS

What is Cross-Site Scripting (XSS)?

Injecting malicious scripts into web pages viewed by others. Stored XSS (in DB), Reflected XSS (in URL), DOM XSS (client-side). Escape output, use CSP, sanitize HTML.

# Vulnerable
<p>Welcome, {{ user_input }}</p>
# Input: <script>document.cookie</script>

# Fixes:
# 1. Escape output
<p>Welcome, {{ user_input | escape }}</p>

# 2. Content Security Policy
Content-Security-Policy: script-src 'self'

# 3. HttpOnly cookies (JS can't read)
Set-Cookie: session=abc; HttpOnly; Secure
#12
CSRF

What is Cross-Site Request Forgery (CSRF)?

Attacker tricks authenticated user into making unwanted requests. User's browser sends cookies automatically. Prevent with CSRF tokens, SameSite cookies, and checking Origin/Referer headers.

# Attack: hidden form on evil site
<form action="https://bank.com/transfer" method="POST">
  <input name="to" value="attacker">
  <input name="amount" value="10000">
</form>
<script>document.forms[0].submit()</script>

# Fixes:
# 1. CSRF token in forms
<input type="hidden" name="csrf" value="random-token">

# 2. SameSite cookie
Set-Cookie: session=abc; SameSite=Strict
#13
injection

How do you prevent SQL injection?

Use parameterized queries (prepared statements) everywhere. Use ORMs. Validate input types. Apply least-privilege database permissions. Never build queries with string concatenation.

# Python โ€” parameterized
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))

# Node.js โ€” parameterized
db.query('SELECT * FROM users WHERE id = $1', [userId])

# ORM (SQLAlchemy)
User.query.filter_by(id=user_id).first()

# Stored procedure
CALL get_user_by_id(?)
#14
headers

What are secure headers every web app should set?

Security headers instruct browsers to enable protections. Essential ones: HSTS, CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy.

# Essential security headers
Strict-Transport-Security: max-age=63072000; includeSubDomains
Content-Security-Policy: default-src 'self'; script-src 'self'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
#15
auth

How do you securely store and handle passwords?

Hash with bcrypt, scrypt, or Argon2 (adaptive work factor). Never MD5/SHA1. Salt is included automatically. Never store plaintext. Use breach detection (HaveIBeenPwned API).

import bcrypt

# Hash password (salt auto-generated)
hashed = bcrypt.hashpw(
    password.encode('utf-8'),
    bcrypt.gensalt(rounds=12)
)

# Verify
bcrypt.checkpw(
    password.encode('utf-8'),
    hashed
)  # True/False

# NEVER:
# md5(password), sha1(password), plaintext
#16
headers

What is Content Security Policy (CSP)?

CSP tells browsers which sources of content are allowed. Prevents XSS by blocking inline scripts and unauthorized sources. Start with report-only mode, then enforce.

# Strict CSP
Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-abc123';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  connect-src 'self' https://api.example.com;
  frame-ancestors 'none';
  report-uri /csp-report

# Report-only (testing)
Content-Security-Policy-Report-Only: ...
#17
auth

How do you secure JWT tokens?

Use strong signing algorithms (RS256, ES256, not HS256 with weak secrets). Short expiry (15-30 min). Store in HttpOnly cookies, not localStorage. Validate issuer, audience, and expiry.

# Secure JWT practices:
- Algorithm: RS256 or ES256 (asymmetric)
- Expiry: 15-30 minutes
- Refresh: separate long-lived refresh token
- Storage: HttpOnly, Secure, SameSite cookie
- Validate: iss, aud, exp, iat

# NEVER:
- Store in localStorage (XSS vulnerable)
- Use 'none' algorithm
- Skip expiry validation
- Put sensitive data in payload
#18
principles

What is the principle of least privilege?

Give every user, process, and system only the minimum permissions needed. Applies to database users, API keys, IAM roles, file permissions. Reduces blast radius of breaches.

# Database โ€” per-service users
CREATE USER api_readonly;
GRANT SELECT ON orders TO api_readonly;
-- NOT: GRANT ALL PRIVILEGES

# AWS IAM โ€” scoped policies
{
  "Effect": "Allow",
  "Action": ["s3:GetObject"],
  "Resource": "arn:aws:s3:::my-bucket/uploads/*"
}
-- NOT: "Action": "s3:*", "Resource": "*"
#19
principles

What is a Web Application Firewall (WAF) and how does it protect against OWASP Top 10?

A WAF inspects HTTP traffic and blocks malicious requests using rulesets. It operates at Layer 7 and can detect SQLi, XSS, and other injection patterns. WAFs complement โ€” but don't replace โ€” secure coding practices.

# AWS WAF rule examples:
# Block SQL injection
aws wafv2 create-rule-group \
  --name "SQLi-Protection" \
  --rules '[{
    "Statement": {
      "SqliMatchStatement": {
        "FieldToMatch": { "Body": {} },
        "TextTransformations": [
          { "Priority": 0, "Type": "URL_DECODE" },
          { "Priority": 1, "Type": "HTML_ENTITY_DECODE" }
        ]
      }
    },
    "Action": { "Block": {} }
  }]'

# WAF deployment options:
# AWS WAF      โ€” ALB, CloudFront, API GW
# Cloudflare   โ€” DNS-based, edge proxy
# ModSecurity  โ€” open-source, Apache/Nginx
# OWASP CRS    โ€” core rule set for ModSec
#20