Magic Numbers (File Signatures)

Magic numbers — more precisely, file signatures — are the fixed byte sequences at (or near) the start of a file that identify its format. Plain text files have no magic number; binary formats usually do, typically in the first 2–8 bytes. The Unix file(1) utility and its libmagic database are the canonical implementation of signature-based identification; Wikipedia’s list of file signatures is the standard community reference.

Well-known examples:

Signature (hex)ASCIIFormat
FF D8 FFÿØÿJPEG image
89 50 4E 47 0D 0A 1A 0A‰PNG␍␊␚␊PNG image
47 49 46 38 37/39 61GIF87a / GIF89aGIF image
25 50 44 46 2D%PDF-PDF document
50 4B 03 04PK␃␄ZIP archive (also docx/xlsx/jar/apk)
7F 45 4C 46␡ELFELF executable
4D 5AMZDOS/PE executable
1F 8Bgzip compressed data

Offensive use: bypassing upload filters

Many web applications validate uploads by checking the magic number rather than parsing the file. Because text files carry no signature, a script payload can be prepended with a few ASCII characters and then patched in a hex editor to match a trusted format’s signature — for example, starting a PHP file with GIF8 and editing it to 47 49 46 38 (GIF8). The file utility will then report the polyglot as an image.

PHP is unusually forgiving here: the interpreter only executes content inside <?php ... ?> tags and passes everything else through verbatim, so a valid image header can coexist with executable code in one file. Most other languages lack this “interpreted vs. non-interpreted region” split — a stray signature at byte 0 breaks the parser. For those, the fallback is to intercept the upload request (e.g. with Burp) and strip the extra bytes after the filter has seen them, lest the delivered reverse shell be unexecutable.

Workflow:

  1. Insert four ASCII placeholder characters at the front of the payload.
  2. Open the file in a hex editor (e.g. hexeditor, xxd with -r for reverse patching) and overwrite the placeholders with the target magic number.
  3. Run file payload.php to confirm the signature is now detected as the spoofed type.

Defensive notes

  • Signature checks are a hint, not validation. Content-type verification should parse the actual format structure (image decoders, archive walkers) and re-encode where possible.
  • file/libmagic results should never be the sole gate for executable-content decisions.

Related: xss-attacks (polyglot payloads), xxd (hex editing on the command line).

Sources

See also

  • xxd
  • xss-attacks
  • zip-bomb — the archive-side cousin: crafted files that abuse parsers rather than spoof formats