Recon, offense, defense: web security told from both sides of the firewall.
Why this book
Most developers learn security as a list of prohibitions: escape your output, use prepared statements, turn on HTTPS. We apply, we tick boxes, and we couldn't explain what each rule actually blocks. The day a flaw falls outside the known catalog, nobody sees it coming. Hoffman walks the opposite way: a third of the book to map an application like an attacker would, a third to actually attack it, and only then a third to defend it. Defense comes last because it means nothing before.
That's exactly the stance I took for this site's security course: show how sqlmap, Burp or Hydra are used before explaining the protections. This book is the long version of that conviction. I read the first edition (2020); the second (2024) adds material I detail below.
The ideas that stay
1Hacking is older than the computer
We like to think software security starts with the web. Hoffman opens with a century of history. In 1932, Polish mathematician Marian Rejewski reconstructed Enigma's inner workings from a stolen machine and configurations supplied by a spy; Turing then automated the codebreaking by exploiting an organizational detail: the Germans broadcast an encrypted weather report every day, so its content was predictable. His machine tested 20,000 configurations in 20 minutes. The technique has a name still taught today: the known plaintext attack (ch. 1).
Then come the phreakers of the sixties. Back then, AT&T's network drove its switches with tones traveling on the same line as the voice, and 2,600 Hz was the internal signal marking the end of a call. Whoever emits that note keeps the line open without being billed. Joe Engressia could whistle it with his mouth; John Draper found that the toy whistle in Cap'n Crunch cereal boxes produced it exactly. The result: free international calls with a breakfast toy.
The lesson carries through the whole book: AT&T's engineers had designed the network for the honest user, not for the one who games the system's rules. "Always consider the worst-case scenario first when designing complex systems" (ch. 1).
2A hacker is first and foremost a detective
We picture an attack as a stroke of technical brilliance. The book describes it differently: "a hacker is first and foremost a detective" (ch. 9). A third of the book is spent mapping an application without ever touching its code. The tools come down to a few moves:
- Google operators:
site:target.com -inurl:wwwsurfaces forgotten subdomains; - archive.org snapshots, where links to supposedly retired servers still linger;
- the DNS zone transfer: two lines of bash that, against a misconfigured server, hand over every subdomain and its IP;
- the dnscan dictionary, built from 86,000 real zone files.
Why all this effort? The public storefront is watched around the clock, its bugs fixed fast. The backstage servers (mail, admin, dev) are "riddled with bugs as they have much less use and exposure" (ch. 4). Recon isn't looking for the front door: it's looking for the service entrance.
3XSS: four faces, and the worst one beats the filters
The book's running thread is a fictional bank, MegaBank. A customer slips a <strong> tag into a support ticket; the agent replies "how did you bold that text?". The detail is funny, but it says everything: HTML travels through the application with no filter at all. What comes next is far less funny. This time the attacker posts a <script> that gets stored in the database. Every time an agent opens the ticket, the script runs in THEIR browser, scrapes the names, emails and phone numbers on screen, and ships them to a rogue server (ch. 10). That's stored XSS: the most profitable kind, because it hits everyone who reads the ticket.
The family has three other faces:
- reflected: the booby-trapped code lives in a URL you're tricked into clicking, it's never stored;
- DOM-based: everything happens in the browser, the server sees nothing, so no log catches it;
- mutation XSS, the trickiest: the browser itself rewrites the HTML after the cleanup, reopening a hole everyone thought was closed. That's how, in 2019, a payload by Masato Kinugawa walked through DOMPurify, the reference sanitizer.
The defense fits in one rule (ch. 22): user data never enters the page as HTML, only as text. The 2nd edition goes further with polyglot payloads (one piece of code valid in several contexts at once) and encoding bypasses.
4CSRF: your browser signs on your behalf
An HTTP request always travels with your cookies, even when you never asked for it. All of CSRF fits in that sentence. The book's example: an invisible zero-pixel image whose address points at mega-bank.com's transfer endpoint, with the attacker's account and the amount tucked into the URL. The page renders, the browser "loads the image", and the transfer goes out with your open session (ch. 11). A nastier variant: a fake login form that, on submit, actually fires a wire transfer while you think you're signing in.
The defense stacks in three layers (ch. 23):
- an architecture rule first: a GET never changes server state (it reads, it doesn't write);
- origin and referer header checks, which reveal where the request actually came from;
- finally the stateless anti-CSRF token: a unique value (user id, timestamp and nonce encrypted together server-side) that the trap page has no way to guess.
The "a GET changes nothing" rule remains a foundation of clean API design, attack or not.
5Injection climbs the ladder: the database, the tool, the system
"Injection" brings SQL to mind, and we often stop there. Hoffman grades the threat in three rungs (ch. 13):
- SQL injection: a
user_idworth'1=1'returns the whole table, a'; DROP TABLE users;'deletes it; - code injection: the target is no longer the database but a command-line tool the server calls; an unfiltered filename passed to an image converter is enough to overwrite the site's logo;
- command injection, the most severe rung: you talk straight to the operating system.
exec(`rm /videos/raw/${req.body.name}`); // name = "myVideo.mp4 && rm -rf /videos/converted/" // the server runs BOTH commands
At that level, the attacker reads /etc/passwd, grabs SSH keys, and rewrites logs to erase their tracks.
The defense (ch. 25):
- prepared statements: the query is compiled before the variables arrive, so an injected
UPDATEstays a plain string of text; - an allowlist of the commands the server is allowed to run;
- one OS user per module, with the minimum permissions it needs.
The 2nd edition adds the three ways to smuggle stolen data out: in the response itself, out-of-band, or by inference (response timing, error messages).
6The chain breaks at the least-tested link
Your code gets reviewed and audited; your hundreds of npm dependencies don't. Hoffman documents two cases from 2018 (ch. 15):
- eslint-scope: a maintainer's stolen credentials let someone publish a booby-trapped version that, in turn, stole the credentials of everyone who installed it;
- event-stream: an obfuscated sub-dependency (flatmap-stream) hunted for Bitcoin wallets on the machines that ran it.
The matching attack pays off every time: spot the exact versions a target runs (the Rails 404 page that dates the framework, the X-Powered-By header, MongoDB ids you recognize by their shape), look them up in the public CVE database, replay the documented exploit. As the book puts it: "a chain is only as strong as its weakest link, and often the weakest link is the one that got the least-rigorous quality assurance" (ch. 15).
The defense (ch. 27): pin the dependency tree to exact versions, even Git SHAs, and keep watching the CVE feed.
7Defense is won before the first line of code
Treating security as an end-of-project task is the most expensive mistake in the trade. The figure Hoffman cites (ch. 18, from NIST): fixing a flaw at design time costs 30 to 60 times less than fixing it in production. The reason is mechanical: once customers are wired to a badly designed API, re-architecting it breaks their integrations.
Hence defense in depth. In his messaging example, one piece of data crosses five layers, and each layer must carry its own guard. Secure only the first, and you leave a boulevard for the bulk-send endpoint someone adds six months later, which walks straight around it.
And one golden rule, no exceptions: never reinvent cryptography. SHA-3 is twenty years of R&D and audits, free inside OpenJDK. The book's warning: "applications full of custom databases, custom cryptography, and special hardware-level optimization often are the easiest to break into" (ch. 7).
8Mitigations, not fixes
Believing a scanner is enough is the last trap. The book splits flaws into two families (ch. 19):
- the archetypes (XSS, injection, CSRF): static analyzers like Checkmarx, Bandit or Brakeman catch them well;
- the logic bugs, invisible by construction: an API that promotes whoever slips the right field into their request. No tool knows that field shouldn't be there; it takes a human who knows the business.
// ✗ mass assignment: the server copies the WHOLE received body
POST /api/profile { "name": "Alice", "isMember": true }
user.update(req.body) // isMember goes through → Alice self-promotes
// ✓ allowlist: only the permitted fields are taken
user.update({ name: req.body.name }) // isMember is ignored
On the process side, a number that stings (ch. 21): roughly 25% of vulnerabilities are regressions of bugs already closed. The direct rule: every closed security bug ships with its own regression test, no exceptions. To prioritize the rest, the three-tier CVSS score (base, temporal, environmental) puts each flaw back in your context: the same injection doesn't weigh the same in a throwaway sandbox and in a medical records system.
The book's final lucidity is in its vocabulary: the defenses are called "mitigations", not "fixes" (ch. 16), because none of them is ever final.
9What the 2nd edition (2024) adds
The second edition, out in early 2024, answers readers' most frequent request: advanced content. Hoffman announces 120 extra pages, and the table of contents confirms nine brand-new chapters, offense and defense mirrored:
- client-side attacks: prototype pollution, clickjacking pushed all the way to camera and microphone hijacking, tabnabbing;
- attacks on data and objects: mass assignment, IDOR, deserialization;
- business-logic flaws: loyalty points, credits, quasi-cash;
- step-by-step threat modeling, and a full chapter on secure configuration (Strict CSP, CORS, HSTS, COOP, Subresource Integrity).
Just one of these new chapters to set the tone, prototype pollution (client-side): in JavaScript, all objects inherit from one shared parent via __proto__. Writing into it contaminates every object in the program at once.
// the attacker sends this JSON, which a naive merge copies unfiltered
const payload = JSON.parse('{"__proto__": {"isAdmin": true}}')
merge({}, payload) // the merge copies __proto__ into the shared parent…
({}).isAdmin // → true! an EMPTY object is now admin
An if (user.isAdmin) check elsewhere in the code now passes for anyone. Zero Trust also enters the architecture chapter. The 2nd edition fills exactly what had aged in the first: if you're buying today, buy that one.
Three things I didn't know before reading it
- The book's subdomain brute-force script avoids Node's
dns.lookup: under its asynchronous looks, it relies ongetaddrinfo, which is synchronous;dns.resolveactually parallelizes. - The first person convicted for hacking in the United States is Robert Morris (1988): his worm infected some 15,000 machines in a day; the verdict, 3 years of probation and a $10,050 fine.
- Ruby on Rails' default 404 page can date a framework: three cosmetic tweaks (2012, 2013, 2017) are enough to bracket the version, and therefore its known CVEs.
My take, honestly
What won't age: the structure. Every attack in Part II has its defense chapter in Part III, and you finally understand what each protection blocks, because you've just run the attack yourself. The pedagogical bet holds too: concepts rather than tools, readable JavaScript rather than Burp screenshots. After reading it, you don't look at your own code the same way, and that's the book's real deliverable.
The first edition shows its age on precise points. SameSite, now the default CSRF defense in every browser, is absent. Automated dependency auditing (npm audit, Dependabot) too. The Twitter API in the recon chapter has been dead since 2023. And a seasoned pentester won't learn much: Hoffman himself described his 1st edition as aimed at entry- and mid-level profiles. The 2nd edition fixes a good share of those gaps, the configuration chapter first.
Why read it in 2026, when a growing share of code is written by AI agents? Precisely because of that. Models reproduce the vulnerability archetypes present in their training corpus, and nobody but you will hunt the logic bugs of your business: no scanner and no LLM knows that isMember: true has no business being in that payload. Understanding the attack means knowing how to review code, whether it comes from a junior or from an agent.
Odilon
Still relevant in 2026?
The concepts, yes: the attack archetypes in the book are still the ones OWASP catalogs, and the recon → offense → defense method doesn't expire. As for the 1st edition's dated details, the 2nd (2024) fixes most of them. What's still missing from both: the security of applications that embed LLMs (prompt injection), outside their scope.
Who is it for?
Read it if
- You build for the web and have never looked at your application through an attacker's eyes
- You apply CSP, CSRF tokens and prepared statements "because you have to", without knowing precisely what each one blocks
- You review code and want to hunt for more than style
- You're aiming for a first application security role with a developer's background
Skip it if
- You already pentest for a living: you won't learn much, and the trade's tools (Burp, sqlmap, Metasploit) are deliberately barely touched
- You want a ready-to-use tooling guide rather than concepts
- You need examples in your own language: here everything is JavaScript and Node
For going further
The web security course on this site (20 lessons, OWASP 2025) practices these very attacks in live labs, SQL injection and XSS included, and the HTTP course covers the protocol every one of these attacks rides on.
Comments (0)