Is safe to rely site security on $_SESSION? - php

I always set several vars on $_SESSION array to control access on my sites, but I would like to know if this is a safe solution or there would be something better than:
($_SESSION['admin'] == 1) ? take_control_of_my_site : get_back;

Session data is maintained on the server side. You can rely on the data as long as
Your server is secure
You carefully validate any data that you place into the session.

Session is safe. Even the name of a session variable is safe and choosing another name will not increase security.
The problem in PHP is the session mechanism. It uses files by default which can slow down your site considerably and scales very poorly, and can potentially be insecure hence the suoshin php patch.
Using sessions from a database back end is much more secure, scales well, and keeps your session data safe (relies on database based security). If a hacker has your database, sessions are the least of your worries as they probably have all your password hashes as well.

Sessions are not inherently unsafe. There are risks, but they can be mitigated.
It is good to be aware of the risks, so that you can learn how to avoid them, but the one thing you shouldn't do is avoid using sessions altogether because of them. Sessions are a well-established tool, and used properly they are perfectly safe and secure.
In fact, it's pretty hard to write a useful web site that doesn't use some kind of session. If you don't use the built-in one, then you'll end up writing your own -- and in most cases, that really is a security risk. (I know of programmers who have become obsessed with the security risks of sessions, and ended up implementing far less secure solutions simply because they didn't want to use sessions).
It's worth pointing out that recent versions of PHP have made huge strides forward in terms of security. There were a number of features in old PHP versions that were genuinely bad for security; recent versions of PHP have made big efforts to deprecate and remove these bad features. You will note that sessions are not in that list. They haven't needed any significant security work. This should tell you all you need to know.
Sessions are stored by default on the server in plain text. This shouldn't be a problem, unless your server can be accessed by unwanted users. If this is the case, then your security is probably already shot, so it's not really an issue, but in the rare occasion that you might be worried about that, it is possible to get PHP to provide session encryption via the session_set_save_handler() function.

Related

Is there anything I need to worry about besides SQL injections and XSS attacks?

I'm finishing up my first "real" PHP application and I am trying to make sure it is secure. I'm kind of afraid that since I'm not an "expert" PHP programmer that I might be missing something huge, so I would like to give you some information about my application and hopefully you can tell me whether or not that is the case. So here we go:
I'm using a CMS to handle user authentication, so I don't have to
worry about that.
After discovering PDO shortly after starting work
on my application, I ported all of my code over to using prepared
statements with PDO.
I am escaping all form and database data (even stuff I think is safe) which is being output with htmlentities().
My application does use a session variable and cookie variable, but the function of both is very unimportant.
I have designed my form processing functions in such a way that it doesn't matter if the form were somehow altered, or submitted from off-server (i.e. I always check the data submitted to ensure it's valid).
I have done my best to make all error messages and exception messages polite but very obscure.
I'm forcing pages with sensitive information (such as the login page) to be served over https.
When I first starting writing my application, I didn't know about prepared statements, which is kind of a huge deal. Have I missed anything else?
OWASP maintains a list of the Top 10 Most Critical Web Application Security Risks (warning, PDF download). This is from 2010, but I think it still applies, perhaps even moreso now.
Injection and XSS are the top two, but you should certainly be aware of the other 8. If you are using an existing CMS, many of these may already be considered, but the more popular the CMS the more you risk running into vulnerabilities because of black hats trying to find holes in it.
If you are not storing critical data like credit cards, order history, addresses, and even emails, then I wouldn't worry too much about your site being affected as long as you are taking the basic precautionary measures (and it sounds like you are).
If you are concerned about security issues, a good resource is the OWASP - Top 10 Application Security Risks
The most important thing to take care in web applications(specially PHPs') is Data Validation of all the inputs taken from the user which are further saved in your database.
For a secure application, all the transactions should be done on HTTPS. For a secure cookie management Secure and HTTPOnly cookie should be implemented.
Some more points I don't see mentioned yet. Most of these are not related to code - I am not sure if you only wished for things related to code, but I'll mention them anyway.
Backups (user data). should be self-evident
Version control. If you have a big bug, you want to have access to the previous version.
Audit trail, alarms and logging. If you do get into trouble, how will you find out? Are you able to track down what happened? if you know something is wrong but don't fully know what, are you able to diagnoze the issue?
Hosting. Where are you hosting? Do you have adequade bandwidth and monitoring? What happens if you get DOSed? Are you able to block out unwanted traffic?
Caching. Can you change it if needed?
There's always one thing left. Availability :) There are three aspects of security:
Confidentiality (Noone can read what they don't have access to)
Integrity (Noone can change any data what they should have to and you have to be able to detect if it happened even so)
Availability (The data, application whatever has to be available)
You pretty much did a nice job and took care of the first two (credentials, prepared statements, htmlentities...) but none of them will help against a DoS attack. You should be able to detect if someone slaps your site and ban the attackers ip from your server. Although this can be done in PHP (still much better to kick the attacker at the first line of php than let them initialize the framework, database connections etv.) it can be done mre effectively in lower layers (for example: nginx/apache, iptables, snort).
However what you're asking for that usually comes to the matter of risk management. In a real application you're not able to be prepared for all the possible attacks, edge cases etc. What you need to do is classify all the risks by the probability and the impact ( http://www.jiscinfonet.ac.uk/InfoKits/infokit-related-files/Resources/Images/risk-matrix ). With this you can focus on the most important (highest) risks first and probably you can completely ignore the lower bottom part.
SQL Injection and XSS are the most prominent Hacking methods.
You are covered from SQL Injections if you use prepared statements.
Also, if htmlentities() on everywhere you display HTML you should be safe.

PHP and MySQL $_POST Security and md5() hash function

I am creating a information system that will handle financial information, contacts, etc. I am developing the site from complete scratch using object oriented programming (classes, functions, etc). A majority of the data will be from a MySQL database. Users will be able to get and submit data to the database.
I am already using the hash function to encrypt data such as passwords, serial keys. I am also using preg_replace() function for all other data going to the database.
What other security measures do I need to take to insure that submitting and getting data from the database does not compromise security?
md5 is a cryptographic hash function. once hashed, it cannot be "un-hashed" back to the original value (one-way) as opposed to encryption which is two-way (encrypt-decrypt).
for security of your data, consider these scenarios and ways of prevention instead of just encryption:
cross-site request forgeries (CRSF) - prevent using form tokens
SSL connection (the "httpS://") to prevent data interception in transport
hash salting to further protect (but not totally) hashed passwords from dictionary attacks. weak and common passwords are the targets in this case.
hashing is not absolute. there is a limit to how many combinations of letters and numbers in a hash. at some point extremely different strings may have the same hash value. this is known as a collision
hashes are prone to brute-force/dictionary attacks. although hashes are one way, one can create a string-hash dictionary, match the hash and figure out the string behind it.
cross-site scripting (XSS) which can include (but not limited to) cookie stealing, click jacking, etc.
SQL injection - ways to trick your SQL when forms are unsanitized
expendable session ids to track user sessions - which should expire in a given amount of time, hence an auto log-out mechanism.
identify your user! user ip address, browser detection, etc to profile your user. any odd data (like sudden change in IP, location etc.) should be considered within a certain threshold. (facebook has this feature. i once accessed my facebook using a proxy - auto lockdown)
preg_replace() will not do much in terms of security. You should familiarize yourself with some basic security/crypto before doing this work. Also, consider the use of a standard cryptographic library for encrypting/decrypting data instead of arbitrarily using hash or regex functions.
Take a look at this: http://php.net/manual/en/book.openssl.php
First: good for you for giving attention to security issues. It's a big subject and one that many people overlook until it's too late. So, kudos to you for seeking more understanding about best practices. :-)
OWASP is a good resource for understanding web security issues.
Another good resource is the SANS report The Top Cyber Security Risks.
Specifically, Cross-Site Scripting (XSS) and SQL Injection are the top two security risks for most websites. You should read about how to design your code to minimize these risks.
I have also designed a presentation SQL Injection Myths and Fallacies that goes deeper into the nature of this issue and methods of defense.
Read the blog You're Probably Storing Passwords Incorrectly by StackOverflow founder Jeff Atwood.
I also cover SQL injection and password hashing in my book SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming.
Hope you have good liability insurance if you are using md5 to secure financial information. Read about md5, http://en.wikipedia.org/wiki/MD5, paying close attention to the line
The security of the MD5 hash function is severely compromised.
You are doing it wrong, because:
md5 is considered broken,
preg_replace() will not give you much.
Consider using already developed, tested and secure frameworks (candidates include Zend Framework, Symphony, Kohana, Yii) for your system. You have a long way before you will achieve security at least nearly as good as standard framework's. Also consider using prepared statements instead of preg_replace() and salted sha1 instead of simple md5, if you still want to reinvent the wheel.
Furthermore:
secure your app against such acronyms as XSS, CSRF,
require SSL at all times (for every request, even for images / styles / scripts),
read security newsletters (you will need them if you want to build secure system for financial activities).
As others have pointed out, md5 is broken. Also, a SHA1 hash is very fast to compute which actually makes it worse as a hashing algo. Instead look at bcrypt. Assuming you're using PHP, the http://www.openwall.com/phpass/ is very a nice password to use that handles hashing and salting for you transparently.
Using preg_replace() for escaping data to the database is a very bad idea. Almost all databases include their own sanitization functions, PHP/MySQL is no exception with mysql_real_escape_string().
Some more points (please note none of these are set in stone):
Sanitize all input
Assume that everything the user sends to your server is designed to cause harm. This includes form submissions, but also URL routes, cookie values, server vars, EVERYTHING. Using a framework will often provide some insulation from this, automatically escaping a lot of data for you.
Escape all output
Assume that everything you display on your site is designed to cause harm. XSS and CSRF are amongst the most common techniques for attacking websites. Escape all text that you output to the browser. Look into using nonces to mitigate attacks.
Use TLS/SSL
If you want to protect your users data enroute, get yourself a signed SSL certificate and set it up. This allows visitors to go to https://yoursite.com securely (or at least more securely if they're the kind of person who does internet banking on coffee shop wifi).
Use a framework
Everyone begins by writing their own framework because they know how to do it right, or don't need the extra complexity or whatever reason they come up with. Unless you're writing a super-specific-niche-application for which PHP probably isn't the right answer anyway, use a framework. I prefer http://kohanaframework.org/, but there's a whole range out there from http://codeigniter.com/ through to http://framework.zend.com/. Frameworks handle session encryption, database escaping, input sanitization and more for you, and because they're used by many people the chance of a bug is much less than code that only one person has worked on.
Secure your infrastructure
This one tends to fly by most people, but make sure you take some time to look at the server(s) you're running on. Are you on a shared account? You don't want to be storing financial information on them then (in some countries it's even illegal too). Apply security patches for your OS/software, make sure you haven't left an old upload script lying around, check your file permissions, use SSH with keys and turn off password logins. Attackers are always looking for the easiest way in.
At the end of the day, the only way to stay secure is to sleep with one eye open, totally paranoid. Watch your logs, install Nagios and set-up some alerts, hire a professional to do a security audit. There's no such thing as 100% secure, but knowing that is half the battle.
I am an experienced PHP developer and I want suggest to you to take a look to this project OWASP_Development_Guide. Every web developer should be use it as a bible. It has been very useful for me and I hope it will be the same for you.
Here a brief description of the document:
The Development Guide provides practical guidance and includes J2EE, ASP.NET, and PHP code samples. The Development Guide covers an extensive array of application-level security issues, from SQL injection through modern concerns such as phishing, credit card handling, session fixation, cross-site request forgeries, compliance, and privacy issues.

Is a PHP session secure?

Now I don't care about data transmission - no man-in-the-middle, that's work of http and https.
As far as I know PHP identifies sessions with the http cookie. But what happens if anyone tries bruteforce guessing session ids?
Its safe to assume that nothing is secure..
http://en.wikipedia.org/wiki/Session_hijacking
https://www.owasp.org/index.php/Session_hijacking_attack
http://www.serversidemagazine.com/php/session-hijacking/
Andreas Bogk made some very reasonable recommendations about a year ago to address a cryptographic weakness in the session key generation logic in PHP versions 5.3.2 and earlier that made PHP sessions more vulnerable to "session hijacking" (which seems to be your primary concern) than they ought to have been.
And Przemek Sobstel wrote a generic catalogue of attack types (including session hijacking) targeting the PHP session mechanism over 4 years ago, along with suggestions for mitigating them. The latest PHP version has changed several times since then, as has the "threat landscape". But the attack types have not changed much since then, and neither have the recommended best practices.
If you want to quantify your risk exposure, then you're going to have to define your scenario (implementation, environment, etc.) more precisely.
But what happens if anyone tries bruteforce of guessing session ids?
they would be aging...

Hashing a session fingerprint really necessary?

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.

Why not use PHP's built-in session handling?

Is there currently - or has there ever been - any serious or significant problem with PHP's built-in session handling?
I mean, it's always worked for me and my projects.
But I see some codebases and frameworks out there seem to use a custom handler. Is this reinventing the wheel? Or improving on some flaws? What flaws?
Pros and cons of PHP's built-in session handler
Pros:
Easy to use (just use session_start() and you're done)
Available OOTB.
Cons:
Uses only SESSID (or SID, SESSIONID, etc.) cookie to recognize user. That's not much, and this information can be easily stolen using XSS attacks or something like that.
In most cases you aren't able to do things like get total count of active sessions (often used in Who's online? features)
Pros and cons of your own session handler
Pros:
Works in the way you want it to work
Total control over how do you recognize users. You can use cookie, IP address, browser signature to make sure that stealing session is impossible (or at least it's much harder task).
You can chose the place where the session data is stored (database/filesystem)
You've got control over session mechanism as a whole
Cons:
You have to spend several minutes to create a such handler
Is there currently - or has there ever
been - any serious or significant
problem with PHP's built-in session
handling?
No problems with the built-in handlers. Access and deletion of old session files are implemented well.
Is this reinventing the wheel? Or
improving on some flaws? What flaws?
File based session handling works fine for single server websites. Problems may arise when applications need to be run on multiple servers (scaled out). A master database can be used to store and provide session information across multiple servers. This can make things easier when an application is scaled out. Custom session handlers can be used to interact with the database.
One of the major advantages of overriding the session behavior is being able to persist the session information into a database. When that is combined with user authentication it can become a powerful tool.
It really opens up a whole new set of possibilities:
Build session management tools for site administrators
Audit trail of a user's session data.
Ability to lock a users account and easily kill active sessions
etc.
A reason to roll your own session handlers would be implementing a single-sign-on system, or session sharing with other applications (= validation of sessions by a Java/CF/whatever application).
Sessions can only be up to a certain size no?

Categories