Analyzing CVE-2018-6376 - Joomla!, Second Order SQL Injection

Prefix

While there are lots of security bugs disclosed each week, for us pentesters, some are more special than others. Very recently, a Second Order SQL Injection was reported in Joomla! and a good analysis can be found here: https://blog.ripstech.com/2018/joomla-privilege-escalation-via-sql-injection/

 In this blog post Savan Gadhiya and Amish Patadiya will try to help us understand and discover Second Order SQL Injection methodology and exploitation techniques. The blog also shows how SQLmap can be used to exploit a Second Order SQL Injection (i.e. do NOT reinvent the wheel).

What is Second Order SQL Injection

In a Second Order SQL injection, the application stores user provided information before executing them. A user will not get any error (or SQLi indication) in the response of that page (on which the input is being fuzzed). Later, when a user access another page or functionality, where the stored information will be used to construct a new SQL query which will execute the previously injected payload, this is what is called a Second Order SQL injection.

More information: https://portswigger.net/kb/issues/00100210_sql-injection-second-order

This sounds a little bit confusing, right? Let's make this simple by taking an example of a second order SQL injection in the Joomla! framework [CVE-2018-6376]

Details

Affected Joomla! Version: <= 3.8.3 and >= 3.7.0

Environment for exploitation: A user with lower privilege (user role ‘Manager’) can escalate their privilege to a higher user role (user role ‘Administrator’ or ‘Super Administrator’).

Injection Detection

Now, we set up a Joomla! Framework as required to test above described scenario. Here, we have set up a vulnerable Joomla! instance (version 3.8.3) as shown in figure below:

Joomla! version 3.8.3 Joomla! version 3.8.3

We have created user 'amish' which has 'Super Users' privileges and another user 'savan' with 'Manager' privileges as shown below:

create a manager level user Create a Manager Level User

Our goal is to escalate privilege from ‘Manager’ role to ‘Super Administrator’ role. So, lets login with the user 'savan'. Below figure show the dashboard for user 'savan' and it also shows that 'Super User' user is also logged in at the same time:

savan user logged in alongside super admin Savan User Logged-in Alongside Super User

As explained in the referenced blog, the affected instance is in the profile update page. Below figure shows the profile update page for user 'savan':

profile update page Profile Update Page

Let’s intercept the profile update request in BURP Suite HTTP proxy tool. As shown in figure below, the POST request with multipart-form data goes on the following resource:

http://<IP/domain>/joomla/administrator/index.php?option=com_admin&view=profile&layout=edit&id=645

Request Intercepted In BurpSuite Request Intercepted In BurpSuite

The affected parameter is 'forms[params][admin_style]' and that is highlighted in figure below. Let’s insert following payload (highlighted in red font) to the affected parameter as shown in Figure below:

PAYLOAD: ' (single quote)

Test SQLi Using Single-Quote Test SQLi Using Single-Quote

On successfully submission of this request, the profile update page shows informational message 'Item saved' as shown in figure below:

Items Saved Message Items Saved Message

This does not disclose any error message as this page does not use the injected payload to structure the SQL query and execute that. Let’s access the following URL on which the SQL query gets constructed with the injected payload and is executed as shown in figure below:

http://<IP/domain>/joomla/administrator/index.php

SQL Error on Other Page SQL Error on Other Page

Let’s confirm from the source code that the insertion point of payload is not vulnerable to SQL injection. Below figure shows snippet code of file ‘~/administrator/components/com_admin/controllers/profile.php’ which highlights route for ‘Edit profile’ feature:

Edit Profile Function Edit Profile Function

When a user updates profile details, the application retrieves all parameters and returns JForm object as shown in figure below:

Obtain Data From Form Obtain Data From Form

Below figure shows that the application stores retrieved user information to the database:

Save Data Save Data

As we have confirmed that user inputs are not being used to construct SQL query and hence the payload insertion instance is not vulnerable, let’s try to exploit it on affected page. As shown in figure below, let’s insert following string as a payload to check how our payload is being used to constructed SQL query:

PAYLOAD: test

Insert Test Payload Insert Test Payload

Now let’s, check the error message on affected dashboard page. As highlighted in figure below, we got only first character of the payload in error message.

SQL Error SQL Error

To try further, we injected another payload 'AND sleep(5);--' and refreshed the dashboard page. As shown in figure below, we got only first character ‘A’ reflected in the error message again:

Sleep Payload Sleep Payload

If we check the  database to verify that how user supplied input gets stored in the database. As shown in figure below, the database has the full payload which we injected:

