Description
An identity verification portal accepts file uploads but blocks PHP files. Bypass the restriction to achieve remote code execution and read the flag.
Setup
Open the file upload portal.
Prepare a webshell and a .htaccess configuration file.
Solution
- Step 1Attempt direct PHP upload (blocked)Trying to upload shell.php is rejected by the extension filter. The server explicitly blocks .php files.
Learn more
Extension-based upload filters are a common but weak defense against malicious file uploads. The server checks the file extension against a blocklist (or allowlist) before saving the file. Blocklist approaches - blocking specific extensions like
.php,.jsp,.asp- are inherently fragile because attackers can often find alternative extensions that the server still executes.This is classified as an unrestricted file upload vulnerability (CWE-434) and appears on OWASP's list of critical web application risks. A secure file upload must validate the file's actual content (MIME type, magic bytes), not just its extension, and must never store uploaded files in a location the web server can execute.
Common bypass techniques include: uploading with alternative extensions (
.php5,.phtml,.phar), double extensions (shell.php.jpg), case variation (shell.PHP), null byte injection (shell.php%00.jpg), and - as used in this challenge - reconfiguring the server itself to execute arbitrary extensions. - Step 2Upload a .htaccess to remap .jpg as PHPCreate a .htaccess file containing `AddType application/x-httpd-php .jpg`. This Apache directive tells the server to execute .jpg files as PHP. Upload it to the same directory as future uploads.
echo 'AddType application/x-httpd-php .jpg' > .htaccessLearn more
.htaccess files are per-directory configuration files that Apache processes before serving any request from that directory. They allow directory owners to override server-wide settings without touching the main Apache configuration. The
AddTypedirective maps a MIME type to file extensions, telling Apache how to handle files with that extension.AddType application/x-httpd-php .jpginstructs Apache'smod_phphandler to execute any.jpgfile as PHP code. Once this .htaccess is in place, every.jpgfile in that directory is a potential code execution vector - regardless of whether the extension filter would have blocked it as PHP.The key insight is that the application's upload filter only checked the extension of the uploaded file. It did not restrict which configuration files could be uploaded. Servers that allow .htaccess should validate uploaded filenames against a strict allowlist (including hidden files starting with a dot) and ideally store uploads outside the web root entirely.
- Step 3Upload a PHP webshell as a .jpgCreate shell.jpg containing a simple PHP command execution payload. Upload it - the .htaccess causes Apache to execute it as PHP despite the .jpg extension.
echo '<?php echo system($_GET["cmd"]); ?>' > shell.jpgcurl 'https://<host>/uploads/shell.jpg?cmd=cat+/var/www/flag.txt'Learn more
A webshell is a script uploaded to a web server that allows the attacker to issue operating system commands through HTTP requests. The minimal one-liner
<?php echo system($_GET["cmd"]); ?>reads thecmdURL parameter and passes it to the OS viasystem(), returning the output in the HTTP response. This turns any GET request into a remote command execution interface.After uploading, the attacker browses to the file's URL with a
?cmd=query parameter. Because .htaccess remapped .jpg to PHP, Apache passes the file through the PHP interpreter, which executes the shell command. Common targets includecat /etc/passwd,id,ls /, and - in CTF scenarios - reading a flag file at a known path.Real-world defenses against this chain include: storing uploads outside the document root (unreachable by URL), disabling .htaccess processing with
AllowOverride None, stripping execution permissions from upload directories, and serving user content from a separate origin (subdomain or CDN) that cannot execute server-side code.
Flag
picoCTF{...}
.htaccess files configure Apache per-directory - uploading one that remaps file extensions turns any uploaded file into a potential webshell.