Frontend Labs
⋯

Chapter 2 — Thinking like an attacker

In one sentence

Attackers don't break your design; they find the places you never considered part of your design.

The idea

Developers think about the happy path. Attackers think about everything else.

   DEVELOPER: "The user enters their email and we send a reset link."

   ATTACKER:  What if the email is 10 MB long?
              What if it's someone else's email?
              What if it contains SQL? Or a script tag? Or a newline
                that injects an extra SMTP header?
              What if I request 10,000 resets a second?
              Is the reset token random? How long is it valid?
              Can I use it twice? Does it work after a password change?
              What does the response tell me about whether the account exists?
              Is the link sent over HTTPS? Does it leak in the Referer header?

Same feature. Ten attacks. The discipline is asking those questions systematically instead of hoping you thought of them.

Attack surface

Everything an attacker can reach and interact with.

   Your application's attack surface includes:

   ENTRY POINTS       every URL, API endpoint, form field, header, cookie,
                      file upload, webhook, queue message, CLI argument,
                      environment variable, config file
   DEPENDENCIES       every library, container image, base OS package,
                      CI/CD action, browser extension in your pipeline
   INFRASTRUCTURE     open ports, cloud metadata endpoints, admin panels,
                      backup buckets, DNS records, forgotten subdomains
   PEOPLE             support staff who can reset passwords, anyone who
                      can be phished, contractors, ex-employees
   PHYSICAL           laptops, USB ports, the office door

Reducing attack surface is the cheapest security work available. A deleted endpoint has no vulnerabilities. An uninstalled package can't be exploited.

Trust boundaries

The single most useful concept in this chapter. A trust boundary is any point where data crosses from a place you control to one you don't (or vice versa).

   INTERNET  --------->|  your load balancer   ------> your app -----> your DB
             boundary 1|              boundary 2|            boundary 3|

   At EVERY boundary you must ask:
      * Do I know who this is?           (authentication)
      * Are they allowed to do this?     (authorization)
      * Is this data shaped as expected?  (validation)
      * What happens if it's hostile?    (the actual question)

Validation happens at boundaries. The classic mistake is validating in the browser (inside the attacker's control) and trusting it on the server.

Rule to memorise: anything that crosses a trust boundary toward you is untrusted, no matter who sent it. Including your own frontend. Including another microservice. Including a "trusted" partner's webhook.

The attacker's process

Real attacks follow a predictable shape (this is the "kill chain"):

   1. RECON        find out what exists: subdomains, ports, versions,
                   employees on LinkedIn, leaked credentials
   2. INITIAL      get a foothold: phishing, an exposed service,
      ACCESS       a known CVE, stolen credentials
   3. EXECUTION    run code
   4. PERSISTENCE  survive a reboot or a password change
   5. PRIVILEGE    become root / admin / a service account
      ESCALATION
   6. LATERAL      move to more valuable systems
      MOVEMENT
   7. COLLECTION   find and stage the data
   8. EXFILTRATION get it out
   9. IMPACT       ransomware, destruction, fraud

Defensive value: you can break the chain at any link. Most organisations obsess over step 2 and ignore 4–8, which is where they'd actually detect a real intrusion. This model is formalised in MITRE ATT&CK (Chapter 49) — a free, extremely detailed catalogue of real techniques.

Practice (25 min)

A. Enumerate an attack surface. For the Juice Shop instance from §0.4:

docker start juice 2>/dev/null || docker run --rm -d -p 3000:3000 --name juice bkimminich/juice-shop
sleep 15

# What's listening?
nmap -sV -p 3000 localhost

# What does the app tell us about itself?
curl -sI http://localhost:3000 | head -20
curl -s http://localhost:3000 | grep -oE 'src="[^"]+"' | head -20

B. Find the trust boundaries in the Juice Shop login flow. Open the browser's DevTools → Network, log in with anything, and list:

  1. What data crosses from browser to server?
  2. What validation could be client-side only?
  3. What does the error message reveal?

C. Think it through. For your own project (or one you know), write down five entry points you'd forgotten existed. Almost everyone finds at least one.

Common confusions

  • "Attackers are geniuses." Overwhelmingly they run automated tools against known vulnerabilities. The sophisticated ones exist but aren't your first problem.
  • "Our API is internal so it's safe." Internal networks get breached; then every unauthenticated internal service is free. This is why "zero trust" exists.
  • "Obscurity helps." A hidden endpoint is found by a scanner in minutes. Obscurity is fine as a bonus layer, never as the control.

Check yourself

  1. What is a trust boundary, and what must you do at one?
  2. Give five things that are part of a web application's attack surface.
  3. Why is reducing attack surface such good value?
  4. Name three stages of the attack chain after initial access.

Further reading

  • Framework: MITRE ATT&CK (attack.mitre.org) — the encyclopedia of real attacker techniques. Browse one tactic column; it's eye-opening.
  • Book: The Web Application Hacker's Handbook — Stuttard & Pinto. Dated in places, still the best mental model for attacking web apps.
  • Practice: PortSwigger Web Security Academy (portswigger.net/web-security) — free, superb, hands-on labs. Start it now and work through it alongside Part 10.

Generated from real-life-guide.md · 8 Oct 2026 16:36