A user logs in using default Laravel authentication, which puts an encrypted cookie in the browser, and saves the session in the database.
The user moves to a classic asp page, where I check the cookie value, get the hash, and call the laravel app back passing the session id hash.
Then I use that in laravel to see if there's an active session for that id, and if so I return true, so the user can be logged in, in classic asp.
On each page request in the classic app, I check the last_updated_time in the db and update it on each page. All logging in and out is done in laravel, and classic relies on the database to see if a session is active.
I would also call a public url to get sessions variables and add session variables using laravel, since it's all encrypted and using classic asp for this would be hard.
The only risk I see is session highjacking, but I don't think it's a higher risk than usual.
Is it important to lockdown the laravel URL I call to check if it's a valid session?
Am I missing a security hole here?
Is this method secure?
From what you've stated you probably haven't opened up any security holes. The session cookie is not itself encrypted on the users machine, but you are making sure it is encrypted between their machines and yours, as well as between each of your machines. You should make sure you've set the Secure Flag to help prevent the cookie being accidentally sent over traditional unencrypted transport (HTTP), but as stated, this doesn't effect storing the cookie itself.
That being said, you are essentially hijacking your own users sessions. While a hole might not be introduced now, you are potentially weakening the overall system, which could lead to hole in the future.
Is there a better way to do it?
This might well be a dumb question, but are you sure you need the session? If you're juggling credentials between servers, it sounds more like you want to use Access Tokens and scrap the session.
Using Access Tokens is similar to using sessions, but you need to make your services stateless. This means your no longer storing information about the logged in user any specific machine so you'll need to pull anything you need from the database every time they hit a server requiring that information.
This is a good thing in the long run as it's much easier to scale your services when you don't need to worry so much about where the session is and what's inside it.
OAuth 2.0 is widely used standard (Facebook, Twitter, Google), and was specifically designed to be easy to use. The RFC is complex, but there's a log of good guides out there don't worry.
The one slight down side (if you can call it that) to OAuth 2, is that it MUST happen over an encrypted connection. If your use case can not guarantee encryption over SSL or (preferably) TLS, then you should use OAuth 1.0 (WITH revision A) instead.
This is due to the fact that OAuth 2.0 exposes it's "secret" token in requests, where as OAuth 1.0 only ever uses it to provide a signature hash. If you take this route it's advisable to use someone else's library as the hash is very, specific.
Further Improvement
(Note: This section added after the answer was accepted)
One system I've been exploring recently is Json Web Tokens. These store information about the user to save each machine repeatedly looking it up in a database. Because the token is hashed with a secret, you can be sure that, so long as your secret isn't exposed, a valid token represents a successfully logged in user, without having to touch the database.
You should avoid putting anything too personal in the tokens if possible. If you must store private or secret information in the token, you can encrypt it, or you can use a reverse caching proxy to exchange the JWT for a traditional security token. This may initially seem to defeat the purpose, but it means some of your services may not need database access at all.
I'm no security expert but I don't see an issue with this. The packaged Laravel database session handler works the same way. The cookie contains a hash that references a record in the database. The session data is base64 encoded but that's neither here nor there. I think you could actually avoid rolling your own and just use Laravel's DatabaseSessionHandler.
Illuminate/Session/DatabaseSessionHandler
... I just read a little deeper into your question and noticed the part about the public URL to set and retrieve session data. I think this is a really bad idea. Mostly because it will provide an open door to the end user allowing them to read and write session data. This can only end badly.
Like I said above, the data is only base64 encoded so I believe you'll be able to parse, read and write that to your hearts content within asp.
Edit
Ok... I think this is the last edit. The data is php serialized and then base64 encoded. This question looks like it may help you to that end. If it doesn't and an API endpoint is the only way, find some way to block the end user from accessing it.
Aside from session-hijacking, no. This is the standard way applications interact on a internal basis. Of course there might be a better way to get at the data if you choose a different type of session store other than your database, Memcached for instance.
There are couple of things that can be done.
Make the channel HTTPS. It will make almost impossible to sniff on your transport layer.
Rather than making interactions with your cookie, you could use a JWT to get this task done. Which will help you to use the existing functionality in your system while connecting with ASP system as well. You can write a small REST web service which allows ASP to connect. You could use this lib. You can refer this article which will give you an idea how it should be done.
Please let me know if you need more information.
Related
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.
I'm creating a server(PHP) to store data from android app. With POST query store name, password and email. These data as mentioned are stored on the server (database on hosting).
But I have a lot of questions how to do it correctly:
First is the backend, how to protect data and how to encrypt them?
I know that you can transfer token of android application on the web (server). And there it checked for accuracy, but android application is easy to decompile. How to be in this case?
Also heard of RSA but examples show how the mechanism works. And when used in RSA, I have the private key stored on the server and the public in android application? But what if I we obtain encrypted data from the server on android? I need to decrypt them using the private key. But the key on the server and store the private key on Android ill (paragraph 2, decompiling).
Other...
Please leave comments. Also describe every paragraph of my question, and it is desirable for each paragraph post a link with useful information. Also, I would appreciate any HELPFUL links related to this topic, well, especially your opinion and how best to do it.
I assume that you are trying to create a basic register/login-to-use-this-app mechanism.
Read the PHP FAQ article on password saving on why and how for secure data saving server-side. Basically, to hash (to irreversibly encrypt) sensitive data before directly saving them.
Regarding your second question,
Generally, it is not a big concern on directly transmitting sensitive data between client and server, because there can be these security measures:
Use HTTPS. This will encrypt the stream of data transmission, and it is less vulnerable to the connection being eavesdropped.
You may want to directly send the hash of the password instead of the password itself in the post request, or in other words, use the hash of the user password as the password.
Client frontend
In terms of internal storage, it is not possible to prevent other installed malicious apps from reading and using data you store, unless you (I am not familiar with this) store them in a storage that is only accessible by your own app.
Server backend
There are some servers that distribute OAuth tokens to clients, such as GitHub. However, if you only expect the server login API to be used by your own apps, OAuth isn't necessary in this case, since it is mainly used as a flexible permission bearer which you don't need to concern for your own app.
Instead, the more important thing is how you handle things server-side. For the web API that I once coded for my own server, although I don't expect others to use it, I made the API designed as if it is for the public to use, and pay attention to unexpected client input. This is because clients can be fake anytime, so never trust the integrity of what clients input. (Forgive my obsession, but I even considered backend of my JavaScript on webpages as "clients" to be safe)
I have never used nor have any comprehensive knowledge on other PHP frameworks, but when I work on my website, I would create a safety layer within my own backend code. I separate my backend into two levels, namely the database level and the interface level. The database level should try not let the interface level even get the data that are not supposed to be known by (the current authentication state of) the client, so as to minimize the chance of security vulnerability.
Client-server communication
So this only leaves the problem of data transmission, which is the main point of this question.
As mentioned above, HTTPS would be good enough to encrypt data transmission.
I do not know if this concept is practical, but after initial registration, it might be, if you are obsessive enough, possible to encrypt the data with a timestamp, etc. I am not quite sure about this, but disconnected tokens inspired me on this.
But how much protection you need still depends on what kind of data you are sending. For example, if you are simply tracking user usage, you don't really need a lot of protection for it. Just make sure that the user's original password cannot be leaked by hashing it.
I've created a forum which uses a PHP session when logged in to determine the user id, and cookies for log-term login.
I suppose I have two questions:
Is this the best/securest method?
Cookies can be added manually via the address bar with javascript, which is a huge security risk. Is there any way around this?
Thanks!
First, make sure you are using https and not http. This will keep your traffic from getting sniffed and exploited.
Secondly, generate as random a value as possible to use as a token in the cookie. This is how many of the big sites do their user tracking. Have a map of token to user on the server side that tracks the identities. Remember: Anything that comes from the client is untrusted and could be tampered with.
Third, use an HMAC to make tampering much more difficult. You don't want users being able to brute force other tokens.
EDIT:
You may find these other SO questions/answers helpful as you build this system:
Long details about creating and using tokens (doesn't necessarily have to be a REST service to be applicable): REST Web Service authentication token implementation
Creating good tokens (don't use microtime): Is using microtime() to generate password-reset tokens bad practice
Please read this THOUROUGHLY before voting...
So I have seen a lot of session management classes that create a fingerprint via concatenation of user agent and a couple of ip blocks or whatever. They seem to also add a salt and then hash this fingerprint before storing it in a session variable.
This fingerprint generation typically happens every request in order to verify that the current user of the session is in deed the original session user. This is why I am wondering, is the salt and hash really necessary on something like this?
If a hacker can get onto your filesystem to see your session file contents, aren't you already hosed at that point?
Any info greatly appreciated.
Most of it makes sense, but the hashing and salting makes no sense.
If you tie the session to an IP address, then it becomes a lot harder to hijack into a session. This is something I recommend doing, but you don't need to be utterly strict about it. You can just tie to the first three parts of the IPv4 or so. The choice is yours. The more strict IP check the more secure it is, but the less convenient it is for users.
And as for tying the session based on the user agent, that may also help. It must be realized that if you work on an unencrypted channel (HTTP for example), then the user agent check is less useful as it can be reproduced by the intruder as well.
When it comes to salting and hashing, that is useless. They add no strength to your identity checks. The only thing they do is complicate your design. For this matter, I believe they lower your level of security.
As always, a few rules to keep in mind:
Use strong session identifiers. This means use good random sources and make sure there are enough bits.
Tie the session to an IP, at least to some extent.
Tie the session to a user agent, if possible.
Use SSL/TLS. Without it, theoretically all session systems are insecure.
Secure your session storage. Whether it's filesystem based or database based.
I can think of two cases where it would be useful:
When the session data is stored client-side. (Like in a cookie.) So, I'd be prevented from taking my cookie to another computer, and I'd be prevented from making up my own cookie contents. (Ok, so this is not a very likely scenario...)
When the session data is stored in some shared server-side resource (i.e., /tmp) and is vulnerable to snooping. In this case, if the snooper is able to see the contents of the session, they'll still be unable to fake a connection to that session because they don't know what data went into the fingerprint.
In complement to the response of #Kai Sellgren (+1) which contains some good hints on how to secure your session storage I would add some ideas than can explain the hash & salt on some specific applications.
I'm not talking of application that are using the cookie as a session storage, we still see this for example on Prestashop eCommerce solution, with encryption of the cookie content (why the hell did they decide to store the session on the cookie?). I understand we talk about server side session storage.
The key point is layered Security and in-depth defense:
Compromissions are never boolean things, your are not 'completly compromised' or 'completly secure'. One of the the real history I like about that is the mySpace worm explanation, it shows a real attack and how defensive steps must be break. There's always a new wall. Just one example, I share the same IP as my boss when i'm in the office, and maybe the same browser, this could break a security based only on IP+user-agent.
So in the hash & salt of session stamping we are clearly acting after a few walls have fallen. And kai shows us some of these walls. When he talks about securing the session storage I would add 2 things:
it's a really good idea to alter the session.save_path and the open_basedir of each PHP application (and get a separate Virtualhost for each). Rarely done.
if your application is installed on a path (like /myapp), add a prefix_path on the session cookie (and fix it for any other app on the same server)
Now Let's imagine a realistic compromission. You've several ways to compromise the session on the server side:
The application is running on a website with some other applications running in other paths (or in other domains in the same server). And at least on of theses applications is quite unsecure. At worst server side code could be injected in this app, but some of the security walls (like open_basedir or other chrooting techniques) may prevent this injected code from affecting your separate application (or data).
Some of the javascript libraries comes with some test subdirectories containing highly insecure scripts, with not only nice session disclosure but maybe some session fixation or prediction available.
The application is shared, and talking about wordpress-like softs you can imagine some platforms sharing a lot of different installations, with different modules and maybe some custom code. On such platforms you'll find settings to allow altering the salt for each consumer, there's a reason for that. One of the website could impact the security of others and clean separation can be harder to do if the applications wants to manage the websites all-in-one.
Your targeted application may get hit by the environment, if the session storage can be shared with some scripts from other application, or from a script in your own application that you did'nt even notice (like these f*** examples in javascript libs, why didn't you suspend php execution on static file directories!)
From this first step of compromission the attacker could potentialy (and in severity increasing):
read the session stamps and maybe find which information he should fake to get the same stamp
build a new session containing a session stamp valid for his configuration, and then use this new session identifier on your application. Your application will find the session file, and accept him.
alter one of your valid session to modify the stamp in the same way
A simple hash of the stamp would make his life harder, but it would just be a wall to break, the salt make this wall really harder to break.
One important point is, from your question, if a guy can alter something in the session storage am I already in a bad mood?. Well, maybe not completly. If it is the only thing the chroot/separation/securization of applications allows him to do this salt will be a nightmare for him.
And the second important point is: should I do this level of in-depth security on every web application?. Answer is no. Overengineering is a bad thing and can reduce the security of your application by the simple fact it became harder to understand and maitin. You do not need to complexify your application if:
you've got a pretty good level of session storage separation
you're alone on your server, only one application, and not any sort of multisite handling
your application security level is so weak that a simple code injection is available on the application, so a session fixation is not needed for an attacker :-)
I can imagine that the point of hashing that fingerprint information is storage space as the resulting hash has a fixed length.
But to also use a salt doesn’t make much sense to me. Because, as you’ve already said, since that data is stored in the session data storage location, you would already have a bigger problem than session fixation/hijacking if someone would be able to obtain that data.
You can find a plausible solution here:
http://shiflett.org/articles/the-truth-about-sessions
Fingerprinting combats session hijacking.
The attacker not only needs your session_id, he also needs any sensitive HTTP headers.
It adds another barrier for the attacker, albeit one that can be easily overcome.
The hash is there to make the data uniform. The salt is there to obscure the hashing process - so an attacker can not generate a valid fingerprint for his own combination of HTTP headers.
If a hacker is in your filesystem you have bigger problems :D
A lot of people who don't understand very much about security combine bits of advice floating around the internet in the hope that what they end up with will be "good enough". Tying the session ID to the U-A breaks browser upgrades (which Chrome does fairly often) and tying to the IP address breaks mobility (anyone with a laptop that uses Wi-Fi), and many ISPs don't have contiguous allocations. Anyone who can sniff cookies can also sniff the U-A, and will probably have access to the same IP address because they got the cookie off insecure Wi-Fi behind a NAT.
What you probably do want to do is change the session ID on a login attempt, which is a reliable way to prevent "session fixation" attacks (where the attacker makes the victim load http://example.com/?SESSIONID=foo e.g. through an <img>, waits for you to log in, and now knows the victim's session ID). There is little reason to preserve a session across a login, and you can copy the few things that need to be preserved (e.g. a shopping cart) across.
If a hacker can get onto you
filesystem to see your session file
contents, aren't you already hosed at
that point?
If you are using PHP as CGI (like in the case with nginx), then I think no. If you set permissions right then your session files must have read/write permission for PHP user while your PHP files should have only read permissions. So, if you pass the salt from the web server to PHP, then PHP user can't get access to it (he can't create any new/change existing PHP files that can be run by your web server and he can't access web server as it is run on another user), so he can't really hack(change) cookies (only delete them) because he can't get salt. Of course you will have to pass database settings from web server as well.
I never really tried it, so please correct me if I am wrong.
is the salt and hash really necessary on something like this [http client fingerprint]?
The hash might be useful to reduce the number of bytes consumed by the fingerprint inside the session data. So as long as the hashed fingerprint is of a smaller size than the fingerprint itself this can make sense in terms of space reduction. Price is the consumption of system resources to generate the hash.
Does it really make sense? You would need to benchmark this to say so.
How can a salt be helpful then? I must admit, I see no reason for a salt. It would only make sense to make it harder to guess the fingerprint from a hash. But as I do not see any security benefit in hashing the fingerprint (it's kept on the server-side only and is already considerably secure), salting is not adding anything.
In case the session store itself is not considered secure (if that's for the argument), the whole session should be encrypted, not only the fingerprint.
So particularly for the fingerprint, I do not see much use in hashing and salting it.
Currently I autheticatic user sessions by matching a key in the session to the same key in a MySQl database. I regenerate the session with a random number that is MD5 protected on every page load. I am aware that sessions are not inherently secure and I'm looking for further security options that can be attached to this method in a speedy manner.
Any Ideas?
Since the session data is stored on the server side and the session ID is used to associate a client’s request with a certain session, it’s the session ID that needs to be protected. And the only viable measure to protect that session ID is to encrypt the connection between the client and server using TLS/SSL.
So you can use sessions as long as the data transfer between client and use is secured. Additionally, you can fix the PHP session to the TLS/SSL session so that the PHP session is only usable within that specific TLS/SSL session.
You're already jumping through hoops which do nothing to enhance the security, and potentially compromise the functionality of your site.
I autheticatic [sic] user sessions by matching a key in the session to the same key in a MySQl database
Even leaving aside the spelling mistakes, this is nonsense. Do you mean you authenticate requests by this method? If so, it's still not helping your security. You've already authenticated the request by de-referencing the session. Whether the request is authorized is completely different - if you need to authenticate the user then you should flag this in the session data.
It sounds like you're trying to prevent a CSRF, but getting this all mixed up with whether you're authenticating a user, a session or a request.
I regenerate the session...on every page load
Again, this is semantic nonsense. You can't "regenerate the session". Do you mean you create a new sessionId? If so then all you are achieving is creating errors when users try to open a second window or use the back button. It provides very little CSRF protection.
is MD5 protected
Just using random cryptographic functions doesn't make your application secure. It doesn't matter what the mapping between the real data and a surrogate identifier is, on its own it provides no protection against MITM.
Either you've done a very bad job describing your current security measures, or you've written lots of code which serves no useful purpose.
Go and read a lot of Stefan Esser's and/or Chriss Schiflet's stuff.