Joomla! Core Remote Privilege Escalation Vulnerability (CVE-2016-9838)

2016-12-15T00:00:00
ID SSV:92574
Type seebug
Reporter Root
Modified 2016-12-15T00:00:00

Description

Author: p0wd3r (know Chong Yu 404 security lab)

Date: 2016-12-21

0x00 vulnerability overview

1. Vulnerability description

Joomla to 12, on 13, released 3. 6. 5 of the upgrade announcement, the upgrade fixes three security vulnerabilities, wherein the CVE-2016-9838 been officially designated as high risk. According to the official Description, This is a privilege elevation vulnerability, exploit the vulnerability an attacker can change the existing user's user information, including user name, password, email and permissions group. After analysis and testing, the successful achievement of a level of user rights breakthrough, but did not achieve the vertical elevation of privileges for the administrator.

2. Vulnerability

Trigger the vulnerability prerequisites:

  1. Website open registration function
  2. The attacker knows you want to attack the user's id instead of user name

A successful attack after the attacker can change the existing user's user information, including user name, password, email and permissions group.

3. Impact version

1.6.0 - 3.6.4

0x01 vulnerability reproduction

1. Environment to build

docker-compose. yml:

`` version: '2'

services: db: image: mysql environment: - MYSQL_ROOT_PASSWORD=hellojm - MYSQL_DATABASE=jm

app: image: joomla:3.6.3 depends_on: - db links: - db ports: - "127.0.0.1:8080:80" ``

Then in the docker-compose. yml the directory where the executing docker-compose up, access to the backstage open the registry and then configure the SMTP.

2. Vulnerability analysis

The official did not give a specific analysis, only to give a description:

Alt text

The translation here is:

Table single validation failure is stored to the session of the unfiltered data not used correctly can lead to an existing user account to modify, including to reset their user name, password, and user group assignment.

Because there is no specific details, so we start from a patch start, wherein the file change caught my attention:

<https://github.com/joomla/joomla-cms/commit/435a2226118a4e83ecaf33431ec05f39c640c744>

Alt text

You can see where$tempis session data, the file and associated with the user, so it is likely that the vulnerability point.

We the following through this two step analysis:

  1. Looking for input points
  2. Carding processing logic

1. Looking for input points

We look for this session came from:

Alt text

In components/com_users/controllers/registration.phpset in components/com_users/models/registration.php. We see components/com_users/controllers/registration.phpin the 108-204 line of the registerfunction:

``php public function register() { ...

$data = $model-&gt;validate($form, $requestData);

// Check for validation errors.
if ($data === false)
{
...

 // Save the data in the session.
 $app-&gt;setUserState('com_users. registration. data', $requestData);

...
}

// Attempt to save the data.
$return = $model-&gt;register($data);

// Check for errors.
if ($return === false)
{
 // Save the data in the session.
 $app-&gt;setUserState('com_users. registration. data', $data);

 ... 
}

...

} ``

This two set at the session are generated in the error after the line, and the vulnerability DESCRIPTION is consistent, and$requestDatais our original request data, and is not filtered, so the basic can be put here as our input points.

We verify, first just register an user, and then re-register the same user and open the dynamic debug:

Alt text

Since this user registered before, so the validation error, so the request is to write data into the session.

Take the session somewhere in components/com_users/models/registration.phpthe getDatafunction, the function in access the registration page will be called once we are in then you can see the session value:

Alt text

Since the stored request data, so we can also construct the request to the session to write some additional variables.

2. Carding processing logic

The input point is found, let's look at our input data where to be used. We see components/com_users/models/registration.phpthe registerfunction:

``php public function register($temp) { $params = JComponentHelper::getParams('com_users');

// Initialise the table with JUser.
$user = new JUser;
$data = (array) $this-&gt;getData();

// Merge in the registration data.
foreach ($temp as $k =&gt; $v)
{
 $data[$k] = $v;
}

// Prepare the data for the user object.
$data['email'] = JStringPunycode::emailToPunycode($data['email1']);
$data['password'] = $data['password1'];
$useractivation = $params-&gt;get('useractivation');
$sendpassword = $params-&gt;get('sendpassword', 1);

...

// Bind the data.
if (!$ user-&gt;bind($data))
{
 $this-&gt;setError(JText::sprintf('COM_USERS_REGISTRATION_BIND_FAILED', $user-&gt;getError()));

 return false;
}

// Load the users plugin group.
JPluginHelper::importPlugin('user');

// Store the data.
if (!$ user-&gt;save())
{
 $this-&gt;setError(JText::sprintf('COM_USERS_REGISTRATION_SAVE_FAILED', $user-&gt;getError()));

 return false;
}

...

} ``

