LFI Uncovered: Easy Tips for Beginners

Introduction

This post only covers the basics of LFI attacks and is aimed at beginners or those looking to refresh their understanding of the fundamentals. I plan to write a more advanced post in the future that dives deeper into this vulnerability. I hope you find this helpful! Feel free to check out my LFI cheat sheets and notes [here].

What Is LFI ?

LFI, or Local File Inclusion, is a vulnerability that can allow an attacker to read system files they shouldn’t have access to, often files located outside the web root. For example, on Linux servers, this might include the /etc/passwd file, or on Windows, files like C:\boot.ini.

This vulnerability typically occurs when user input isn’t properly sanitised, enabling malicious actors to manipulate file paths and access sensitive data.

How Does It Happen ?

LFI vulnerabilities are often referred to as the ‘dot dot slash‘ attack. This is because the attack usually involves using ../ in the payload.

In the command line, if you want to move up one directory level, you can use “cd ..“. To move two levels up, you can use “../..“, and so on. The same concept applies when exploiting a Local File Inclusion (LFI) vulnerability.

Example

Suppose a web application is hosted in the following directory on the server:

var/www/html/website

Inside this directory are files used to run the website:

index.html
about.html
contact-us.html
downloads.php

Let’s say you’ve found an LFI vulnerability on the index.html page and want to read the /etc/passwd file on the system. Your payload might look something like this:

../../../../etc/passwd

Since the website is hosted in the “website” directory, you need to go back four levels:

website -> html
html -> www
www -> var
var -> / (the root directory)

The reason you need to go back to the root is that /etc/passwd is located in the /etc directory at the system root. Once you’ve navigated back to the root, you can specify the file you want to read: /etc/passwd. If successful, the contents of this file will appear in the browser or be downloaded, depending on the website’s functionality.

Why Does It Happen?

Hopefully that is all making sense to you. Now we have covered the ‘how’ it happens, we will cover the ‘why’ it happens. I will go a bit deeper into the theory side of things but hang in there.

In PHP, the functions include() and require() are used to load and run code from other files. If these functions are used with user input, like a filename provided through a URL parameter, an attacker can manipulate that input to include and read sensitive files from the server.

For Example

If a website has code like include($_GET[‘page’]);, and the URL is https://example.com/index.php?page=home.php, it will include home.php. But if the input isn’t properly checked, an attacker could set page=../../../../etc/passwd, causing the server to include and display the contents of /etc/passwd. This is how Local File Inclusion (LFI) occurs, by tricking the server into including files it shouldn’t, just by controlling the input passed to include() or require().

Enumeration

So, how do we find these vulnerabilities?

Websites sometimes have functionality that allows users to download files. This is just one basic example where an LFI vulnerability might occur. For instance, a finance web application might let users download weekly reports. These reports are stored on the server, for example in:

var/www/html/website/reports

When you click the download button, the URL might look something like this:

https://example.com/downloads.php?file=report1.pdf

Notice the parameter called “file”. This parameter tells the server which file to download.

What if we tell the web application to download a different file? If the application doesn’t properly sanitise user input, we can use the ../ technique to tell the server to look somewhere else, potentially anywhere on the system.

For example, if we want to download the /etc/passwd file instead of report1.pdf, our payload might look like this:

https://example.com/downloads.php?file=../../../../etc/passwd

Note: Depending on the directory structure and how deep the files are stored, you may need to adjust the number of ../ in your payload.

It’s important to understand that if you don’t use enough ../, you might not reach the desired file because you’re not going back far enough in the directory tree. Conversely, adding too many ../ (more than needed) doesn’t harm—once you reach the root directory /, further ../ do nothing, since you’re already at the top of the filesystem hierarchy.

In practice, it’s often better to include more ../ than you think necessary. Sometimes, you won’t know exactly how deep the web app is nested within the directory structure. For example, if the web app is hosted at:

/var/www/html/nginx/test/alternative-app/client1/website

Using only four ../ might not be enough to reach /etc/passwd. But if you include, say, 30 ../, you’re more likely to successfully reach and retrieve the file.

LFI Example

