PHP Filters
Last updated
Last updated
Related Sites:
Many popular web applications are developed in PHP, along with various custom web applications built with different PHP frameworks, like Laravel or Symfony. If we identify an LFI vulnerability in PHP web applications, then we can utilize different to be able to extend our LFI exploitation, and even potentially reach remote code execution.
PHP Wrappers allow us to access different I/O streams at the application level, like standard input/output, file descriptors, and memory streams. This has a lot of uses for PHP developers. Still, as web penetration testers, we can utilize these wrappers to extend our exploitation attacks and be able to read PHP source code files or even execute system commands. This is not only beneficial with LFI attacks, but also with other web attacks like XXE, as covered in the module.
In this section, we will see how basic PHP filters are used to read PHP source code, and in the next section, we will see how different PHP wrappers can help us in gaining remote code execution through LFI vulnerabilities.
are a type of PHP wrappers, where we can pass different types of input and have it filtered by the filter we specify. To use PHP wrapper streams, we can use the php://
scheme in our string, and we can access the PHP filter wrapper with php://filter/
.
The filter
wrapper has several parameters, but the main ones we require for our attack are resource
and read
. The resource
parameter is required for filter wrappers, and with it we can specify the stream we would like to apply the filter on (e.g. a local file), while the read
parameter can apply different filters on the input resource, so we can use it to specify which filter we want to apply on our resource.
There are four different types of filters available for use, which are , , , and . You can read more about each filter on their respective link, but the filter that is useful for LFI attacks is the convert.base64-encode
filter, under Conversion Filters
.
Like the string. filters, the convert. filters perform actions similar to their names. For more information on a given filter, refer to the manual page for the corresponding function.
Use of these filters are equivalent to processing all stream data through the and functions respectively. convert.base64-encode
supports parameters given as an associative array. If line-length
is given, the base64 output will be split into chunks of line-length
characters each. If line-break-chars
is given, each chunk will be delimited by the characters given. These parameters give the same effect as using with .
The first step would be to fuzz for different available PHP pages with a tool like ffuf
or gobuster:
Tip: Unlike normal web application usage, we are not restricted to pages with HTTP response code 200, as we have local file inclusion access, so we should be scanning for all codes, including 301
, 302
and 403
pages, and we should be able to read their source code as well.
Even after reading the sources of any identified files, we can scan them for other referenced PHP files
, and then read those as well, until we are able to capture most of the web application's source or have an accurate image of what it does. It is also possible to start by reading index.php
and scanning it for more references and so on, but fuzzing for PHP files may reveal some files that may not otherwise be found that way.
In previous sections, if you tried to include any php files through LFI, you would have noticed that the included PHP file gets executed, and eventually gets rendered as a normal HTML page. For example, let's try to include the config.php
page (.php
extension appended by web application):
As we can see, we get an empty result in place of our LFI string, since the config.php
most likely only sets up the web app configuration and does not render any HTML output.
This may be useful in certain cases, like accessing local PHP pages we do not have access over (i.e. SSRF), but in most cases, we would be more interested in reading the PHP source code through LFI, as source codes tend to reveal important information about the web application. This is where the base64
php filter gets useful, as we can use it to base64 encode the php file, and then we would get the encoded source code instead of having it being executed and rendered. This is especially useful for cases where we are dealing with LFI with appended PHP extensions, because we may be restricted to including PHP files only, as discussed in the previous section.
Note: The same applies to web application languages other than PHP, as long as the vulnerable function can execute files. Otherwise, we would directly get the source code, and would not need to use extra filters/functions to read the source code. Refer to the functions table in section 1 to see which functions have which privileges.
Once we have a list of potential PHP files we want to read, we can start disclosing their sources with the base64
PHP filter. Let's try to read the source code of config.php
using the base64 filter, by specifying convert.base64-encode
for the read
parameter and config
for the resource
parameter, as follows:
Note: We intentionally left the resource file at the end of our string, as the .php
extension is automatically appended to the end of our input string, which would make the resource we specified be config.php
.
As we can see, unlike our attempt with regular LFI, using the base64 filter returned an encoded string instead of the empty result we saw earlier. We can now decode this string to get the content of the source code of config.php
, as follows:
Tip: When copying the base64 encoded string, be sure to copy the entire string or it will not fully decode. You can view the page source to ensure you copy the entire string.
We can now investigate this file for sensitive information like credentials or database keys and start identifying further references and then disclose their sources.