⚠ FOR SECURITY TESTING PURPOSES ONLY — DO NOT DEPLOY IN PRODUCTION
PHP2Shell
PHP File Upload → RCE
The upload endpoint accepts any file extension and stores it in a web-accessible directory. Upload a .php file to achieve Remote Code Execution — execute arbitrary OS commands through the browser.
> Show hints
- [1] The server checks Content-Type: image/jpeg but never validates the file extension or content
- [2] Upload a file named shell.php with Content-Type: image/jpeg — it will be saved and executed as PHP
- [3] Access the shell at /uploads/<filename>?cmd=id to run OS commands
- [4] Playwright: upload the file, follow the returned URL, assert command output in the response
- [5] Try: ?cmd=id, ?cmd=whoami, ?cmd=cat+/etc/passwd, ?cmd=ls+-la
[1] Upload a PHP Webshell
The server validates only the MIME type reported by the browser (Content-Type header), not the actual file content or extension. Upload a .php file to get a shell.
Custom payload
(any extension — server won't reject it)
[2] Execute Commands
Once uploaded, the shell is accessible at its URL. Send OS commands via the ?cmd= query parameter.
[no shells uploaded yet]
[3] Uploaded Shells
[no shells uploaded yet]
[4] Vulnerable Code
// VULNERABLE: checks Content-Type header only
const contentType = req.headers['content-type'];
if (!contentType.includes('image/')) {
return res.status(400).json({ error: 'Only images allowed' });
}
// No extension check, no magic-byte validation
fs.writeFileSync('/var/www/uploads/' + filename, fileBuffer);
// -> upload shell.php with Content-Type: image/jpeg
// -> GET /uploads/shell.php?cmd=id -> RCE