Skip to content
The library

Notes on a book

Hunting Security Bugs

Tom Gallagher, Bryan Jeffries, and Lawrence Landauer · Microsoft Press, 2006

A security testing manual from inside Microsoft, written for testers rather than researchers. Twenty years old, and still the most complete account anywhere of how a parser can be tricked into disagreeing with the check in front of it.

This is a testing book, not a hacking book, and the difference shows on every page: it assumes you have the source, the build and a mandate, and it is organised around finding every instance of a bug class rather than exploiting one. That makes it exhaustive where modern books are selective, which is exactly what you want from a reference.

It is also from 2006, and some of it reads that way - ActiveX controls, Internet Explorer zone policy, COM object safety. Skip those. What survives is the material on parsers, encodings and memory, none of which has changed at all, and the enumerative habit of mind that produced it.

Why it is on this shelf

Because it is the book that takes seriously the idea that a security check and the thing it protects can disagree about what the input says. That disagreement is the mechanism behind path traversal, filter bypass, request smuggling, SQL injection through a sanitiser, and half the web challenges you will ever see, and nobody else devotes a chapter to it.

Chapter 8, Buffer Overflows and Stack and Heap Manipulation

The memory chapter, written for people who have to find overflows in a large codebase rather than exploit one in a competition. It covers stack and heap layout, the arithmetic mistakes that produce an undersized allocation, and the API calls that were the usual culprits.

Its value now is the taxonomy of causes rather than the exploitation. Most overflow challenges are one of a handful of shapes - an off-by-one on a boundary, a signed length compared against an unsigned buffer size, a loop that trusts a terminator that is not there - and this chapter enumerates them. Once you can name the cause, stack overflow to shell and the buffer overflow offset and cyclic pattern tools take it from there. Integer bugs and type confusion covers the arithmetic half in detail.

Chapter 9, Format String Attacks

Short, complete, and one of the few treatments that explains the bug from the callee's side. A format string is a small program interpreted by the formatting function, and the arguments it reads are whatever is next on the stack. If an attacker supplies the program, the attacker chooses how many arguments get read and what happens to them.

The two consequences it draws are the two that matter: percent-x and percent-s turn the bug into an arbitrary read of the stack and of memory it points to, and percent-n turns it into an arbitrary write. That second one is why format strings are treated as full compromise rather than an information leak. Format string exploitation and the format string exploit tool do the arithmetic for you once you have found the offset.

Chapter 10, HTML Scripting Attacks

Cross-site scripting from the era in which it was still being worked out, which is why it is more careful about context than most modern accounts. The chapter's spine is the list of ways programmers try to prevent scripting attacks and what each attempt misses: blocking script tags, stripping angle brackets, escaping quotes, filtering keywords.

That is the useful framing for a challenge, because a CTF XSS is nearly always a filter you have to defeat rather than a field with no filter at all. Each defence in the chapter has a named bypass, and the bypasses come from the same place they do today - the browser's parser is more permissive than the filter's model of it. XSS in CTF is the current version; read this chapter for the discipline of enumerating the defence before the payload.

Chapter 12, Canonicalization Issues

The best chapter in the book, and the reason it is cited here at all. Canonicalization is turning data into its simplest form, and the bug is making a security decision on a form that is not the canonical one. Their example is that Bryan can also be written BrYaN, or Br%79an, or with Latin characters that render identically.

The file-path list they print is the one to internalise, because every item in it is a real bypass somebody shipped:

  • Forward and backward slashes, treated as equivalent by the filesystem and not by the check.
  • Extended path syntax and file: URLs reaching the same object by a different name.
  • Environment variables that expand after validation.
  • UNC and loopback administrative shares naming a local path as a remote one.
  • Dot and dot-dot segments, so that /somedir/../secret is compared against somedir and resolves to secret.

Their worked example is the 2005 ASP.NET bulletin, where a backslash instead of a forward slash walked straight past the authorisation check on a protected directory. That is the whole class in one line, and it is still how path traversal and LFI challenges are built: the decision and the resolution disagree.

Chapter 16, SQL Injection

Testing-oriented rather than exploitation-oriented: how to find every injectable parameter in an application, including the ones not in the request - stored values, headers, second-order paths through a batch job. That breadth is its contribution, since most treatments assume you already know which parameter is interesting.

The detection material is timeless because it is about behaviour rather than payload syntax: a single quote that changes the response, an expression that evaluates, a boolean that flips a page's content. Once detected, SQL injection in CTF is the faster route to extraction.

Where it stops

It is a 2006 Windows book. Whole chapters concern technologies that no longer exist, the tooling is gone, and there is nothing on modern web frameworks, JSON APIs, mobile or cloud. If you read it front to back you will waste a third of your time.

It also assumes white-box access throughout. The advice to read the code first is good advice and not always available to you.

What to take into a challenge

Enumerate the defence, not the payload. When a filter blocks you, the productive question is what rule the author wrote, not which payload from a list might slip through. Every bypass in this book is derived from a model of the check - it compares before decoding, it looks at the first slash, it stops at the null byte - and a bypass you derived is one you can repeat on the next challenge.