Web applications and APIs represent the primary attack surface for modern enterprises. Because web services must remain publicly accessible to legitimate users over ports 80 and 443, perimeter firewalls alone cannot distinguish between legitimate business traffic and malicious application-layer exploits.
The Open Worldwide Application Security Project (OWASP) publishes the authoritative OWASP Top 10, identifying the most critical web application security risks. In this guide, we analyze the architectural root causes of leading web vulnerabilities (SQL Injection, Cross-Site Scripting, and Server-Side Request Forgery) and implement production defenses.
1. Injection Vulnerabilities (SQL Injection)#
Injection occurs when untrusted user input is directly concatenated into a dynamic database interpreter query without contextual escaping or parameterization:
# VULNERABLE CODE (DO NOT USE IN PRODUCTION)
# If user inputs: ' OR 1=1 --
query = f"SELECT * FROM users WHERE username = '{user_input}'"The database interpreter interprets ' OR 1=1 -- as SQL syntax rather than literal data, returning all user records in the table and bypassing authentication.
Production Defense: Parameterized Queries (Prepared Statements)#
Prepared statements separate the SQL code from user-supplied data. The SQL query structure is pre-compiled by the database engine into an execution plan. User input is transmitted separately as parameter values and treated strictly as literal data, making SQL injection mathematically impossible:
# SECURE DEFENSE: Using Parameterized Placeholders
import sqlite3
def authenticate_user(username: str, password_hash: str):
conn = sqlite3.connect("enterprise.db")
cursor = conn.cursor()
# User input is bound as parameters (?), never concatenated
query = "SELECT id, email, role FROM users WHERE username = ? AND password_hash = ?"
cursor.execute(query, (username, password_hash))
return cursor.fetchone()2. Cross-Site Scripting (XSS)#
Cross-Site Scripting occurs when an application includes untrusted data in an HTTP response rendered by a victim's browser without adequate validation or encoding:
- Stored XSS: Malicious script is permanently stored in a database (e.g., in a comment field) and served to every user viewing the page.
- Reflected XSS: Malicious script is reflected off the web server in an immediate HTTP response (e.g., inside a search query error message).
- DOM-based XSS: Vulnerability exists purely in client-side JavaScript executing untrusted data from
location.searchdirectly into sinks likeinnerHTMLordocument.write.
Impact of XSS#
Once malicious JavaScript executes in the victim's browser context, the attacker can:
- Steal sensitive session authentication cookies (
document.cookie). - Perform unauthorized actions on behalf of the user (account takeover).
- Capture keystrokes (in-browser keylogger) or redirect users to malicious phishing portals.
Multi-Layer XSS Defenses:#
- Context-Aware Output Encoding: Encode HTML entities (
<,>,",',&) before rendering dynamic data. Modern frameworks (React, Next.js, Angular) perform contextual encoding by default when using standard JSX expressions{data}. - HttpOnly Cookies: Protect session cookies by setting the
HttpOnlyflag. When enabled, client-side JavaScript cannot readdocument.cookie, neutralizing session theft via XSS! - Content Security Policy (CSP): An HTTP response header instructing the browser which domains can execute scripts:
```http
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-cdn.com; object-src 'none';
```
3. Server-Side Request Forgery (SSRF)#
Server-Side Request Forgery occurs when a web application fetches a remote resource (e.g., downloading an avatar image or importing a webhook URL) without validating the destination address supplied by the user.
An attacker supplies an internal loopback or cloud metadata IP address:
Target URL: http://169.254.169.254/latest/meta-data/iam/security-credentials/admin-roleBecause the request originates from the trusted web server inside the private VPC, the AWS Instance Metadata Service (IMDS) responds with IAM credentials, allowing the attacker to compromise the entire cloud account!
Production SSRF Mitigations:#
- Strict URL Allow-listing: Validate requested URLs against an explicit allow-list of approved domains and protocols (e.g., only HTTPS).
- DNS Resolution & Private IP Blocking: Resolve the hostname via DNS and reject any IP address falling within RFC 1918 private subnets (
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16) or link-local ranges (169.254.169.254,127.0.0.1). - Enforce IMDSv2: In cloud environments, mandate IMDSv2, which requires a session token obtained via HTTP PUT request with custom headers that SSRF payloads cannot forge.
Checkpoint Questions & Practice Exercises#
Question 1: Why does setting the HttpOnly flag on session cookies fail to prevent Cross-Site Request Forgery (CSRF) or prevent an attacker from executing API requests via an active XSS exploit?
- Answer:
HttpOnlystrictly prevents JavaScript from reading the cookie value. When an attacker exploits XSS or CSRF to trigger an HTTP request to the backend server, the browser automatically attaches the session cookie to the outbound request regardless ofHttpOnly. To prevent CSRF, anti-CSRF tokens orSameSite=Strictcookie flags are required.
Question 2: Explain the mechanism of a Blind SQL Injection attack and how an adversary extracts database information without seeing query errors or outputs.
- Answer: In Blind SQLi, the application reveals no error messages or query results. An adversary infers information using boolean logic (observing whether the page loads normally or differently based on conditions like
AND SUBSTRING(password, 1, 1) = 'a') or time-based blind logic (forcing the database to sleep viapg_sleep(5)orWAITFOR DELAYand measuring HTTP response latency).