The Hacker now requires the file content to start with the image signature GIF89a and the name to end in an image extension jpg png or gif. But the Ravens’ server is misconfigured and runs any file whose name contains .php, even if it ends with an image extension.
The same upload page, but the protection is now stronger: it checks the content starts with the GIF89a image signature and the name ends in an image extension. But the server runs any name containing php, even behind an image suffix.
Upload a web shell that passes both the content and extension checks and still runs.
You bypassed the content and extension checks with a double extension and a polyglot file.
Why the solution worked
Even a signature-and-extension check is broken: a polyglot file starts with a valid image signature and carries code in the rest, and the double extension shell.php.jpg passes the suffix check while the misconfigured server runs it. Two mistakes: a check that is not enough, and a server configured to execute on a middle extension. The fix: rename the file to a random name with an extension you choose, store it outside the web root, and configure the server never to execute anything in the upload folder or to interpret double extensions.
The root cause
Signature and extension checks do not stop a polyglot that starts as an image and ends with an image name yet contains code, and the server runs any php in the name. The root is a misconfig executing based on part of the name.
How the code is fixed
An image signature does not stop a polyglot, and a double extension fools a suffix check. Rename and store where nothing executes.
Vulnerable code
if (!data.startsWith('GIF89a')) return bad(); // magic bytes
if (!/\.(jpe?g|png|gif)$/i.test(name)) return bad(); // suffix only
save('/var/www/uploads/' + name); // server runs *.php.jpg as PHP (misconfig)
Safe code
if (!isRealImage(data)) return bad(); // full decode, not just magic
const name = randomId() + '.' + safeExtFor(data); // our name, our extension
save('/srv/blobs/' + name); // outside web root, never executed
Impact in the real world
Polyglot files bypass both content and extension checks and have planted web shells in systems that believed they validated well.
How defenders detect it
Defenders store outside the web root with generated names and no executable extension, re-encode images, and forbid executing any content in the upload folder.