EXERCISE 3 — Polyglots, and why encoding beats blocklists
==========================================================
WHAT A POLYGLOT PAYLOAD IS:
- A single payload string crafted to be syntactically valid -- and to
EXECUTE -- across MULTIPLE injection contexts at once (HTML body, various
attributes, inside
Whatever context it landed in -- a title, a style block, a script string,
a textarea, an attribute -- one of those closers escapes it, and the
trailing fires.
WHY AN ATTACKER PROBING AN UNKNOWN INJECTION POINT USES ONE:
- When testing an unfamiliar field, the attacker often DOESN'T KNOW which
context their input lands in (is it reflected into HTML? an attribute? a
JS string?). Trying context-specific payloads one by one is slow.
- A polyglot is a single "does ANYTHING fire?" probe: submit it once, and if
it executes, the point is injectable -- without first knowing the context.
It maximises the chance of a hit per request. (Testers/scanners use them
the same way, with a benign marker instead of alert.)
WHY CONTEXT-AWARE OUTPUT ENCODING DEFEATS ALL VARIANTS:
- Output encoding doesn't try to RECOGNISE payloads at all. It transforms
untrusted data so that, in the specific context it's emitted into, the
characters that could break out are rendered INERT:
* HTML body: < > & -> entities, so no tag (polyglot's , ,
etc.) can ever be introduced -- they show as text.
* Attribute: quotes encoded + value quoted, so no breakout.
* URL: scheme allowlist, so javascript: is rejected.
- Because EVERY breakout character for that context is neutralised, it does
not matter how the attacker spelled the payload -- case tricks, entities,
whitespace, polyglot structure -- there is simply no character left that
the parser will treat as code. The data stays data. ALL variants fail at
once, including ones nobody has invented yet.
WHY A BLOCKLIST DEFEATS NONE OF THEM RELIABLY:
- A blocklist must match specific bad PATTERNS. The browser's parsing
tolerance (Exercise 2) yields unlimited equivalent encodings, and
polyglots are explicitly engineered to slip through pattern matching by
being valid in many grammars. The attacker needs one miss; the blocklist
must catch everything. So it reliably defeats none of them.
THE PRINCIPLE:
Encoding works on the OUTPUT side and is COMPLETE for its context (a closed
set of dangerous characters with known safe transforms). Blocklisting works
on the INPUT side against an OPEN, unbounded set of attacker spellings.
Defend by making output safe-by-construction, not by guessing bad input.