Full Payload Present In Database Full Payload Present In Database

As we confirmed that the payload got stored properly, let’s verify the affected code to check how it constructs the SQL query. The affected instance is from the 'administrator/templates/hathor/postinstall/hathormessage.php' file. As shown in figure below, code in 40th line number stores user provided value from 'admin_style' parameter to 'adminstyle' variable. Now, the code in 47th line number consumes the user supplied input directly to construct SQL query. But wait, here it treats that value as an array. So, index 0 of stored value will be consumed to construct a query. Here we got the answer that why only first character of payload was reflecting.

Vulnerable Code Vulnerable Code

Now, we know that the payload is being treated as an array and index 0 will be consumed in SQL query. So, let’s try to provide an array '["test1","test2","test3"]' as a payload. Then, we were expecting the 0th index of the array i.e. ("test1") to be consumed to structure the SQL query. But as shown in figure below, the application reflected "[" in the error message which means that the entire payload was again treated as a string.

Array Also Treated As String Array Also Treated As String

Oops. So, what next? Is it not an exploitable instance of SQL injection?

 

Nope. We came up with an idea to change the parameter name and provide the 0th index of an array ‘admin_style’. As shown in figure below, we changed the parameter name with ‘jform[params][admin_style][0]’ and injected the same payload to 0th index of ‘admin_style’:

PAYLOAD: AND sleep(5);--

Sent First Parameter of Array Sent First Parameter of Array

Now, the application reflected our full payload. Though, the payload did not worked.

Full Payload Reflected Full Payload Reflected

Again, We injected following payload to extract database name and the application responded with database name ‘joomla’ as shown in figure below:

Payload: extractvalue(0x0a,concat(0x0a,(select database())))

Database Name Extracted Database Name Extracted

Hurray!!! We successfully exploited this. Now let’s fulfill our goal to access the application with  Super Administrator privileges. The following payload will give us the session id of an Super Administrator user ‘amish’ as highlighted in figure below:

Payload: extractvalue(0x0a,concat(0x0a,(select * from joomla_session where username='amish')))

Extracting SessionId of Super Admin User Extracting SessionId of Super Admin User

Yeah…. Now we can use this session id to impersonate the Super Administrator user.

Automation of Exploitation

Now, when it comes to a real penetration test we need to extract information as well. If we try to do that manually it will kill so much time. So how to automate that?

There is a solution for that. SQLMap tool provides a switch ‘--second-order’ which requires payload reflection URL as an input and it will work.

Note/Limitation: As this is the second order SQL injection, we can not automate with multiple threads to check output of each query.

If we directly provide that instance to SQLMap tool, that may not work. To work this process we need to build a query in which Sqlmap can inject its payload and can fetch the data smoothly. We constructed following payload to supply as the value of the parameter ‘jform[params][admin_style][0]’ in the request and parsed that request with the SQLMap tool switch ‘-r’ as shown in figure below;

PAYLOAD: extractvalue(0x0a,concat(0x0a,(select @@version where 1=1 *)))

Preparing request for SQLMap Preparing request for SQLMap

Here, ‘*’ in the payload will work as a marker for SQLMap tool to inject the payloads such as:

  • extractvalue(0x0a,concat(0x0a,(select @@version where 1=1 AND 5231=5231)))
  • extractvalue(0x0a,concat(0x0a,(select @@version where 1=1 AND 5231=1623)))
  • extractvalue(0x0a,concat(0x0a,(select @@version where 1=1 OR 7231=7231)))
  • extractvalue(0x0a,concat(0x0a,(select @@version where 1=1 order by 1 --)))
  • extractvalue(0x0a,concat(0x0a,(select @@version where 1=1 union all select NULL,NULL,NULL,'21231231232')))

As shown in figure below, SQLMap now detects the injection and extracts all database names with following command:

sqlmap -r 1.txt --dbms MySQL --second-order "http://<IP/domain>/joomla/administrator/index.php" -D "joomla" --dbs

Data Extraction via SQLMap Data Extraction via SQLMap

Using Sqlmap tool we can now extract further data easily.

Remediation

To mitigate this SQL Injection attack, upgrade Joomla! framework to version 3.8.5 (latest version available at the time of writing this blog). We observed that Joomla! patched this instance with snippet code as highlighted in figure below:

Official Fix For The Bug Official Fix For The Bug

If you have any questions please post below. We shall try our best to answer them.

Marketing

For more such vulnerabilities and exploits, check out our Advance Web Hacking training at Advanced web hacking