I use the $_SESSION variable to log users in. Are they safe from Injections?
If you wish to have a look at my scripts to check for vulnerability's Here you go: http://pastebin.com/raw/7iiSSjKP
So thanks to a user below they linked me to: http://resources.infosecinstitute.com/session-hijacking-cheat-sheet/
It looks like my sessions are being stored exactly the same as the InfoSec website's vulnerabilities. And yes, It is vulnerable.
I tested and the PHPSESSID cookie stored on the browser is exploitable, If I inject a different users cookie I will be logged into there account and vice-versa. If I stay on there cookie, logout and login to my own account, they will be logged into my account.
(Bottom msg and top 2 msgs are me other ones are my friend bean)
How can I fix this?
I have read around a lot and apparently a SSL certificate just solves this, I do have a SSL certificate but it doesn't seem to change anything. What do I do to solve this?!
Methods I have tried:
http://pastebin.com/raw/5skKhPSw (Seems to work at first and it would make sense to work but if you log into other accounts and vice-versa it just messes up here and there so its not a great solution.
Dont know any other way. Open to Suggestions.
$_SESSION are usually used for logins, thus they are reasonably safe by default, as a user won't be able to somehow set the $_SESSION['username'] value themselves; the value can only be set by your server.
However, there are still vulnerabilities about $_SESSION, more specifically session hijacking, this is the only real vulnerability to the whole scheme.
Also, after header("Location: http://gameshare.io");, you should use exit;.
Setting a header will not terminate the current script. Thus, if you're outputting sensitive information after this line, it will be sent to the client! You need to explicitly exit after setting the header.
Related
I've made a website which has registration/login. I can see the PHPSESSID cookie in Chrome's Developer Tools, so I'm wondering how can I use this session id value to hijack into the account I'm logged, from let's say a different browser, for simplicity's sake?
Should a secure website be able to determine that this session is being hijacked and prevent it?
Also, how come other big sites that use PHP (e.g. Facebook) do not have PHPSESSID cookies? Do they give it a different name for obscurity, or do they just use a different mechanism altogether?
Lots of good questions, and good on you for asking them.
First.. a session is just a cookie. A 'session' is not something that's part of the HTTP stack. PHP just happens to provide some conveniences that make it easy to work with cookies, thus introducing sessions. PHP chooses PHPSESSID as a default name for the cookie, but you can choose any you want.. even in PHP you can change the session_name.
Everything an attacker has to do is grab that session cookie you're looking at, and use it in its own browser. The attacker can do this with automated scripts or for instance using firebug, you can just change the current cookie values.
So yes, if I have your id.. I can steal your session if you didn't do anything to prevent it.
However.. the hardest part for an attacker is to obtain the cookie in the first place. The attacker can't really do this, unless:
They have access to your computer
They somehow are able to snoop in on your network traffic.
The first part is hard to solve.. there are some tricks you can do to identify the computer that started the session (check if the user agent changed, check if the ip address changed), but non are waterproof or not so great solutions.
You can fix the second by ensuring that all your traffic is encrypted using HTTPS. There are very little reasons to not use HTTPS. If you have a 'logged in' area on your site, do use SSL!!
I hope this kind of answers your question.. A few other pointers I thought of right now:
Whenever a user logs in, give them a new session id
Whenever a user logs out, also give them a new session id!
Make sure that under no circumstances the browser can determine the value of the session cookie. If you don't recognize the cookie, regenerate a new one!
If you're on the same IP and using the same browser, all you have to do is duplicating the session ID (and maybe other cookie values: not really sure if browser specific things like its agent string is tracked/compared; this is implementation dependant).
In general, there are different ways to track users (in the end it's just user tracking). For example, you could use a cookie or some hidden value inside the web page. You could as well use a value in HTTP GET requests, a Flash cookie or some other method of authentication (or a combination of these).
In case of Facebook they use several cookie values, so I'd just assume they use one of these values (e.g. 'xs').
Overall, there's no real 100% secure way to do it (e.g. due to man-in-the-middle attacks), but overall, I'd do the following:
Upon logging in, store the user's IP address, his browser agent string and a unique token (edit due to comment above: you could as well skip he IP address; making the whole thing a bit less secure).
Client side store the user's unique id (e.g. user id) and that token (in a cookie or GET value).
As long as the data stored in first step matches, it's the same user. To log out, simply delete the token from the database.
Oh, and just to mention it: All these things aren't PHP specific. They can be done with any server side language (Perl, PHP, Ruby, C#, ...) or server in general.
Someone sniffs the session ID cookie and sets it for a subsequent request. If that's the only thing authenticated a user, they're logged in.
Most sites will use authentication based on cookies in some form. There are several ways to make this more secure such as storing info about the user's browser when they log in (e.g. user agent, IP address). If someone else naively tries to copy the cookie, it won't work. (Of course, there are ways around this too.) You'll also see session cookies being regenerated periodically to make sure they aren't valid for a particularly long time.
Check out Firesheep for a Firefox extension that performs session hijacking. I'm not suggesting you use it, but you may find the discussion on that page interesting.
Ok, i have always wondered if these 2 actions are possible:
To manipulate cookies. I mean, if i login for example into facebook it will save a cookie in my browser. Could i edit it in anyway? I think so since it is set into MY browser and not set locally.
To manipulare a javascript script. I mean, since javascript is read by the browser and every user can read the language, could it be edited? For example, let's say i have an ajax call that send data strings like user=basic or something (it's just an example), could someone change it to user=admin?
I hope this kind of things are not possible or i am pretty much f****d!
In that case, I'm sorry to say you are pretty much f****d.
You must always assume that everything on the client side can be manipulated by some evil hacker. This includes cookies and JavaScript.
Firefox makes this extra easy, using the Edit Cookies extension for cookies, and Firebug to edit JavaScript (and HTML and CSS).
Both users and javascript can manipulate cookie data. However, broswers have optional (maybe default) protection against setting cookie data cross-domain.
I think modifying cookies should be pretty easy, as they're stored locally. I checked and in firefox there's a bunch of sqlite files that seem to have that. I don't know much about sqlite, but it seems that modifying them should not be a problem (especially since you could get to the browser source code in this case and see how it interacts with them :) )
I'm not sure about javascript modification, it most surely can be done by messing around with low level HTTP stuff (intercepting request and sending bogus responses with the modified code). Anti cross-site scripting policies helps a little, but I wouldn't rely on them much, there should be security checks server based to be safer.
Yes/No, your domain can only manipulate cookies set by your domain. Your JS script, being on youdomain.com or localhost cannot edit a cookie set by facebook.com. Think about it, Internet would have imploded by now if you could do that.
However, users can edit their cookies at will.
Yes.
Yes and yes, and there are even tools specifically designed to make doing so easy. Getting security right is hard, and unfortunately it's something that greener web developers often completely miss.
The only thing you can really safely store in a cookie is a login token. Basically, each time your user logs in, generate something like a GUID. Save the GUID to a column in the user's record (like LoginToken or whatever) and then set their cookie to the same GUID. When they logout, clear the record's LoginToken. Then when a request comes in, you can just query your database for the user who has a LoginToken equal to the value in the cookie. It's safe to assume that by holding the token, the requestor is in fact the user represented by the token.
If a malicious user edits their cookie, they'll get nothing more than logged out, since you'd treat a not-found token the same as no token at all.
On the server, once you check a token, you then determine if that user has admin rights (usually by looking at their record).
As far as being able to modify script, that's just a fact of life. Your server code has to assume that every request is malicious. Before you do anything, verify their token and verify that they're allowed to do what they're requesting.
2 things:
Validate the data client-side for usability, but also do it server-side to prevent someone from tampering with the data
Encrypt cookies to make it harder to manipulate
I'm using php for my site and was wondeirng if it would be a good idea to use the $_SERVER
md5($_SERVER['remote_addr'] + $_SERVER['http_user_agent'])) into a cookie_auth field in the user table.
When the user logs in, php will use the above key to re-check the current user and compare it to the stored key and if matched get credintials for the user.
The problems are, the user agent can change and IP can change. I guess my main concern is the user user agent. IP addresses typically stay around for a month or two and my primary user base has static ip addresses (companies) so this shouldn't be issue.
Are there any other php $_SERVER variablies that I could concatinate that would be less volitile... but still dynamic?
I have the php manual infront of me but I don't see any usefull... Maybe I'm missing something.
Do other developers implement anything similar to this?
Thoughts?
Is there a better way to go about this?
It won't work, also because of proxies. If two people with the same user agent visit, then it's disaster.
Some projects can do "cookieless sessions" by passing the session id in a GET variable in all URLs that they use.
PHP can actually do this by itself. And you can even force PHP to not use cookies at all, just pass it in GET variables.
But there are some drawbacks. If you invoke URLs of your application in your javascript code, you have to insert the session id there. Also, if there are external links, the session id can be made available via the referer (sic) HTTP parameter to third parties, which could result in potential session stealing. You have to be extra careful with XSS holes. You probably have to be careful with session fixation happening during the login procedure of your application. And so on.
my primary user base has static ip addresses (companies)
So, if one persone in MegaCorp (with all the same browsers, and the same external IP address) logs in, everybody there is logged in? Don't do it.
And another reason: all iPhones in the same area (same proxy, same browser) are logged in. All I have to do to break in is just to be within several hundred meters (to some kilometers in some places) to someone with access, and it's automagically granted to me.
There are in general 2 ways to have a 'passwordless login' (which is where most of these questions originate):
Cookies with a sufficient 'unguessable hash' from a previous login
Convince the user to install a certificate you can validate over HTTPS.
Most of the $_SERVER variables are attacker controlled (remote_addr is pulled directly from the tcp socket and there for cannot be spoofed or otherwise tampered with). However an attacker can change the user-agent to anything.
Don't re-invent the wheal. session_start() and the $_SESSION super-global is secure, easy to implement and robust. To use this you should always call session_start() in a header file for all pages.
if(!$_SESSION[logged_in]){
header("location: login.php");
die();//Yes php keeps executing so you need this!
}
then in login.php:
if(login($_REQUEST[user],$_REQUEST[password])){
$_SESSION[logged_in]=true;
}
When a user logins I get him/her's ID and save it in a session var. What I wonder is, is this the way to go? Or should I use cookies? so it automatically login and so on.
session_start();
ifcorrectlogin {
$_SESSION['id'] = mysql_result($loginQuery, 0, 'user_id');
}
how do you authenticate your users?
//Newbie
Yes, this is the way to go. The session itself is already backed by a cookie to remove you any programming efforts around that. The session (actually, the cookie) will live as long as the user has the browser instance open or until the session times out at the server side because the user didn't visit the site for a certain time (usually around 30 minutes).
On login, just put the obtained User in the $_SESSION. On every request on the restricted pages you just check if the logged-in User is available in the $_SESSION and handle the request accordingly, i.e. continue with it or redirect to a login or error page. On logout, just remove the User from the $_SESSION.
If you want to add a Remember me on this computer option, then you'll need to add another cookie yourself which lives longer than the session. You only need to ensure that you generate a long, unique and hard-to-guess value for the cookie, otherwise it's too easy to hack. Look how PHP did it by checking the cookie with the name phpsessionid in your webbrowser.
Cookies can be manipulated very easily. Manage login/logout with Sessions. If you want, you can store the users emailaddress/username in a cookie, and fill the username box for them the next time they visit after the present session has expired.
I would try to find a session engine so you don't have to deal with the misc. security issues that bite you in the ass if you do the slightest thing wrong. I use django which has a session engine built in. I'm not aware of the other offerings in the field although I would assume most frameworks would have one.
The way they did it in django was by placing a cryptographic hash in the user's cookies that gets updated every page view and saving all other session information in a database on your server to prevent user tampering and security issues.
As BalusC mentions, the session_-functions in php are the way to go, your basic idea is sound. But there are still many different realisations, some of them have their pitfalls.
For example, as Jonathan Samson explains, using cookies can result in security holes.
My PHP is a bit rusty, but I remember that the session_-functions can also use session IDs that are encoded in URLs. (There was also an option to have this automatically added to all local links (as GET) and form targets (as POST). But that was not without risks, either.) One way to prevent session hijacking by copying the SID is to remember the IP address and compare it for any request that comes with a valid session ID to to IP that sent this request.
As you can see, the underlying method is only the start, there are many more things to consider. The recommendation by SapphireSun is therefore something to be considered: By using a well tested library, you can gain a good level of security, without using valuable development time for developing your own session system. I would recommend this approach for any system that you want to deploy in the real world.
OTOH, if you want to learn about PHP sessions and security issues, you should definitely do it yourself, if only to understand how not to do it ;-)
I'm looking for tips and ideas on how to best incorporate authentication with PHP using Cookies.
Should each php script check for the cookie value to determine if the user is still logged in? Should there be one script that does this check and Include that script from each of the other scripts? Can the cookie value be seen by php from different depths of the filesystem?
Like: blahblahblah.com/ and blahblahblah.com/login/
Can they both read the cookie?
Lots of questions on one post, but thanks!
nothing is safe on the client side.
You change the login flag on Cookies easily on any browser. Thus it is more recommended to be saving login-related data on php's $_SESSION
If you wish to extend the session, simply look at session_set_cookie_params().
By default, the same session will be used for the current domain and all the paths on that domain. Thus it is readable for both blahblahblah.com/ and blahblahblah.com/login/
When the user logs in, save the username and the hash of the password in the Session.
At the start of each script, verify the Session's username and password with the one in database. If is correct, then set a flag (e.g. $userLoggedIn = true) to indicate on server-side that the user is logged in. else false.
Some thoughts, in no particular order:
Separate out the various layers: persistent storage vs authentication.
PHP sessions are quite robust and are the recommended way to maintain persistent storage.
You can have a valid session, but not a valid login.
Avoid multiple cookies. One is enough. PHP sessions work with one cookie.
You can set sub-domains and paths on cookies, but there's really little point unless you set lots, which is not recommended (see above).
Put everything you think you might want in a cookie in the session instead.
You should have some common code that all your pages include. That is where you initialize your session. Then everything will Just Work. It can also verify the login is valid, too.
Have one place that does the login authentication and everything associated with that.
Don't forget a logout screen!
Its a good idea to have one script do the session/login check and include it in the secure pages. AS for the depth , you can define that in the setcookie() if the directory parameter is set to "/" then its accessible all across.
Generally its a good idea to use sessions instead of cookies , as thats more secure , but you can decide to build your own session system based on encrypted data in the cookie and that can work too , but again sessions, which store data on the server side are recommended.
The cookie is per domain, so no matter how deep you are in your directory structure, the cookie will be read OK (as long as your domain stays the same - NB this means that www.example.com and example.com can be different cookies).
I'd suggest having an authentication check that compares the session ID in the cookie with eg a database table listing logged in users and their session ID - this check can be in its own method/include file that is include()'d on each page. That way the check will be performed on every page load. NB this is basic and there are much more secure methods - some of which have been mentioned in other comments here.
As Mauris said though, nothing is safe on the client side - don't use a cookie to store a "logged_in" value which you check for true/false!