Rémi Matasse (@_remsio_)

Pentester @Synacktiv


PHP filter chains: How to use it
Rémi Matasse (@_remsio_)

Local file inclusion methods in PHP evolved through time, there are 2 main objectives when exploiting them:
- Getting a remote code execution by including files containing PHP via include() or require() functions.
- Leak local files such as PHP sources or configuration files via file_get_contents() or file() functions for example.

In the past, the following requirements had to be met to exploit a local file inclusion.
To exploit a remote code execution you could inject information in log files and include them, or control a variable in your PHP session to poison the session file. But in most cases, you needed to be able to upload a file on the system.

To leak local files, it was required to either fully control the path pointing to the file to leak, or to have a path traversal to go up in the file tree. Most importantly, it was mandatory for the server to send you back its content in the response.

In both cases, the affected functions support several wrappers, the most iconic being file:// which is a prefix before a file path. Other wrappers such as php://filter can be passed on these methods and for example it was well known to allow leaking PHP sources by base64 encoding them (ex : php://filter/convert.base64-encode/resource=index.php).

In a 2021 CTF write-up by loknop , this wrapper was actually proven to be much more useful. Indeed, it allows setting the encoding of contents passing through it, and most importantly to chain an infinite number of encodings leading to the generation of arbitrary data at the start of a file. In this presentation, the full process will be explained with examples allowing, for instance, to generate interesting prefixes to a file content, such as '<?php system("id"); ?>', therefore removing the need to have a file upload when exploiting include() or require() functions to get remote code execution (if the full path is controlled).

In 2022, hash_kitten showed that it was also possible to use PHP filters chain as an error-base oracle when used in many built-in functions, such as file_get_contents(). Its method chains encodings that will make the content size of a file exponential, triggering a PHP memory_limit exhaustion. By using other filters, the first character of the file content can also be determined. By using other encodings it is also possible to rotate the chain order to retrieve characters that are located further away in the content.

Using this error-based oracle, it is therefore possible to leak the entire file content without having PHP to serve it in a server response.

Salle Europe