Security questions about cookies and javascript - php

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

Related

Cookies signing with hash to validate integrity. Good idea?

I would like to know if it is a good idea to sign cookies with hash to check it's integrity? First of all, I do realize that I should not store any sensitve data in cookies and use sessions instead. That's exactly what i do. But still I am feeling not comfortable with user being able to modify even not so important data. (I'm kind of security paranoic :) )
I came up with the following solution. Let's say we have cookies for:
PHPSESSID
site_lang
recently_viewed
Now whenever I update cookie value I recalculate hash for cookie with key of let's say cookie_hash and value of let's say md5(serialize($_COOKIE)+$secret)
the only thing that I am not using PHPSESSID for calculation and validating hash because it is not being managed by CookieManager class (my custom class) and might be refreshed with new session id and corrupt hash.
My concern is what if some third-party package sets it's own cookie bypassing my CookieManager of course. it will collapse hash. So is it a good idea at all?
MD5 is weak for this, and the scheme you proposed (hash(data||secret)) is flawed anyway. Cryptography is hard, please don't try to come up with your own. :)
What you may be looking for is invented already, it's called message authentication. Have a look at things like HMAC, which is one proper way to do something very similar.
In most cases, authenticating cookie values doesn't make sense in a web application and provides no additional security, but there are cases, when it does. Your examples above don't seem so. :) For example the session id is cryptographically random already, and the other two usually present no harm if changed by a user (but in very special cases, they probably may, though I can't come up with a reasonable example). If something matters and should not be changed by the client (user), that should probably be stored in a server-side session.
However, you may decide to store application state on the client in encrypted and/or authenticated cookies, one reason for that may be a stateless application on the server (see the default session management in Ruby on Rails for example), and in that case, something like your idea (but done correctly) is indeed the solution, but it has its own set of risks (as do server-side sessions).
Note that anytime you store state on the client, one threat that comes up besides secrecy and authenticity is replay. This affects your idea as well. Say it is a problem in your application if the user can change the last_viewed cookie, but you still don't want to put it in the session. You properly authenticate the cookie, maybe even encrypt it, the client has no access. But what if at some point, the user saves the cookie, and in a different session replays it? (Okay, your example tries to protect all cookies at once, which may make this a little bit more difficult, but you get the idea, replay is still a potential problem.)
So in short, you most probably don't need this, but if you do, then use proper message authentication (something like an authenticated encryption, or a proper MAC like HMAC).
I don't know how deep you digged in PHP and Webdevelopment, so please forgive me if the level of my answear is to low.
If you are paranoid you should read more about PHP, sessions, cookies, hashing algorithms and more.
For example:
PHP session handling
PHP session configuration
PHP session security
With this you can modify your sessions & your handling a little bit to serve your paranoia.
By the way you shouldn't use something like md5 in reference to make your web application more secure.
If i understand what you want to do, you want to write a hash of your serialized session array plus a secret/salt into the session to verify the integrity of the session and its data.
If this is your motivation, you really should rethink, at least in my opinion.
A session is just a file on your server (on the users system it's a database entry in a sqlite database of firefox or something else, but without the data you write to the cookie array, that data are just writen to the server) and the session ID is a file name/path to this data on the server, except your sessions are saved on a database.
So with your approach you would just save the value to verify the integrity of the data in the same data (on the server) you want to verify.
And where you want to save the secret?
I think it's a little bit useless.
Depending on your needs and the needs of your application you could search about the key word session TAN, you could set a additional cookie with a random value you save on the session to verify each other, you could save and check the IP (depending on the law of your country and the way your users connect), shorten the session lifetime and more.
You could also set ini directives like session.cookie_httponly (that's one i recommend if you don't want to access your session cookie by a script language like JavaScript) you can find on the links above and more.
Something is a matter of faith, something evident.
Digg in deeper and understand how the technology works under the hood and you can make your decision more easy by yourself.

Can a user manipulate cookies?

I have a question regarding usage of cookies for standard login purposes. Say my php script saves a cookie into a users computer each time he logs in. The cookie value is say "Mike" after his username at the website. Can that user somehow manipulate that cookie in his browser to change the value to say "Admin" so suddenly he has access to administration of the website?
If this could happen how to solve such security risk?
--
Additionally... What if someone was to copy cookies from my browser, either he would stare at my computer screen and copy cookies and values into his computer or such intruder could steal cookies from my browser via JavaScript.
How is that taken care of?
Yes, that is a security problem, which extends to any information provided by the client.
Cookies are stored on the user's machine. They can be modified in any way. In fact, the cookies can just be created on the fly and sent via several utilities for making HTTP requests. It isn't even a browser problem.
Never trust any data that comes from the client.
Yes, a user can manipulate cookies if they're stored on their computer.
Use a session.
A 'session' is the server-side storage of connection-relative information that is linked to the user through a variable which is passed back and forth, most often a cookie, however logically, anywhere will do if both your client and server can handle it.
This 'session' is often represented by an integer which the client and server both know.
The problem is, if another client has a session open on the server, we (as a client) could 'hi-jack' this session by replacing our given id with a random id until one is found. The server would now believe we are in fact the other use and could give us access to their private informatin.
For this reason, we have 'keys'. A key is a unique, often alphanumeric, code which is changed on each request-response pair with the server, ensuring that only those who have the latest key are able to gain access.
YES
They can manipulate, edit, modify, create and delete cookies.
You should only store a hash key that you use on the server to look up in a database anything that should be secure.
Yes, users can manipulate cookies. The best way to handle it is to not store user credentials in such a manner that they can gain admin access by changing their user name.
The specifics on how to do this are pretty deep, but a good start would be to just store the users's session identifier instead. That has its own issues, but won't let people break things quite so easily.
Cookies are clientside which means that they can be read, write and delete by the client. A cookie manager plugin makes it easier to change the cookie value.
http://www.ehow.com/how_7149468_edit-cookies-computer.html
Yes a user can easily manipulate the cookies by just going to cooking option which all popular browser provide

How exactly does session hijacking work in PHP?

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.

Session hijacking from another angle

I have been working on a secure login/portal type set of tools, the general code is free from SQL injections, XSS etc, I have mulitple things in place to stop session hijacking.
regenerate session's ID for EVERY page
Compare the user's IP with the IP at login
compare the user's user_agent with the agent at login
have short session time outs
etc
I have done all I can think of to stop hijacking, however I have still located a situation where it might be possible and would like to know if anyone has any ideas.
Imagine a situation where you have 2 users behind a firewall which does SNAT/DNAT, so both apart to come from the same IP. They are both identical machines supplied by the same place. One connects to the site and logs in, the other copies the PHPSESSID cookie and can simply steal the session.
This might sound like an extreme example, however this is very similar to my place of work, everyone is behind a firewall so looks to be the same IP, and all machines are managed/supplied by the IT team, so all have the same version of browser, OS etc etc.
I am trying to think of another way (server side) to stop the hijacking or minimize it further, I was thinking of a token which gets embedded into every URL (changed for each page), and checked.
I am looking for ideas or suggestions, if you want to offer code or examples you're welcome, but I am more interested in out of the box ideas or comments on my token idea.
Force everything to use HTTPS.
I think you are referring to a passive attack where a user in the network sniffs the cookie. For that, you don't need HTTPS. There are several options that are sufficient when the parties are sure to whom they're talking (e.g. you could do a DH exchange first and the server would encrypt a token the client would use in the next request...), but it's not worth the trouble going down that route.
If the user initially types in a non-https address, an active attack is still possible, but there's nothing you can do in that case. In the future, you might prevent future attacks of this kind once the user establishes one unadulterated connection to your site through HTTP strict transport security..
I wrote the main login portal for a major branch of the U.S. military.
I did all you mentioned above, plus at least one more step:
Have you stored a cookie on first login w/ the SESSION salt? Then encrypt everything serverside using that salt. The crooks would have to know about THAT cookie and STEAL IT, and it dramatically reduces exposure to session hijacking, as they just aren't lokoing for it.
Also, use JS and AJAX to detect if they have flash installed and if they do, store a flash cookie, too, with another salt. At that point you can more or less assume you have some pretty dedicated attackers out there and there's not much more you can do (like sending your users GPG keys to use via javascript and make them sign every single bit of data they send to you).
Do not reinvent the wheal, the built in session handler for your platform is very secure.
There are a number of configuration for PHP's session handler. Use HTTPS, at no point can a session ID be transmitted over http "cookie_secure" does this, its a great feature but a terrible name. httponly cookies makes xss harder because javascript cannot access document.cookie. Use_only_cookies stops session fixation, because an attacker cannot influence this value on another domain (unless he has xss, but thats a moot point).
PHP configuration:
session.cookie_httponly=on
session.cookie_secure=on
session.use_only_cookies=on
I am trying to think of another way (server side) to stop the hijacking or minimize it further, I was thinking of a token which gets embedded into every URL (changed for each page), and checked.
You should look at:
Understanding the Rails Authenticity Token
Tokens are a good idea.

Cookies/Sessions login system

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 ;-)

Categories