How I found a Joomla vulnerability

“I've found a simple way to self register users to a Joomla website from 1.6 to the latest 3.6, despite the user auto registration feature has been disabled.
This allows an attacker to gain Registered access level (or a different level, based on the configuration) and to see content reserved to manually registered and trusted users.”
From my report to the Joomla! Security Strike Team on October 18, 2016
Two weeks before sending that report, while working on improving the user experience for the Joomla login, registration, and user account, I decided to look into a suspicion I had about how the Joomla core handles registration requests internally.
I was surprised to find two different pieces of code delegated to user self-registration.
The two pieces of code are quite similar, but have slight differences. Something didn’t smell right.
I thought it was old code, perhaps rewritten during a refactoring, left there for a while, then afterwards forgotten there.
I asked the other opinions on the official Joomla! Development discussion group and on StackExchange, but surprisingly I got no useful answers. 
In hindsight, those posts were dangerously close to publicly disclosing the vulnerability, but at that time, I did not know it.
So, I decided to investigate further, and I compared the two methods, line by line.
The two pieces of code are UsersControllerRegistration::register(), defined in components/com_users/controllers/registration.php, which is actually used by the self-registration process, and UsersControllerUser::register(), defined in components/com_users/controllers/user.php, which, on the contrary, is no longer used anywhere.
The fact that a piece of code is not used by the application does not mean that it is not reachable from the outside by malicious requests.
However, comparing the files, hidden among minor differences, there is an interesting peculiarity: the abandoned code completely ignores the “Allow User Registration” setting! This is going to take a turn for the worse.
This means that it could be possible, in theory, to self-register even when the global option “Allow User Registration” is turned off.

The attack test

Looking into the data it requires, it turns out that it reads the data from a variable called “user” rather than the usual “jform”.
So it is required to craft a form ad-hoc. For those who do not know me, yes, I feel comfortable with forms. :)
A flat HTML file on your local computer holds the code needed for the attack test:

...Technical details temporary removed to allow the most of the Joomla website to update...

At this point, there isn’t anything else to do but browse the local HTML file that was just prepared, and submit the form. Voila.
If there are no error messages, the attack has been successful.

But that is not all

It is worth to point out a second potential vulnerability is present.
While the registration controller filters the received data and saves the filtered data, the user controller filters the data, but stores the unfiltered data instead.
$data = $model->validate($form, $requestData);


$return = $model->register($data);
$return = $model->validate($form, $data);


$return = $model->register($data);

Guess what?

Just out of curiosity, I started checking the previous versions of Joomla to see how old the problem was. I checked the previous version, and sure enough, the problem was there.
I then checked the one before that, and the problem was there, and before, that one even, it was there.
You won’t believe this, but it has been hiding in plain sight for almost 5 years. The vulnerability was already present in Joomla 1.6.0 in January, 2011.

How could this happen? 

That code has probably been seen by hundreds, if not thousands, of programmers in the meantime. Why has nobody seen the problem in 5 years?
I think it’s possible that most people do not question or doubt something that works. If it works, they think, then it must be fine as a whole.
It is said that the best thing about open source is the fact that everyone can look into it.
And it’s true, but you also have to connect your brain to get a sense for what you’re seeing. ;)

Additional note

Anna Mendez has rightly pointed out: "In you article you say this issue is affecting Joomla from 1.6 version. So why Joomla officially says: Affected Installs Joomla! CMS versions 3.4.4 through 3.6.3. So it's from 1.6 or 3.4.4?"
Well, the abandoned code is there from 1.6. I have to deduce that the Security Team has determined that versions below 3.4.4 are not affected by the bug.