PHP Filter Wrapper (Source Disclosure)
Full command arsenal in the cheatsheetphp://filter is one of PHP's stream wrappers: a "pipe" that applies transformation filters to a resource before delivering it. Its classic abuse turns a file inclusion or read primitive (LFI, XXE) into theft of the application's source code.
The problem it solves for the attacker. If you directly request a .php file through an LFI or XXE, the server executes it and you only see its output (often empty), not its code. The secrets live in the code: database credentials, API keys, authentication logic. To see them you need the source text, not the result of running it.
The technique. You wrap the resource with the convert.base64-encode filter, which encodes the file's content in Base64 before inclusion. Since the result is Base64 text (not valid PHP code), the engine doesn't execute it: it returns it as-is, and decoding it reveals the full source:
php://filter/read=convert.base64-encode/resource=/var/www/html/db.phpecho -ne '<received base64>' | base64 -d # -> db.php source codeWhy Base64. Without the filter, including db.php would execute it; with convert.base64-encode, PHP processes the file through the filter stream and emits Base64, which survives inclusion intact. Other chainable filters enable more advanced things (the filter chains technique can even generate arbitrary content for RCE), but the common case is source exfiltration.
From LFI to RCE with filter chains. When there are no data:///input wrappers, an iconv filter chain builds arbitrary PHP byte by byte using only php://filter, turning a read-only LFI into RCE:
python3 php_filter_chain_generator.py --chain '<?php system($_GET["cmd"]); ?>'
# paste the resulting php://filter/... chain into the vulnerable parameter and add &cmd=id
curl 'http://<ip>/index.php?page=php://filter/convert.iconv.../resource=php://temp&cmd=id'Where it applies. Any point that includes or reads a controllable path: ?page=, ?file= parameters, and also inside an XXE as the external entity's resource, exactly as in BountyHunter to extract db.php.
How to detect it. The access-log signature is the wrapper itself in a parameter: php://filter/, convert.base64-encode, resource= or, in the RCE variant, the long iconv/convert.iconv.* filter chain (filter chains produce huge, very recognisable URLs). A WAF inspecting parameters for php:// and base64-encode blocks them. A spike of large Base64 responses from ?page=/?file=-style endpoints suggests source exfiltration. Inside an XXE, the same chain appears as the external entity's resource in the XML body.
Defence. Don't pass user input to file inclusion/read functions; if unavoidable, use path allowlists and disable dangerous wrappers (allow_url_include=Off, restrict php://). And, fundamentally, don't embed secrets in web-accessible code.
Machines where it's used
- BountyHunterHackTheBox
- Hacker Kid 1.0.1VulnHub
- Symfonos 5VulnHub