?
avatar nSamu
nSamu
21 Feb 2015

The problem

We have just ran into a problem. The activation token for users is generated by this code: JApplication::getHash(JUserHelper::genRandomPassword()); (in /components/com_users/models/registration.php:362)

The genRandomPassword() doesn't generate unique string, so in some cases (with large amount of registration) the activation link of two users won't be unique.
In these cases if A user registers before the B user and B uses the activation link first, that link will activate A user instead of B. This is a more serious problem with some auto login plugins, and can't be altered without Joomla core modification.

Possible solution

Change genRandomPassword() with uniqid( rand(), true ) or other unique id generator method.

Another solution can be to prepend the registration email value (or a hash of it) to the generated "password", or add it to the activation link and check it before the activation.

avatar nSamu nSamu - open - 21 Feb 2015
avatar brianteeman brianteeman - change - 23 Feb 2015
Labels Added: ?
avatar brianteeman brianteeman - change - 25 Feb 2015
Labels Removed: ?
avatar brianteeman brianteeman - change - 25 Feb 2015
Labels Added: ?
avatar nikosdion
nikosdion - comment - 1 Mar 2015

Actually, you are wrong. genRandomPassword uses JCrypt::genRandomBytes which, as you can see for yourself, returns a cryptographically safe string. The randomness is provided by openssl_random_pseudo_bytes, /dev/urandom or a cryptographically secure pRNG (pseudo-random number generator) implemented in PHP according to what is available. The result is a very random string with a conflict possibility one in 2 billion. Winning the lottery twice is more likely.

On the other hand, what you propose uses the uniqid method. It comes with a big fat warning in the php.net site:

Warning
This function does not create random nor unpredictable strings. This function must not be used for security purposes. Use a cryptographically secure random function/generator and cryptographically secure hash functions to create unpredictable secure IDs.

Not to mention that you are priming it with rand() which uses a not-quite-random Mersenne twister pRNG. It also comes with a big fat warning:

Caution
This function does not generate cryptographically secure values, and should not be used for cryptographic purposes. If you need a cryptographically secure value, consider using openssl_random_pseudo_bytes() instead.

As you can see Joomla! is already aware that using uniqid() or rand() CAN and WILL lead to collisions, with the adverse results you described, and has already been using cryptographically secure random number generators since Joomla! 3.2.5.

What is proposed here is a regression with a detrimental impact on security, therefore I'd advise the maintainers to close this issue.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6139.
avatar nSamu
nSamu - comment - 1 Mar 2015

You miss the point. What I recommended is just not as secure as you want (sorry for that), but it's unique. Use uniqid( genRandomPassword(), true ). This will provide a unique and secure string...but if you don't want uniqid(), use at least the user's email as a prefix with the genRandomPassword() to achieve more uniqueness.

avatar nikosdion
nikosdion - comment - 1 Mar 2015

You are missing MY point. Uniqid will NOT return a guaranteed unique value. It will return a random ID based on time which is predictable. Therefore an attacker observing the network can deduce the ID and fake a user account under an email address he doesn't control. If you do not understand why this has TERRIBLE security repercussions (more so when this function is also used for password resets) I would recommend educating yourself on the importance of random string generators and their implications in security of web applications.

And I have to remind you: the collision possibility RIGHT NOW is 1 in 2 billions. Jumping off a plane at 3,000 feet without a parachute and surviving to tell the story is about a hundred thousand times MORE likely than the collision you are afraid of. Winning the lottery TWICE in a row is also more likely.

In short, your theoretical attack is impractical. If you don't believe me please generate 20 billion random strings using this method and perform a frequency analysis on the population. You will see what I mean in a statistically meaningful manner.

avatar akoszodi
akoszodi - comment - 1 Mar 2015

Dear nikosdion: You miss the point.

Point was not about how to generate random key. He started with this: "We have just ran into a problem" .So he is not talking about theory. We ran into same problem. We had around 80 000 users resistered to an event, and around 8000 activated in 2 weeks (the time is not important here). Independetly of theory that possibility is 1/2billion. We had around 10 users which got same activation code. And every of them activated into other's account.

So the point is not about theory how to generate random string, just to change it on enough long.

avatar nikosdion
nikosdion - comment - 1 Mar 2015

Which Joomla! version and environment?

On Joomla! 3.2 it makes sense, it was using an insecure method.

On Joomla! 3.3 and 3.4 it depends on your environment. If the OpenSSL module for PHP is not present it will use urandom, the randomness of which depends on your server. If it is available it depends upon server configuration which pRNG is used. So, if you are using Joomla! 3.3 or 3.4 and you have this issue you have a major problem with your server's security that goes far beyond Joomla!. Just the fact that an insecure MT pRNG worked better than your server's implementation of a randomness source is a strong indication that HTTPS and SSH are likely broken. Maybe you want to fix your server?

