I have a web application that I want to improve in its security flaws, I read a lot of articles about it but some questions are still unanswered. I appreciate your help.
First of all I have a login screen. After the user enters his credentials, they are checked against the database ( they are properly hashed ;)), and if it succeeds the server creates a session variable
//Jhon id = 1
$_SESSION["userID"]= '1';
At the beginning of every php file (e.g. dashboard.php) I have the following code:
session_start();
if(isset($_SESSION['userID'])) {
if($_SESSION["userID"]==""){header("location:login.php");}
}else{
header("location:login.php");
}
?>
<html ...
For improve maintenance i want to include this code in an external php file like
include('inc/restricted.php');
?>
<html ...
My two main questions are:
1) If an intruder handles to corrupt or to deny access to restricted.php, would the remain of dashboard.php show up? Is it possible to do something like that? If it is, how could I fix it the way I can include the security code as an external file?
2) As you see the value of my session variables are simple (integers numbers), should I change them to hashed values? I thought the php session was stored on server side but i read about some php session variables stored on cookies and now im worried about the chance of create a cookie with a random number and granted access.
It's possible if the code in this file is insecure. Since we can't see it it's impossible to say how it could be compromised. But generally speaking, the web-facing request should have no ability to control your php code unless you have a severely insecure setup.
The values don't matter. Data stored in $_SESSION is never stored on the client, only on the server. This is controlled in php by the session.handler interface (by default it's stored as a plain-text file on your server in session.save_path).
The things that tend to make sessions insecure are almost always the result of poorly written code or a poorly configured server.
Some things you can do to improve the security of your sessions are outlined below:
Always use session_regenerate_id(true) when logging the user in (this prevents session fixation attacks).
Always delete the session cookie on the client when you log the user out (see the first example in http://php.net/session-destroy). This prevents session take-over attacks when the user is logged in from a public computer, for example, as the session may not always be deleted instantly on the server side and the cookie allows the client to re-trigger the session TTL on the server.
Only transmit session cookies over a secure connection (See session.cookie_secure
To prevent some XSS and CSRF vectors consider using session.cookie_httponly and session.cookie_samesite to prevent malicious JS from opening up these kinds of attacks.
Always use CSRF tokens along with all modifying requests to protect the user from compromising their access strictly via sessions. This is an added layer of security.
Just remember that this is not an unabridged list. Security is built in layers and requires a lot of forethought in use cases and objectives.
Related
So I have my database with the standard usernames and hashed passwords (password_hash).
There's a login form on my site, where users type their details and a session gets created based on that.
<?php
session_start();
//if the username and password is valid
if(validLogin){
$_SESSION['account'] = $username;
}
//$_SESSION['account'] is used from now on for backend user activities
?>
If the credentials are correct, an account session variable is created pointing to the username.
I have increased Session lengths to 1 month (as users complained they kept getting logged out before)
What can I do to increase security here?
If I go into Dev Tools, there is only a single cookie called PHPSESSID, which holds a 26 character value.
However, anyone can just copy and paste that value into their own browser and hijack someone's account - if they had the value.
I am not sure what to do and quite lost.
How can I improve the security here? Besides logging out users every 24 minutes
Firstly, The concept of a session (originally) implied:
The session begins when you open an application, continuous as long as
you work on it, and ends when you close the app.
Since the nature of apps changed and for convenience reasons, this basic pattern has been extended, and sessions kept alive much longer, even if the user is not actively working on it. However, if security is your main focus use a more strict approach, i.e. shorter expiration time and forced logouts.
Secondly, PHP sessions have been invented to solve many of the problems that plague regular browser cookies (stored on the client as text, limited to 4KB, rather accessible, sent along with every request, hence bloating the HTTP request). A PHP session only sends a hashed ID to the browser, and stores all data on the server. If an attacker owns the client security is indeed compromised. But this may be out of your hands if you cannot control the client device security. Security is a multi-layered concept that implies varying degrees of trust..
This answer gives more context on PHP session security and has some useful security recommendations. However, I have one additional recommendation: If you do not need to work with the PHP session id in your client code (i.e. JavaScript) disable session.cookie-httponly in your php.ini (or alike).
If this all is not 'good enough' you will need to implement a more secure protocol, use multi-factor-authentication, or alike. In general, session ids are probably your least concern; having a properly configured web server and following best practices is more important.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
What are some guidelines for maintaining responsible session security with PHP? There's information all over the web and it's about time it all landed in one place!
There are a couple of things to do in order to keep your session secure:
Use SSL when authenticating users or performing sensitive operations.
Regenerate the session id whenever the security level changes (such as logging in). You can even regenerate the session id every request if you wish.
Have sessions time out
Don't use register globals
Store authentication details on the server. That is, don't send details such as username in the cookie.
Check the $_SERVER['HTTP_USER_AGENT']. This adds a small barrier to session hijacking. You can also check the IP address. But this causes problems for users that have changing IP address due to load balancing on multiple internet connections etc (which is the case in our environment here).
Lock down access to the sessions on the file system or use custom session handling
For sensitive operations consider requiring logged in users to provide their authenication details again
One guideline is to call session_regenerate_id every time a session's security level changes. This helps prevent session hijacking.
My two (or more) cents:
Trust no one
Filter input, escape output (cookie, session data are your input too)
Avoid XSS (keep your HTML well formed, take a look at PHPTAL or HTMLPurifier)
Defense in depth
Do not expose data
There is a tiny but good book on this topic: Essential PHP Security by Chris Shiflett.
Essential PHP Security http://shiflett.org/images/essential-php-security-small.png
On the home page of the book you will find some interesting code examples and sample chapters.
You may use technique mentioned above (IP & UserAgent), described here: How to avoid identity theft
I think one of the major problems (which is being addressed in PHP 6) is register_globals. Right now one of the standard methods used to avoid register_globals is to use the $_REQUEST, $_GET or $_POST arrays.
The "correct" way to do it (as of 5.2, although it's a little buggy there, but stable as of 6, which is coming soon) is through filters.
So instead of:
$username = $_POST["username"];
you would do:
$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
or even just:
$username = filter_input(INPUT_POST, 'username');
This session fixation paper has very good pointers where attack may come. See also session fixation page at Wikipedia.
Using IP address isn't really the best idea in my experience. For example; my office has two IP addresses that get used depending on load and we constantly run into issues using IP addresses.
Instead, I've opted for storing the sessions in a separate database for the domains on my servers. This way no one on the file system has access to that session info. This was really helpful with phpBB before 3.0 (they've since fixed this) but it's still a good idea I think.
This is pretty trivial and obvious, but be sure to session_destroy after every use. This can be difficult to implement if the user does not log out explicitly, so a timer can be set to do this.
Here is a good tutorial on setTimer() and clearTimer().
The main problem with PHP sessions and security (besides session hijacking) comes with what environment you are in. By default PHP stores the session data in a file in the OS's temp directory. Without any special thought or planning this is a world readable directory so all of your session information is public to anyone with access to the server.
As for maintaining sessions over multiple servers. At that point it would be better to switch PHP to user handled sessions where it calls your provided functions to CRUD (create, read, update, delete) the session data. At that point you could store the session information in a database or memcache like solution so that all application servers have access to the data.
Storing your own sessions may also be advantageous if you are on a shared server because it will let you store it in the database which you often times have more control over then the filesystem.
I set my sessions up like this-
on the log in page:
$_SESSION['fingerprint'] = md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR']);
(phrase defined on a config page)
then on the header that is throughout the rest of the site:
session_start();
if ($_SESSION['fingerprint'] != md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR'])) {
session_destroy();
header('Location: http://website login page/');
exit();
}
php.ini
session.cookie_httponly = 1
change session name from default PHPSESSID
eq Apache add header:
X-XSS-Protection 1
I would check both IP and User Agent to see if they change
if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']
|| $_SESSION['user_ip'] != $_SERVER['REMOTE_ADDR'])
{
//Something fishy is going on here?
}
If you you use session_set_save_handler() you can set your own session handler. For example you could store your sessions in the database. Refer to the php.net comments for examples of a database session handler.
DB sessions are also good if you have multiple servers otherwise if you are using file based sessions you would need to make sure that each webserver had access to the same filesystem to read/write the sessions.
You need to be sure the session data are safe. By looking at your php.ini or using phpinfo() you can find you session settings. _session.save_path_ tells you where they are saved.
Check the permission of the folder and of its parents. It shouldn't be public (/tmp) or be accessible by other websites on your shared server.
Assuming you still want to use php session, You can set php to use an other folder by changing _session.save_path_ or save the data in the database by changing _session.save_handler_ .
You might be able to set _session.save_path_ in your php.ini (some providers allow it) or for apache + mod_php, in a .htaccess file in your site root folder:
php_value session.save_path "/home/example.com/html/session". You can also set it at run time with _session_save_path()_ .
Check Chris Shiflett's tutorial or Zend_Session_SaveHandler_DbTable to set and alternative session handler.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
PHP Session Security
I am using sessions all throughout my application. I want to make them much more secure. Currently I am using code like $username = $_SESSION['username']; and the like.
How do I make my sessions more secure?
The first thing you'll want to watch out for is Session Hijacking. To quote Wikipedia:
In computer science, session hijacking refers to the exploitation of a valid computer session—sometimes also called a session key—to gain unauthorized access to information or services in a computer system. In particular, it is used to refer to the theft of a magic cookie used to authenticate a user to a remote server. It has particular relevance to web developers, as the HTTP cookies used to maintain a session on many web sites can be easily stolen by an attacker using an intermediary computer or with access to the saved cookies on the victim's computer (see HTTP cookie theft).
The basic idea is, if a visitor to your website (Alice) has a session cookie and a session ID (let's assume it's 12345), then if a malicious user (Mallory) is able to learn Alice's session ID via either JavaScript, traffic sniffing, social engineering or other methods, then Mallory can browse to your site and set his session ID to 12345 and he effectively becomes Alice.
One way to prevent this is to alter the session ID on every request, which you can do via the PHP session_regenerate_id function. You would call session_regenerate_id at the beginning of every request, after calling session_start()
Please be aware that this is a very complicated topic. I'd highly recommended reading the Wikipedia article and making sure you fully understand the issues at play.
EDIT: I was about to type a lot more information out for you, but then I realized that your question really is a duplicate of this StackOverflow question. I'd recommended reading that as a starting point.
It depends a lot what you are trying to protects. If you are worried about that the information contained in the session could be exposed or modified, you don't have to worry about that since it can only be seen and modified by the server.
If you are worried about the possibility that some people could use other people session, you can do the following :
Analyze your code and make sure you have no XSS flaw.
Use SSL to prevent session hijacking if your visitor are using public network.
Make sure your session are using the HTTP Only flag
Use md5 version of a password in the database and then md5 encrypt the session password, so that if the password is correct, then these 2 values will be the same.
I know about all the issues with session fixation and hijacking. My question is really basic: I want to create an authentication system with PHP. For that, after the login, I would just store the user id in the session.
But: I've seen some people do weird things like generating a GUID for each user and session and storing that instead of just the user id in the session. Why?
The content of a session cannot be obtained by a client - or can it?
You're correct. The client just sees a randomly generated session id token. There are ways this token can be misused (hijacked, etc.), but having a GUID on top adds nothing. In contrast, options like session.cookie_httponly (JavaScript can't see session cookie) session.cookie_secure (Cookie can only be transmitted over HTTPS) protect against certain attack scenarios.
The short answer is that $_SESSION is safe and you do not need to worry about its contents being leaked to a user or attacker.
The content of the session is not normally be accessible to the user. You should be able to store the user's primary key and you'll be fine. There are cases where the session can be leaked, on a normal linux system the session folder is in /tmp, however this could be changed in your php.ini to the web root (/var/www/tmp) and then could be accessible. The only other way is if the user is able to get access to the $_SESSION super global by hijacking a call to eval() or by the variable being printed normally.
If you are running on a shared host and using an old version of PHP and/or your server is misconfigured it might be possible for another user on this system to read or even modify a session file stored in /tmp/. I don't know of a single application that takes this attack into consideration. If this is a problem you can store the information in a session table in the database.
Sometimes, for added security, developers may assign a long string to the user's session in order to make hijacking even more difficult. By setting a cookie with this new string at the time of session creation, the app can check for the correct string on subsequent requests to better ensure it is the person who actually logged in.
It's just adding one more thing a wannabe hijacker would have to guess. However, it can be a false sense of security as it does little to protect the session if sniffing is involved because the new cookie is sent right along with the php session cookie. Also, session id's are very hard to guess as it is (as I'm sure you know, just don't place it in the url but, rather, in the cookie).
Session info is stored on the harddrive so it's not obtainable by clients without application intervention.
I've never seen GUIDs being used for sessions, but there are a couple of additional methods I have seen that do add a little more security.
Storing the user's IP - if you need to force a session change based on locations (sometimes geoIP stuff will do this)
Storing the user's HTTP_USER_AGENT header string. Can provide a bit of security against hijacking if the hijacker happens to be using a different browser.
There's a great article on session hijacking countermeasures on Wikipedia, actually.
That being said, I would imagine that anyone storing a GUID as part of a session to use in session security might be failing to see a better solution (such as session regeneration). I can see other uses for a GUID to be stored (maybe it's part of a random generator for a game), but not for use with session security.
I have a php site that lets registered users login (with a valid passord) and sets up a session based on their UserID. However I'm pretty sure thisis being hijacked and I've found "new" files on my server I didn't put there. My site cleans all user input for SQL injections and XSS but this keeps happening. Has anyone got any ideas on how to solve this?
A session cookie hijacking should NOT allow an attacker to create new files on your server. All it could do is given access to an authenticated user's session. It'd be up to your code, and/or the server's configuration that would allow uploading arbitrary files to the site's webroot.
To check for remote compromise hits, get the file creation times of the suspicious files (searches.php, 7.php.jpg) etc..., then comb through your server's logs to see what was happening around that time. If you're logging the session ID along with the rest of the hit, you could trivially see if the session was hijacked, as it would be used from two or more different IPs during the session's lifetime. It'd be especially obviously if the original user logged in from one ISP, then suddenly appeared to jump to a completely different ISP.
And of course, how are your sessions implemented? Cookies? PHP trans_sid (passing the session in hidden form fields and query strings)? trans_sid is especially vulnerable to hijacking, as the mere act of sharing a link to something your site also transmits the session ID, and any external links on your site will have the session ID show up in the HTTP referer.
The solution that PHP experts have come up with is to use unique keys/tokens with each submission of the forms, have a look at the idea here at net-tutes.
Don't forget have a look at the PHP Security Guide.. It covers topics including XSS, Form Spoofing, SQL Injection, session hijacking, session fixation and more.
Remember, always use proper data types in your queries, for example use the int or intval function before numbers and mysql_real_escape_string function for the string values. Example:
$my_num = (int) $_POST['some_number'];
$my_string = mysql_real_escape_string($_POST['some_string']);
You may also use the prepend statements for your queries.
Popular Project To Secure PHP Applications:
XSS Filtering Functions by Christian Stocker (Also used by Kohana framework)
HTML Purifier (Also used by Kohana framework)
OSAP PHP Security Project
I'll have ago and say that your 'cookie' is easy to guess.
Some sites, when the user logs, just create a cookie and the authentication code just checks for the EXISTENCE of a cookie.
Now, if I register and login to your site and then cut your cookie open and notice that you just store my user id then I can manipulate the value to some other user id and voila!
You get the idea.