Please don’t think I spend all my time looking at Joomla. But a friend was struggling with a problem where every attempt to login to the admin side of a site failed to achieve a login, but also failed to show any kind of diagnostic. What could block the Joomla admin login?
We diagnosed the problem as being an issue with not recognizing the session. The login was working, but when the user was redirected back to the admin side index.php the system did not think there was a valid session in effect. So a fresh login screen was presented. And so on….
Well, it took hours of trawling around Joomla, and a few hints from forums to find the answer. It seems that the Joomla developers introduced code to change the session ID at the point of a login. This happened at version 1.5.16. Unfortunately, the code fails to work on some PHP versions. It is also unnecessarily cumbersome. It is not reproduced here, there is nothing to be gained by reviewing it.
Before looking at a solution, let us review what was the aim of the change. If someone can obtain the session ID, it may be possible to fix the session so as to do things that ought not to be done. Read up session fixation for more details. Many systems start a session even if the user does not log in, so that, for example, a shopping cart can be collected using session variables. Cautiously designed systems also change the session ID on a login, as one contribution towards achieving security. So the aim of the Joomla change made sense.
The question is, therefore, how to modify the Joomla code to get the advantage without the problems. In fact, PHP provides a straightforward answer. For reasons best known to the early Joomla designers, Joomla attempts to set the session ID to a random value that is generated within Joomla software. It is not clear that this is at all necessary, or that the session IDs generated by PHP are defective. There are other obfuscating factors that make the session ID relatively unimportant. So, if we want to change the session ID, the obvious way to do it is to call the PHP function session_regenerate_id.
So to fix the problem but retain a gain in security, modify the file ../libraries/joomla/session/session.php and replace the “fork” method with the following code:
function fork()
{
if ('active' == $this->_state) {
$this->_store->destroy($this->getId());
// restart session with new id
session_regenerate_id();
}
}
This saves quite a chunk of code, and on all tests so far, it works!
[There are articles about the PHP session ID generation process failing to be sufficiently random. They appear to be somewhat exaggerated, and some of them contain downright mistakes. Although it is certainly true that all the “random” mechanisms that can be used in PHP have severe limitations when tested for pure randomness. At present, there is no real answer to this, since it stems from the fact that the servers that are used for the vast majority of web sites do not have hardware randomness generators. Without them, there is no way to avoid the limitation that only pseudo-random numbers can be generated, which will sometimes not be very random at all. Indeed, Linux servers sometimes struggle to create enough randomness to support SSL. However, overriding one PHP mechanism with another, such as generating the session ID using PHP random number functions, is unlikely to offer any significant improvement. The bottom line is that, as with all security issues, there is no point expecting to find a perfect solution. The best is the enemy of the good. Implement what you can, block whatever problems you can, then stop worrying! Most hacks use the crudest possible techniques. You could be hacked by a problem with PHP’s attempts to generate random numbers, but you probably won’t be.]