Here call the getDatafunction, and then use the request data to the$dataassignment, and then use$datato the user data changes.

The first follow-up$user-&gt;bind($data), in libraries/joomla/user/user.phpin No. 595-693 lines:

``php public function bind(&$array) { ...

// Bind the array
if (!$ this-&gt;setProperties($array))
{
$this-&gt;setError(JText::_('JLIB_USER_ERROR_BIND_ARRAY'));

 return false;
}

// Make sure its an integer
$this-&gt;id = (int) $this-&gt;id;

return true;

} ``

Here according to our incoming data to the object attribute assignment, setPropertiesand no assignment restrictions.

Next we look at$user-&gt;save($data), in libraries/joomla/user/user.phpin the first 706-818 line:

``php public function save($updateOnly = false) { // Create the user table object $table = $this->getTable(); $this->params = (string) $this->_params; $table->bind($this->getProperties());

...

if (!$ table-&gt;check())
{
$this-&gt;setError($table-&gt;getError());

 return false;
}

...

// Store the user data in the database
$result = $table-&gt;store();

...

} ``

The specific content is the$userattribute is bound to the$tableand$tableis checked, there is only filtering special symbols and a repeated username and email, if the check is passed, the data stored in the database, the stored data function in the libraries/joomla/table/user.phpin:

php /** * Method to store a row in the database from the JTable instance properties. * * If a primary key value is set the row with that primary key value will be updated with the instance property values. * If no primary key value is set a new row will be inserted into the database with the properties from the JTable instance. * * @param boolean $updateNulls True to update fields even if they are null. * * @return boolean True on success. * * @since 11.1 */ public function store($updateNulls = false)

If the primary key exists then update, the primary key does not exist it is inserted.

The whole process looked down, I found a problem:

If$datahas idthis attribute and its value is an existing user id, since in the bindand saveand not for the attribute filter, then the final saved data will with id the primary key, which becomes the update operation, that is, by our request of data to update an existing user.

The actual operation of what we previously registered a name for the victim user, the database id is 57: the

Alt text

And then we with the same username then initiate a request, then intercept the package, add a value of 57 named jform[id]attribute:

Alt text

After the release due to duplicate registry which the error occurred, the program would then request data recorded to the session:

Alt text

Next we send a new registration request, the user name of the mailbox are not previously registered, in the savefunction at the following breakpoints:

Alt text

id is written into the$user. Then release the request to the database to see the results:

Alt text

Before the victim has to be a new user attacker replaced.

The entire attack process is summarized as follows:

  1. Registered user A
  2. Repeated registration of the user A, The request packet Plus The want to attack the user C's id
  3. Registered User B
  4. User B replaces the user C

Above the the demo A and C are the same user

Note that we can not directly send an id request to update the user, such request will be in the validatefunction is filtered out, in components/com_users/controllers/registration.phpthe registerfunction:

``php public function register() { ...

$data = $model-&gt;validate($form, $requestData);

// Check for validation errors.
if ($data === false)
{
...

 // Save the data in the session.
 $app-&gt;setUserState('com_users. registration. data', $requestData);

...
}

// Attempt to save the data.
$return = $model-&gt;register($data);

...

} ``

So we use the first through the validatetrigger error to the id is written to session, and then send a normal request, in the registerin the reading session to introduce the id, so that you can bypass the validate.

Another point, the implementation of the attack after the attack the user's permissions will be changed to the new registered user's permission generally is Registered, and the permissions currently we cannot change, because in the getDatafunction in the groupsto do the mandatory assignment:

``php $temp = (array) $app->getUserState('com_users. registration. data', array());

...

// Get the groups the user should be added to after registration. $this->data->groups = array();

// Get the default new user group, Registered if not specified. $system = $params->get('new_usertype', 2);

$this->data->groups[] = $system; ``

So now just to achieve a level of elevation of Privilege, as to whether can be vertically elevated as well as how to upgrade to official instructions or is everyone's analysis.

Since no technical details, everything is according to their own estimation, as there is an error, also hope to correct me :)

3. Patch analysis

Alt text

Use the session only allows the use of the specified attribute.

0x02 repair program

Upgrade to 3. 6. 5 <https://www.joomla.org/announcements/release-news/5693-joomla-3-6-5-released.html>

0x03 reference

  • <https://www.joomla.org/announcements/release-news/5693-joomla-3-6-5-released.html>

  • <https://developer.joomla.org/security-centre/664-20161201-core-elevated-privileges.html>

  • <https://github.com/joomla/joomla-cms/commit/435a2226118a4e83ecaf33431ec05f39c640c744>