Introduction

None

File Inclusion vulnerabilities are among the most common and impactful issues in web applications. In this walkthrough, we will solve a practical challenge from the hackviser platform, focusing on Local File Inclusion (LFI) and how it can be leveraged to extract sensitive information.

Understanding the Problem

The challenge is straightforward on the surface:

Question: What is the database password in the "config.php" file?

None

This lab on Hackviser Labs helped me understand how dangerous improper file handling can be in web applications. If you are new to web penetration testing or practicing on Hackviser platform, this write-up will explain every step in a clear and easy-to-follow way.

Step 1: Analyzing the Web Application

I began by exploring the provided web application in the browser. The application appeared to be a simple HealthMate page with basic functionality.

While navigating through the application, I noticed an interesting feature: an attachment labeled "guide". When clicked, it opened a new page with the following URL structure:

http://healthmateapp.hv/index.php?page=guide.php

This immediately caught my attention. The application was using a page parameter in the URL to decide which file to load and display. In web development, this pattern is very common — developers often use something like include($_GET['page']) or similar functions in PHP to dynamically load content.

However, when user input directly controls which file gets included without proper validation, it opens the door to Local File Inclusion (LFI) attacks.

To make testing more controlled and efficient, I intercepted the request using Burp Suite and sent it to the Repeater tool. This allowed me to modify the "page" parameter and observe how the server responded to different inputs.

Step 2: Identifying the Vulnerability

Since the goal was to read the config.php file (which likely contained database credentials), I started with simple payloads.

I first tried:

?page=config.php

The server returned a 200 OK status code, which was promising. However, the response body was completely empty. This is a classic sign that the file was being included, but because it was a .php file, the server executed the PHP code instead of showing its source. The database password never appeared because the code ran on the server side and only its output (if any) was sent back.

Next, I tried the classic path traversal technique to move up directories:

  • ?page=../config.php
  • ?page=../../../../config.php
  • And many variations with more ../ sequences

These attempts also did not work as expected. The application seemed to have some restrictions or the file was not located in the expected directory relative to the current script.

Step 3: Using an Advanced Payload to Extract Source Code

After several failed attempts and testing different bypass methods, I recalled a powerful technique that works well against LFI when you need to read PHP source code instead of executing it.

I used the following payload:

?page=php://filter/convert.base64-encode/resource=config.php

This payload uses PHP's stream wrapper functionality, specifically the php://filter wrapper.

Simple Explanation of the Payload

The payload works as follows:

  • The php://filter is a built-in PHP stream wrapper. It allows you to apply filters to data as it is being read or written.
  • convert.base64-encode tells PHP to encode the entire file content into Base64 format before including it.
  • resource=config.php specifies which file we want to read.

Why does this work?

Normally, when the application does something like:

include($_GET['page']);

It treats the value of page as a filename and includes it. If the file ends with .php, PHP executes the code inside it.

By using the filter wrapper, we instruct PHP to:

  1. Read the raw content of config.php as plain text (without executing it).
  2. Apply Base64 encoding to that content.
  3. Return the encoded result to the browser.

This clever trick bypasses the execution behavior and gives us the actual source code of the configuration file.

Step 4: Analyzing the Response

After sending the payload, the server returned a long Base64-encoded string:

None

Since the output was Base64 encoded, I decoded it using an online decoder or Burp Suite's decoder tool.

After decoding, I obtained the actual PHP source code of config.php. This file contained database configuration details, including the username and password.

<?php
    try{
        $host = 'localhost';
        $db_name = 'hv_database';
        $charset = 'utf8';
        $username = 'root';
        $password = '6-----------A';
        
        $db = new PDO("mysql:host=$host;dbname=$db_name;charset=$charset",$username,$password);
    } catch(PDOException $e){
        
    }
?>

This successfully solved the lab, This was exactly what the Hackviser question asked for. I submitted it and successfully completed the lab.

Understanding Why This Attack Works

To fully understand this vulnerability, let's break down what is happening internally.

If the application contains code like:

include($_GET['page']);

Then when we pass the payload:

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

PHP interprets it as:

include("php://filter/convert.base64-encode/resource=config.php");

Instead of executing config.php, PHP applies the filter and outputs the encoded content.

Since config.php is used for configuration so it does not print output, nothing is displayed.

This attack works when:

  • The application directly includes user-controlled input
  • No proper validation or sanitization is applied
  • PHP stream wrappers are enabled

This is a classic example of how insecure coding practices can expose sensitive backend data.

How to Prevent File Inclusion Vulnerabilities

Preventing LFI vulnerabilities is critical for securing web applications. The most important rule is to never trust user input when including files.

A secure approach is to use a whitelist of allowed pages:

$allowed_pages = ['home.php', 'guide.php', 'about.php'];

$page = $_GET['page'] ?? 'home.php';

if (in_array($page, $allowed_pages)) {
    include("pages/" . $page);
} else {
    include("pages/home.php");
}
  • Avoid using functions like include(), require(), include_once(), or require_once() with unsanitized user input.
  • Consider using absolute paths or predefined templates instead of dynamic file loading.
  • Disable unnecessary PHP stream wrappers if possible in your server configuration.

Conclusion

This Hackviser Labs challenge was a great way to practice Local File Inclusion (LFI) exploitation, especially the use of PHP filters for reading source code. It shows how a seemingly innocent feature (loading pages dynamically) can lead to serious information disclosure if not handled carefully.

If you are learning web security, I highly recommend trying the File Inclusion (LFI/RFI) labs on the Hackviser platform. They provide hands-on practice in a safe environment and help build strong foundational skills.

Have you solved this challenge on Hackviser? Feel free to share your approach or any other bypass techniques you discovered in the comments.

Happy Hacking