A great example which demonstrates this vulnerability well is the Proving Grounds Practice Box “Inclusiveness”. On this web application were two links for English language and Spanish language. When either of these links were clicked, a parameter appeared in the URL of “?lang=“. This parameter was vulnerable to LFI and I was able to read the /etc/passwd file using the techniques we discussed. Screenshots displaying this can be seen below.

Bypass Techniques

In the real world, you’re unlikely to find applications that don’t sanitise input at all, allowing you to simply use ../ characters. Unfortunately, I’ve seen cases where this is true, but most applications will be a bit trickier to exploit. That’s where bypass techniques come in handy.

A basic example of bypassing security measures is using encoding. Some Web Application Firewalls (WAFs) will trigger alerts when they see ../ characters. URL encoding these characters can help bypass these defences. For example:

%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e/etc/passwd

You can even double-encode it:

%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e/etc/passwd

Another bypass method involves using a double payload, where you use four dots and two slashes instead of two dots and one slash. Some security measures might detect and block ../, but if you double it, the server may remove those characters (seen in red below) leaving you with a working payload. For example:

....//....//....//....//....//....//

The server might interpret this as:

../../../../../../

This way, even if the ../ pattern is detected and removed, the extra dots can still carry you past the security.

Exploitation

Now that we’ve covered some bypass techniques, let’s look deeper into what you can do with this vulnerability.

Reading /etc/passwd is useful as proof of concept because it reveals important system information. However, that alone often doesn’t lead to further access. To increase your chances of gaining a foothold, you should try to enumerate as much as possible.

It’s also important to note that with this vulnerability, you generally cannot list available files directly. You need to know the specific paths of files you want to read, as you can’t perform directory listing.

One effective way to gain a foothold is to try and read your target user’s private SSH key, typically located at:

/home/<username>/.ssh/id_rsa

If you already read /etc/passwd, you know the username to put into the above payload. If you can retrieve the SSH key, you can potentially use it to log into the system via SSH without a password.

Another approach is to look for files that may contain credentials, such as the wp-config.php file in WordPress installations. File structures are often available online, so researching the specific CMS or web application can help you identify where sensitive data might be stored.

Depending on the infrastructure and configuration, you may find other files containing login details or secrets. The best way to prepare is to research the specific software or framework the target uses — sometimes, open-source projects have publicly available repositories that reveal their directory structures.

Conclusion

Local File Inclusion (LFI) is a vulnerability that allows an attacker to read sensitive system files that they normally shouldn’t have access to. In most cases, this is a critical security flaw. It can be effectively mitigated by sanitising user input throughout the entire application, ensuring that characters like ../ are properly handled so the server doesn’t interpret or execute malicious path traversal.

Personally, I find LFI to be one of my favourite exploits. It often requires a bit of creativity to bypass active protections, and it feels a bit like going on a treasure hunt. Patience is key—you want to spend time exploring files that may contain valuable information, such as credentials or configuration details.

This post only covers the basics of LFI attacks and is aimed at beginners or those looking to refresh their understanding of the fundamentals. I plan to write a more advanced post in the future that dives deeper into this vulnerability. I hope you found this helpful! Feel free to check out my LFI cheatsheets and notes [here].

Boxes To Practice On

Proving Grounds

  • Solstice – A beginner friendly box, great for starting out, with LFI as the foothold.

  • Ha-Natraj – A play machine where you exploit LFI combined with a poisoning attack in the Apache logs.

  • Bottleup – An LFI challenge that requires  bypass techniques discussed in this blog post.

  • Slort – LFI and RFI attacks 

  • Inclusiveness – Practice machine with an LFI vulnerability (seen in screenshots above).

HackTheBox

  • Beep – A retired HTB machine that centers on exploiting Local File Inclusion (LFI), eventually escalating to Remote Code Execution via log poisoning.

  • Included – Contains a vulnerable PHP application where LFI combined with directory traversal can lead to deeper system compromise.

  • HTB Academy: File Inclusion Module – Offers structured lessons on LFI, covering everything from basic inclusion to more complex exploitation methods.

TryHackMe

  • File Inclusion Room – A practical learning environment that explores both LFI and Remote File Inclusion (RFI). It guides users through common techniques like directory traversal (../), null byte (%00) exploitation, and the use of PHP stream wrappers.

References