avatar akoszodi
akoszodi - comment - 1 Mar 2015

I wouldn't like to dig deeper. I think 99% of users are just installing and using it, and mostly on shared hosting. But you still don't get the point, just repeating yourself. It is not about security, just about enough long activation key. And it can be solved even with basic functions without cryptographic stuff, openssl, etc.

I think uuid v4 would be enough good for everyone ;).

avatar nikosdion
nikosdion - comment - 1 Mar 2015

Then you are missing the entire point of security. The idea is that you need an activation / password reset key which CANNOT BE GUESSED. If it can be guessed (using rand it can!!!) an attacker can and will hijack any account. This is why I am repeating myself.

Besides. The problem is not being hosted on a shared server. The problem is that YOUR server is badly configured which is NOT the norm. This is why nobody else had this experience.

And you still have not told me which version of Joomla! you are using and whether the OpenSSL PHP extension is enabled. Instead you insist that Joomla! screws up its security model which is, sorry to have to put it so bluntly, completely irresponsible!

avatar akoszodi
akoszodi - comment - 1 Mar 2015

Please guess: uniqid( genRandomPassword(), true )

In this case the bigger problem is, that keys are not unique, so users are arriving to each other's account, and not that someone in the world can guess activation key.

If you still can't get it, nSamu didn't report a security issue, just an issue. That guy who will or won't solve will decide what to do.

System was : PHP Version 5.4.36, OpenSSL/1.0.1e , Joomla 3.3.1
Shared hosting any my server doesn't have any connection. Joomla is on that server, and there was this problem. So just forget 'my' server.

avatar brianteeman
brianteeman - comment - 1 Mar 2015

Reducing the security and implementing a fundamentally insecure method is not an option. Closed so we dont waste any more time on code that will not be accepted


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6139.
avatar brianteeman brianteeman - change - 1 Mar 2015
Status New Closed
Closed_Date 0000-00-00 00:00:00 2015-03-01 15:36:30
Closed_By brianteeman
avatar brianteeman brianteeman - close - 1 Mar 2015
avatar brianteeman brianteeman - close - 1 Mar 2015
avatar nikosdion
nikosdion - comment - 1 Mar 2015

There are TWO equally important issues.

  1. Being able to guess keys. I am not a cryptanalyst so I can't explain the gory details of a seed attack, but this core PHP developer and cryptanalyst can: http://blog.ircmaxell.com/2011/07/random-number-generation-in-php.html So, really, trust me, I do know that using rand() and uniqid() is susceptible to an attack. In other words, if you use uniqid and rand you may have seemingly unique IDs (they are not unique and I cannot stress this enough) but an attacker CAN AND WILL guess them. In one syllable words for you to understand it: if Joomla! uses uniqid then an attacker will be able to use the password reset of the Super User and reset the Super User password to his liking, taking over your site. Therefore using any combination of rand(), mt_rand() and uniqid() is a Totally Bad Idea™.

  2. Key duplication. Joomla! –just like every single other PHP-based software out there– needs a source of random bytes to generate the hash used for account activation and password resets. Normally it tries to use the OpenSSL PHP module which IS NOT the same as having the OpenSSL library on your server. If this is found the data returned is nearly guaranteed to be extremely unique and absolutely unguessable, fixing both problems (see the previous blog post for the potential pitfalls which are far less than using rand(), mt_rand() and uniqid()). If this is not found Joomla! tries to use /dev/urandom. Please hold that thought for a minute, I'll explain below why this may be a problem. Finally, if /dev/urandom is not available, e.g. on Windows, it uses a PHP implementation of a random bytes generator. Any of these three methods guarantees uniqueness of the generated hashes on a server which is not configured like total crap.

And now let's discuss the thought I told you to hold. Using /dev/urandom. Please read http://en.wikipedia.org/?title=/dev/random Did you spot the problem? If the entropy pool is depleted it will be reused. This means that randomness (ergo, non-repeatability) is not guaranteed if the entropy (random noise) pool empties faster than it is filled. Considering that entropy should be added from random operations such as disk or network access we do conclude that the problem of key repeatability you are talking about is not a Joomla! issue but a server issue and it would only happen when all of the following conditions are true:

C1. The OpenSSL PHP module is not installed or activated (server configuration error)
C2. There is a lot of randomness being consumed very fast e.g. hundreds of user registrations in a few seconds (operating condition)
C3. The kernel entropy pool not being filled in (server configuration error)

I am disinclined to consider what is clearly a server issue to be an issue with Joomla! itself. The proper fix is to enable the OpenSSL PHP module (see http://php.net/manual/en/book.openssl.php). The alternative workaround is hacking core to remove the if-block using /dev/urandom because your server is broken. But screwing up the security model of Joomla! IS NOT A FIX! Fix your server, don't screw up Joomla!.

Add a Comment

Login with GitHub to post a comment