Skip to content

SQL Injection Vulnerability

High
DawoudIO published GHSA-h3vq-9gr6-h9r4 Dec 17, 2025

Package

No package listed

Affected versions

<=5.22.0

Patched versions

6.5.3

Description

Security Advisory: SQL Injection Vulnerability in CartToFamily.php

Date: December 06, 2025
Reporter: Guilherme Mury
Severity: High / Critical
Affected Component: /src/CartToFamily.php
Vulnerability Type: SQL Injection (CWE-89)


πŸ‘‹ Introduction

Hello ChurchCRM Team,

First of all, thank you for maintaining this project. While conducting a source code review of the application to study its security patterns, I identified a SQL Injection vulnerability in the "Add to Family" feature.

I am reporting this responsibly to ensure the security of the users relying on this software. Below is a detailed analysis of the issue, why it happens, and how to fix it using the project's existing security standards.


🚨 Vulnerability Details

The vulnerability exists in the src/CartToFamily.php file, specifically in how the PersonAddress POST parameter is handled.

Unlike other parameters in the same file which are correctly cast to integers using your InputUtils class, the PersonAddress parameter is missing the type definition. This allows an attacker to inject arbitrary SQL commands directly into the query.

πŸ” Root Cause Analysis (Comparative)

The issue is best understood by comparing two lines of code within the same file (src/CartToFamily.php):

1. The Secure Pattern (Line 18):

$iFamilyID = InputUtils::legacyFilterInput($_POST['FamilyID'], 'int');
  • Observation: Here, the developer correctly passed the 'int' flag as the second argument. This forces InputUtils to cast the input to an integer, neutralizing any malicious string characters. This is secure.

2. The Vulnerable Pattern (Line 29 - The Issue):

$iPersonAddress = InputUtils::legacyFilterInput($_POST['PersonAddress']);
  • Observation: Here, the 'int' flag is missing. The function defaults to treating the input as a string.
  • The Exploit: Because the subsequent SQL query (Line 32) does not use quotes around the variable, an attacker does not even need to "break out" using quotes. They can simply append SQL logic.

Vulnerable Query (Line 32):

$sSQL = 'SELECT * FROM person_per WHERE per_ID = ' . $iPersonAddress;

πŸ’₯ Proof of Concept (PoC)

An attacker with "Add Records" permission can exploit this vulnerability to extract sensitive data from the database (e.g., admin credentials) or bypass logic checks.

Steps to Reproduce:

  1. Log in as a user with Add Records permission.
  2. Add a person to the cart.
  3. Navigate to the "Cart to Family" page.
  4. Intercept the POST request when submitting the form.
  5. Modify the PersonAddress parameter in the body:

Payload Example (Boolean-Based):

PersonAddress=1 OR 1=1

Resulting Query Executed:

SELECT * FROM person_per WHERE per_ID = 1 OR 1=1
  • Result: The application will retrieve all user records instead of just the intended one, potentially exposing PII (Personally Identifiable Information) of the entire congregation in the subsequent logic.

Payload Example (Union-Based - Theoretical):

PersonAddress=0 UNION SELECT 1,2,3,4,usr_Password,6... FROM user_usr
  • Result: Allows extraction of data from other tables, such as admin password hashes.

πŸ›‘οΈ Remediation (The Fix)

The fix is simple and aligns with the coding style already present in the file. You simply need to enforce the integer type on the input.

Vulnerable Code:

$iPersonAddress = InputUtils::legacyFilterInput($_POST['PersonAddress']);

Patched Code:

$iPersonAddress = InputUtils::legacyFilterInput($_POST['PersonAddress'], 'int');

By adding the 'int' argument, InputUtils will ensure that $iPersonAddress is strictly a number, making the SQL Injection impossible.


🀝 Conclusion

This vulnerability appears to be an oversight where the security pattern used in line 18 was not applied to line 29. A simple one-line change will fully mitigate the risk.

Please let me know if you need further assistance or if you would like me to open a Pull Request with the fix (though I recommend handling it via a private security PR first).

Best regards,

Guilherme Mury
Security Researcher

Severity

High

CVE ID

CVE-2025-67877

Weaknesses

Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')

The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data. Learn more on MITRE.

Credits