I'm trying to wrap my head around session hijacking and the use of tokens for CSRF protecting.
I use this object method in each of my scripts to check whether a session variable is set or the token matches the session token.
public function admin_index(){
session_start();
if(!isset($_SESSION["user"]) || $_GET['token']!=$_SESSION['token']) {
header("location: login/login_form.php");
session_destroy();
exit();
}
I'm new at this and my question is:
If my session id is somehow hijacked will he be able to some how also read my variable $_SESSION['token'] in the short time span after session_start and the the session data is fetched and populate in $_SESSION or is it still safe on the server?
Are session variables generally safe even though a valid session has been obtained?
Never mind the $_GET['token'] instead of POST. I'm still working on it.
Thanks
EDIT:
What I'm asking is. If a token also helps me secure my sessions the way I'm using it. If every query, link or view in my script requires a valid token and an attacker only got a hold of my session_id the tokens would be another layer of protection cause he/she would need both the id AND the token to do anything in the script, right?
And the token is secure on the server even though an attacker has acquired my session_id?
Session Hijacking and CSRF attacks are two completely different things and once someone has your access to your session they are 'you' and can access everything on your account.
A CSRF attack is an attack which forces an end user to execute
unwanted actions on a web application in which he/she is currently
authenticated
This is a social engineering and validation issue which using a token can obviously solve as it can be proved that the data was sent legitimately from your form. Using POST instead of GET will make this attack very difficult.
A Session Hijack on the other hand is where someone can use your
session, become 'you' and use your account which will allow them to do
whatever they please.
Once a malicious user has access to this session a CSRF attack is pretty much useless as it is not needed.
If you are worried about your session ids being hijacked then you can take some precautionary measures such as regenerating a users session id once they are elevated to a higher level of access. This can be done using the session_regenerate_id() PHP function. You can also check the User Agent of the browser to check if there are changes and if there are then you can simply ask the user to login and regenerate the id so it is then unknown to the attacker. Obviously there is always a chance that they will be the same user agent but it does limit the risk significantly. Encryption such as SSL/HTTPS are also an option that you may want to look at
For more information you should check out this link for some examples: http://phpsec.org/projects/guide/4.html. Hopefully this has solved your problem :)
Correct me if I'm wrong, but I'm quite sure you simply can't hijack $_SESSION values because these, unlike $_COOKIE is saved on the server and not in the webbrowser.
Therefor they can't change it either. They can close their webbrowser to remove it, but not edit it.
Session variables are stored on the server. They can not be read. However, a session can be hijacked typically by an attacker getting access to the session id of another user, and can then use that session id to impersonate them (hijack) their session.
CSRF is an entirely different concern. CSRF exploits get users to inadvertantly perform operations in a manner similar to xss exploits: I might post a bogus img link where the src is actually a url that passes parameters to a script that your browser runs on your behalf. In that case the attacker is simply getting your browser to make a request you didn't intend it to. The CSRF protection should stop this, because the user does not know what the token is, so they can't embed it into the url.
Related
I'm using session variable for login purpose. If login is successful $_SESSION['userName'] is set. In some pages there are codes like if(isset($_SESSION['userName'])) echo $_SESSION['userName];
I wonder if $_SESSION['userName'] is already set by other website in someone's browser it will lead to a huge problem. How may I overcome this problem, please suggest.
The session value is communicated between a browser and a server by HTTP cookie.
The HTTP cookie is only shared on the same host name like (*.stackoverflow.com)
So, I think another website cannot be get a session value of others.
So this is how a PHP session works.
PHP generates a session id for a specific user. It then hashes that ID and passes the hash to the user as a cookie.
On each subsequent request the user send that cookie back, PHP and looks up the session data for that session hash. It is then able to start the session associated with that user. In that sense no other user is able to access the first user's session without knowing the session hash.
However the end user is vulnerable to session hijacking in case someone else steals their cookies and there's a number of ways this can happen.
Session fixation which someone tricks a user of your site to use a session ID that someone has provided them (there's not much you can do about this).
Man in the middle attacks where someone is between the user and your website and intercepts all data that get passed along. This usually can be protected against by serving the page under HTTPS (not always but it's a lot harder for someone to steal data that comes over HTTPS).
Cross-site scripting (XSS), when someone uses client-side code (which can access cookies) to impersonate that user. You can protect against this by implementing CORS restrictions and sending a "nonce" with each response which you expect the user to return when they send the next request.
Taking advantage of browser exploits that expose the user's cookies to another website. It's normally a requirement to browser manufacturers to prevent websites from accessing cookies they did not set, but sometimes bugs can be present that prevent this. This is usually taken care of if the user keeps their browser up to date (not because exploits are not there but because most people haven't found them yet).
Someone breaks into a user's house and uses the user's browser (can't do anything about this one either).
There's probably more ways
I am implementing CSRF token in my website on every post method.
But when i am accessing my webpages in different tabs then token gets change on both pages and token mismatches.
My token is stored in DOM and i am matching token using SESSION.
How to solve this.?
i change the token on every successful request
Yeah this is why we don't invalidate the token on every successful request. That doesn't just break multi-tab browsing, it also means you can't do stuff like hit the back button then submit.
“Invalidate token on every request” is the kind of bogus security recommendation you get from pentest reports where the tester hasn't found much that's really vulnerable. It's a trade-off as always whether you do, but the usability downside almost always outweighs the minimal security benefit.
You only really need to invalidate the CSRF token (along with the session token) on a privilege level change, most notably on login. This mitigates session fixation attacks, by preventing an attacker who knows the session and CSRF tokens prior to login from exploiting those tokens after you've logged in.
You can achieve this easily:
In the server side, store the CSRF tokens in session like this:
$_SESSION['csrf_tokens']['form1'] = //code to generate csrf token
While validating the token on form submit, you can check,
$_SESSION['csrf_tokens']['form1'] === $_POST['csrf_token']
Please post an example code, unless you are using ajax (which I wouldn't recommend for CSRF tokens the code shouldn't change in both tabs if you open a new tab). Also, I disagree with bobince, you are doing the right thing to implement this measure as once you have the logic in place you can easily and effortlessly use it in all your forms. The best way to implement this is to just have each token expire after a certain amount of time.
bobince: CSRF tokes are used to prevent CSRF attacks not session fixation attacks, both are different the former prevents scripts from executing actions on behalf of the user whereas the latter is an attack in which a malicious user impersonates a normal user by guessing or stealing their session id.
Generate two values – one random key (f.e. via uniqid), and a random token.
You generate both every time a form is rendered – and put them both into hidden fields. And you save the token into the session using the random key. Then when the form data is received, you check if the token send is in the session under the key send. (And if so, you delete the entry with this key after processing the form of course.)
Anything else (f.e. expiration time of tokens, binding of tokens to a certain form type out of several) you implement the same as you would before.
is unnecessarily and unsafe like this why you dont create a token based on session with openssl_random_pseudo_bytes() ,which will produce a safe token, and check if is correct or not or you can use also to expire after 2-5 min.also you can check on owasp about tokens on dom,can be easy spoffed !!!
I'm using the following code for my user login. Everything works fine but im just wondering the security of using this. I'm using the userid as the sessionid when a user logs in.
What are my security issues with using this?
Can the user change the sessionid to a different number and then be logged in as a different user? (how do i stop this?)
if (!empty($row['member_id']))
{
$_SESSION['id'] = $row['member_id'];
header ("Location: team.php");
exit();
I'm not a security expert by any means.
There was an uproar back in, I want to say, 2010 about session theft. So much so that a group put out a tool called Firesheep that would let you quickly steal other sessions in an open wifi situation. The solution is to protect the entire logged in session with SSL or not be on an open network. Back when SSL was first being used, it proved too slow to be used as a session long security measure, but now computing is fast enough.
TLDR: If you don't SSL, someone can steal your session. Facebook and Google both had the same problem.
For clarification, they can't "steal" sessions so much as they can find out the SESSIONID being passed around in the POST request in order to keep you logged in and then modify their cookies to send that around as you instead. The Firesheep tool could snag Facebook logins in seconds. By modifying the cookie with someone else's SESSIONID, the tool was able to pretend to be the original user, allowing full access to the areas of the account that were unlocked upon login. See also: this.
Another good solution to help things is to reprompt the user during any account sensitive activity regardless of their session. For instance, if they try to change their password or change other account info, make sure to ask for their current password again.
The contents of the $_SESSION server-side are only safe as long as there is no way to submit user data in any way that would eventually end up in the session variable. If someone stole a SESSIONID and then entered data on some form (or if you blindly use the name of the form element as the index into the $_SESSION array) they could get stuff in there. The key is to never ever ever ever ever ever ever ever...EVER....trust what the client side has sent as valid or trustworthy. Paranoia is your friend.
I think you are mixing up the Session ID (SID) with your own login id, you save in $_SESSION['id'].
Your code is fine. Session data is saved on the server and cannot be manipulated by the client directly. So he cannot change the value of $_SESSION['id'] (btw: I suggest to use a more unique key name like 'login_id').
Talking about the real Session ID (SID). The SID is a random string generated by PHP automatically and saved as a cookie on the client’s machine. The client can actually manipulate his SID and so potentially takeover a different session. This is called Session Hijacking and it’s a general problem of using sessions, no special problem of your code. Have a look here for further information: PHP Session Fixation / Hijacking
I used $_SESSION['name'] to handle data from page to page. I mainly used it to keep the user logged in between pages. Within every page, i check if $_SESSION[logged_in'] is true or not. If true, keep user logged in. Otherwise, do something else.
This is how i handle my sessions - basic sample:
<?php
session_start();
if($_SESSION['logged_in'])
{
//show control panel list
}
else
{
//show login box. Once user logs in. Once user logs in,
//fetch userID, username, etc from database. Also set
//$_SESSION['logged_in'] = true.
}
?>
Somewhere in between codes i do the following:
SELECT * FROM User WHERE userID = $_SESSION['userID'];
I'm not sure if $_SESSION['userID'] would be accessible by users or not. If its accessible, then the page would be in threat because a user could change the userID manually and get access to others account he/she desires.
I'm not much into security. Please advice! What can i do?
Note: i'm trying to make code as simple as possible. For now, no oop is involved.
Your code is vulnerable to session fixation and session hijacking attacks. See http://phpsec.org/projects/guide/4.html for more information.
As you build bigger, more involved applications, you will also want to be careful how you handle logging the user out and handling other session-related aspects, such as privilege escalation. Handling sessions and logins safely is a tricky beast.
Implementing secure authentication is hard. Unless you are doing it as an academic exercise, i would strongly recommend using the library provided by your framework, if you are lucky enough to have a good one.
You will also want to consider things such as the following:
Do not allow the session id to be forced. [session fixation]
When permissions or credentials are changed (e.g. because the user has now logged in or out) then
immediately invalidate the session and start a fresh one.
Provide a logout feature, and be sure to invalidate the session upon logout.
Set the session cookie to HttpOnly -Preferably, require HTTPS and alo set the cookie to secure only.
Consider restricting the session validity to include checking some other information that helps to match the user e.g. user-agent. [session hijacking]
Always expire sessions after non-use and do not implement "keep me logged in" by reconnecting the user to their old http session.
Ensure that all session-related data is destroyed when a session is invalidated, regardless of where it is stored. A new user coming along, may just happen to get assigned a session id that has been used previously. This new session must not have any access to session data that has been set previously against that session id.
$_SESSION is one of the server-side Super Globals. It's not accessible by users or transmitted from your server in any way.
That's pretty good, here are a few other tips for session management:
Do not accept session identifiers from GET/POST variables:
Session identifiers in URL (query string, GET variables) or POST variables are not recommended as it simplifies this attack. It is easy to make links on forms which set GET/POST variables.
Regenerate the SID on each request:
In PHP use session_regenerate_id(). Every time a user's access level changes, it is necessary to regenerate the session identifier. This means that although an attacker may trick a user into accepting a known SID, the SID will be invalid when the attacker attempts to re-use the SID.
Yes, that is pretty much the right idea.
Here are a couple resources that may help, both with understanding session security and secure programming in general:
http://phpsec.org/projects/guide/4.html
http://phpsec.org/projects/guide/
When a low-privilege non-administrator user logs into my web app successfully, I am storing the following data in the $_SESSION array:
$_SESSION = array(
'user_id' => 2343, // whatever their user_id number is from the DB
'allow_admin' => false, // don't give them access to admin tools
'allow_edit' => false, // don't let them edit stuff
);
Is there any way that they could manipulate the $_SESSION array to give them Admin or Edit access, apart from somehow editing the session files in /tmp? (The above code is the only place where those items are added to $_SESSION)
The contents of the session are only visible and modifiable on the server side.
They could only be modified in an "unauthorized" way if your application or server contains some vulnerability.
You should also be aware of such things as session fixation attacks, where an attacker forces a particular session id onto an unsuspecting user, who when logs in and elevates that session's privileges, allowing an attacker to share that session.
One approach to mitigating these is to regenerate the session id whenever you change privilege levels of the session.
See also this question:
PHP Session Security
If you want to avoid javascript reading your cookies and man in the middle attacks, you need to use a server with https and set the session cookie to only be transported over https.
session.cookie_secure specifies whether cookies should only be sent over secure connections. Defaults to off. This setting was added in PHP 4.0.4. See also session_get_cookie_params() and session_set_cookie_params().
session.cookie_httponly Marks the cookie as accessible only through the HTTP protocol. This means that the cookie won't be accessible by scripting languages, such as JavaScript. This setting can effectively help to reduce identity theft through XSS attacks (although it is not supported by all browsers).
To secure admin privileges better for someone leaving his computer unguarded for a few mins, you should have a timer on last (admin) login. If that time is more then x timeunits away, the user has to login again to use admin rights.
Shorter sessions are also more secure then longer ones.
Server
Sessions are stored on the server. A user could change session data if they have direct access to the directory where sessions are stored. A solution to this is to secure the directory. And make sure you don't have a hole in your php code where you allow the user_id to be set by a $_POST or $_GET.
Client
But on the client side manipulating sessions is possible by hijacking someones session_id. This will let the hijacker pose as that user. And send request on their behalf.
There is also Cross-Site Request Forgery. This is when a hacker tricks a user into sending requests for him. By making him click on a link for example. You could combat this with tokens. A token is a generated string that is put in the $_SESSION array and in every HTML form as a hidden field. When the user submits a form the values are checked against each other. And every time the user requests a new page the token changes. This way an attacker must try to predict the token, which is pretty hard depending on how you make the token.
The links will also show examples on these attacks.
If you don't provide such access in your script there isn't much users can do about that. So your session data should be pretty secure. The only thing user can do is to manipulate session cookie or session id passed in the URL but it's unlikely that he will find an existing session id of another user.
Not unless you've left a security hole somewhere (such as allowing users to add/change $_SESSION data somehow).
As far as i know, no, unless user guess your session id and replaces it in his cookies. You should add additional IP-check at least server-side to prevent this.