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:
- What data crosses from browser to server?
- What validation could be client-side only?
- 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
- What is a trust boundary, and what must you do at one?
- Give five things that are part of a web application's attack surface.
- Why is reducing attack surface such good value?
- 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.