On October 25th, Joomla! was updated to version 3.6.4 to address two vulnerabilities :
CVE-2016-8869 concerning registration with elevated privileges.
CVE-2016-8870 concerning account creation while registration is disabled.
In this post, we wanted to quickly discuss the vulnerability and its impact on vulnerable installations.
Upon patch-diffing the two versions, we noticed that an entire method had been removed from the components/com_users/controllers/user.php file : the register method from the UsersControllerUser class.
Normally, the register method used by Joomla! is the one from the UsersControllerRegistration class, in components/com_users/controllers/registration.php.
The deleted one is most likely a leftover from old patches, and doesn’t enforce a check on whether or not user registration is enabled (as opposed to the UsersControllerRegistration.register method).
Moreover, the $data array is supposed to be sanitized in the first line below, but the unsanitized value is then used in the register function at the end of this snippet, allowing us to submit custom data such as group and uid values.
We can call this method by posting our registration values on the index.php?option=com_users&task=User.register URL.
POST /index.php?option=com_users&task=User.register HTTP/1.1 Host: localhost Connection: keep-alive Accept-Encoding: gzip, deflate Accept: */* User-Agent: python-requests/2.11.1 Cookie: 96b8cb33d84fb0aa459957bcad81cf90=go86e62fsve2a3jaqdmk6h6oq4 Content-Length: 284 Content-Type: application/x-www-form-urlencoded user[password1]=exploit&user[username]=exploit&user[email2]=email@example.com&user[password2]=exploit&user[name]=exploit&user[email1]=firstname.lastname@example.org&user[groups]=7&7c48521fa302676bada83d0e344011f2=1
The newly created user is then found on the server :
For a valid request, we need to retrieve a CSRF Token and post it with a value = 1.
We are able to specify a custom user[id] value. If that id pre-exists in the database, the corresponding user will be overwritten during the registration.
Additionally, we can get high privileges by posting an array of user[groups] values that will be assigned to the account. The default group id for Administrators is 7.
However, the only way to get the SuperAdmin group (8 by default) is to overwrite a pre-existing SuperAdmin user by specifying his user id.
Note that if user registration is disabled, the new/overwritten user will be blocked from logging in resulting in a denial of service for the SuperAdmin account.
In order to find and compromise a SuperAdmin account, it is possible to bruteforce all user ids and try to create a user with all possible groups. This will ensure that only the existing SuperAdmin accounts are overwritten (only the SuperAdmin ids can be overwritten to have SuperAdmin rights).
To create an admin account when the Administrator group id isn’t 7, it is possible to assign all the group ids from 1-99 (but leave the SuperAdmin group id out).