What is the best way to secure an application with session vars? - php

I have an application with an index page, where the user can enter a login and a password. Then they are submitted as POST variables, and if they are both correct, my script creates a session var as follows :
$_SESSION['auth'] = $login;
and the index page echoes a menu. If they are not, the login window is displayed again, as if the user went on the index page for the first time (with an error message under the required fields).
For now, I verify if the session variable is set :
<?php
include 'functions.php'; //this file contains session_start()
if (!isset($_SESSION['auth'])) {
header("Location: index.php");
exit();
}
?>
<html>
Html stuff with jquery...
</html>
Do I have to put all my html stuff in brackets within an else statement, or my page is secured enough ? Even if the user is redirected, the html part is still got by his browser, isn't it ?
I have several PHP pages on my server, and at the beginning of each one I make the same test as above. I also make this verification when the user comes on the index page (if he has already signed in, I don't want him to log-in again).
Assuming my script is safe (all the information provided by the user is checked on server side), what is the best way to work with secure sessions ?

It's great you are thinking about security, but allow me to explain a little on how sessions and session cookies work.
First of all cookies only allow a limited amount of data stored in them, I forget how much but I know it's not limitless. So how do severs allow you to store all that session data. What happens is the actual session cookie only stores the session id. On the server there is an actual physical file that has the session data in it. So when a client connects they send the session id, which in turn tells what file to use. Therefor, the session is as secure as the severs filesystem and the algorithm used to create the cookie's id. No actual session data ( besides that id ) leaves the server.
That said there are 2 settings that might help ensure sessions are safe.
These are httponly and secure, you can read more about them here
http://php.net/manual/en/session.configuration.php#ini.session.cookie-httponly
Now the short of it is, secure means to only transmit the session data ( the session id ) over Https, this only works if you have https setup on your server and website. Httponly, tells the browser that the cookie should only be sent over http ( or https ) not by client-side scripting. However as you have no control over what browser the client uses, or if their computer has been compromised in some way that will tell the browser otherwise ( although I don't know of any exploits that might do that ) you really are just making a suggestion to the client machine.
Now as far as the security of the actual data, any input from anywhere even your own database should always be treated as potentially insecure. This doesn't mean you have to check it everywhere, mainly that you escape html when outputting to the page, and that you use proper means to prevent sql injection into the database. As a general rule these should be done at the point of entry.
For example, when outputting content to a page that should not have html, simply use html_entities etc.. when outputting it. When using data in sql, use prepared statements there. You see you don't need to check the $_POST data every time you touch it, just check the data before using it for something that could be exploited, such as saving it in the database.
Lets take a small example function ( assume its in a user class )
public function getUser( $id ){
$sql = "Select * from user where id = $id"
//execute sql
}
We would never do this using PDO but lets assume this is old school stuff, you filter the data from a login form elsewhere, so when you set this up you assume its always a clean a id, because you filter it at the login form. Then latter you need a user from the session. Well you have the id there too, so you use it. Now is that id from the session clean, who knows right. Maybe it's an id from a file, or some other obscure place. Who knows where an Id can come from ( when we make the user class ). So what we do now-a-days is check that or use a prepared statement "at the point we use" the data, the point of entry. Then we don't care where the data came from. Because, it is always being cleared at the prepared statement, just before we use it in the database. That way it is always 100%, no question asked, clean. We can see it right there where we run the query from. We don't need to worry if we make a new login form latter. Maybe you add a pop-up login form somewhere? Dosn't matter, your sql will always be clean. Now, I am not saying not to check it at the login form. Never hurts to be safe, not to mention you might want to validate other things there, email format, uniqueness of a username etc. But, the critical point, is covered.
Make sense?
To address your comment about not using cookies ( I should have explained this at the beginning ). By it's very nature the internet is stateless. What this means is that every page reload is essentially a new connection. The only way to maintain a login ( or any data across reloads ) is to pass some data between requests. There is generally only a few ways to do this, they are
$_POST, $_GET, $_FILE, $_COOKIES. Notice how they are formatted, that's a hint, they are called super globals.
http://php.net/manual/en/language.variables.superglobals.php
By the way we have Netscape to thank for both Cookies and Javascript, both of which IE "borrowed", to me it's sad I don't see Netscape Navigator anymore. I remember that from the AOL 3.0 days, that was before you could embed images in email. You old timers know what I am talking about... Churr.Beep.bong.Cherrrk (various analog modem noises )... streaming video what's that, it's like 1.5 days to download a song. & Pr#y 2 teh GodZ of de inTerWeBz MomZ do4't g3t a [ call .... L33t BaBy >:-)~ ^v^

Related

Client access to Superglobals

PHP Superglobals behave in different ways and I'm never sure about which one to use.
When can the client (I'm not talking about hackers or security attacks, but "normal users") edit, create or access a Superglobal variable?
Even php.net documentation does not talk about this fact.
Basing on what I've learnt so far I can summarize them in this way:
superglobal read create edit
$_GET V V V
$_POST X V X
$_FILES X V X
$_SESSION ? X X
$_COOKIE V V V
I'm not talking about your PHP script which creates a SESSION variable when an user send a form or something like that, but I'm talking about the fact that anyone could add a fake form inside the DOM to POST anything or use a simple Chrome extension like EditThisCookie to read, create or edit any COOKIE.
So:
Is my table right? I'm not sure about some points and they are crucial for security reasons
Where should I store sensible data such as access tokens or user IDs?
I've always stored IDs inside a COOKIE because I can set its expire time, and then I figured out that anyone could fake them. If there's not a way to prevent it, I would be forced to use SESSION, with the problem that it expires together with the browser session (when an user closes its browser, he loses its login session).
Or sometimes I used POST method to verify that a call comes from a specific page, but then I realized that the client could read the content of that form and fake it from everywhere. Should I use SESSION for this purpose too?
Is my table right?
No.
With the exception of $_SESSION all of those superglobals contain data pulled from the request made by the client. The client can set the initial value (for a given run of the PHP program) for any of them.
The client can't read any of them. (They can read all the data sent by or stored in their browser and infer the data in any of those superglobals from it ($_SESSION still excepted), but they can't read the superglobals themselves).
The client can't edit any of them (other than by making a new request which would rerun the PHP program from the start).
$_SESSION contains data stored on the server. A particular session can be selected with the SESSION ID that is stored in a cookie and sent by the client.
anyone could add a fake form inside the DOM to POST anything or use a simple Chrome extension like EditThisCookie to read, create or edit any COOKIE.
Yes. Don't trust data from the client blindly. The client can send whatever data it wants in the cookies, query string or post body.
Or sometimes I used POST method to verify that a call comes from a specific page, but then I realized that the client could read the content of that form and fake it from everywhere. Should I use SESSION for this purpose too?
You probably shouldn't care.
(Tricking a third party into submitting fake data is another matter, but see this question).
Where should I store sensible data such as access tokens or user IDs?
Access tokens (providing they are tokens which are designed to give a particular user access to something and not (say) an API key that your server should use to access a third-party server) need to be stored on the client. The particular place depends on how you are going to use it. For the most part, a session ID is fine.
User Ids (assuming they are being used as evidence that the user is that user Id) need to be stored in such a way that they can't be edited to someone else's. That means either being stored on the server (in a session usually) or in a format that can't be altered (like an encrypted JWT on the client).

Is it possible to prevent php session from destroying when you close browser?

We want to use sessions instead of cookies for keeping track of a few things. However, when I close my browser, and I reopen a page to echo a session var, it doesn't exist (which is how it is suppose to be). Is it possible to prevent this from happening with some magic or anything?
This is not a duplicate question, all I see are people wanting to destroy sessions, I want to do the opposite and retain the session for as long as possible.
Any knowledge would be appreciated.
The right way of doing this is with a database, you can mimic or control php sessions and store them in a database instead of in a file ( as normal ). Then once you have control of the data you can base renewing session via the ip address or better yet by login.
So say a user logs in and then you need to store some data, you store that in the session but php will store it in your database table ( when configured correctly ). Latter the user comes back, initially any visitor would get a fresh session, however once they login you would be able to retrieve the past session they had. You generally don't have much control on if or when a client will delete expired cookies.
This topic is too extensive to put just a few pieces of example code but I did find this small article on the topic.
http://culttt.com/2013/02/04/how-to-save-php-sessions-to-a-database/
The guts of it is to use this function, session_set_save_handler
http://php.net/manual/en/function.session-set-save-handler.php
Once you have control of the data you can do whatever you want, however I would caution you about relying only on the IP address and it would be preferable to use a login system for something like this to prevent serving the session up to the wrong visitor.
You cannot reliably control what happens on the client side, even using a separate cookie would not be reliable and would have the disadvantage of storing data on the client where it could be accessed instead of keeping it on your server. Sessions are controlled by cookies but the data in them remains on your server, the cookie just identifies the client.
As a side note, I personally dislike using sessions at all. It may be possible to store what you need in the url, then it can be bookmarked. The classic example would be input for a search form ( via $_GET ) or for paging purposes. There is nothing wrong with doing this if it's not secure data. The problem with sessions is if the data is for a page such as my "classic example" or for paging you get only one session, so you would only be able to have one set of search data at a time, in the url you could have several sets of search data open at once. That said it does largely depend on what you need to save or persist.
Reset the session cookie manually.
$lifetime=60*60; // duration in seconds
session_start();
setcookie(session_name(),session_id(),time()+$lifetime);
You can use session.gc_maxlifetime and session_set_cookie_params, i.e.:
// server should keep session data for AT LEAST 1 Year
ini_set('session.gc_maxlifetime', 3600 * 24 * 365);
// each client should remember their session id for EXACTLY 1 Year
session_set_cookie_params(3600 * 24 * 365);
session_start();
Note:
You can also change the session options globally by editing php.ini -
Session configuration options
PHP sessions use session cookies. Browsers have their own ways of dealing with them but they all consider them to be trash if you close the browser.
Session cookies are not and can not be made persistent. If you need persistent cookies, just use a regular cookie to save a user identification code that your server would recognize, and save their session information in a database or flat file indexed on that id code.
Note that accumulating sessions on the server progressively causes important performance and security concerns.
Note on other answers: All of them mention ways to extend the session cookie expiration which will not overcome the regular behavior when you close your browser window.

Is passing session data from one PHP page to another efficient?

I was wondering if using a SESSION variable to pass data from one PHP page to another is efficient. I ask this because I thought that SESSIONS were only used to keep the user logged in to a website, and as an alternative to cookies. Would it not be better to pass data (non-sensitive) from one page to another via a URI such as members.php?name=Joe&age=28?
A PHP session writes a cookie to your browser and then stores the data associated with that session on disk; its about as expensive as an include() to read it back in on the next page load, which is to say completely trivial.
Additionally, the user can't change session data unless you create a mechanism which allows them to; they can mess with the query string easily.
Short answer: Yes, its efficient.
Sessions are useful for lots of things, not just login information. They're great for holding status messages during a POST/redirect/GET cycle or anything else that keeps track of the state of the user's session (hence the name) - but only the current session, not long-term permanent configuration options.
As far as efficiency goes, you need to remember that anything in the session needs to be serialized & unserialized on every page load. Storing a name and age wouldn't add much. Adding a megabyte of image upload would probably be bad.
More important than the efficiency consideration is to remember that session data is only temporarily persistent. If you want to always know that Joe is 28, it should go in the database. If it's only useful on a single page load, it should probably stay in the URL or be POSTed. If you're interested in remembering it for a few minutes, the session might be the place to put it.
Depends on what you're doing. If that page requires that information to function properly and is not behind a login then passing in a query string is the way to go (e.g. search results, product pages). If it is behind a login then using a session would allow you to keep your URLs clean and also make it difficult for users to abuse the page (e.g. swap out data in the query string).
Yes, you can store data and message in SESSION and it is accessible from any page. But remember, SESSION uses browser support to store data. They can be deleted manually by the user

Preventing mass form submits by $_SESSION

If I'm getting bombed by a .NET program created in C# - bombed as in the user is submitting the $_POST fields on my form in mass quantities... It's specifically my contact form.
I'm not sure how exactly the mass $_POST occurs in the .NET program or it even could be a c++ program, I have no idea. However I had an idea to counter this.
My first idea requires $_SESSION but... Would those $_POST bombing program(s) the user created handle/accept a $_SESSION? I really don't want to find out but maybe someone with experience with the WebClient class in C# would know if it handled $_SESSION'S or whatever it is the user is using. I was considering using $_SESSION['submitted'] = $count; and another part of $count++;
if($_SESSION['submitted'] > 5) {
//display captcha or block from site
} else {
$count++;
}
If the user's program didn't handle a $_SESSION is there anyway possible I can disable the site to them? So they can't attack my contact form?
Bypassing the session lockout is trivial for a malicious user. Just delete the session cookie after each POST and they get a brand new clean session with the limit reset.
The only secure way to block a user such as this is to start throttling their IP address. Limit it to a certain number of connection attempts per minute and they won't be able to submit than that many requests per minute. Now, if they can hop between hosts then you've got a bigger problem, and should probably look at moving your form elsewhere so all they get is a 404 (until they notice it's moved).
The downside is if they're using a common proxy or somethign like AOL which proxies EVERYTHING, you'd be blocking other legitimate users as well.
Well you can put some security barriers like a login form or some other form of authentication (like browser check or the like)
Aside from that the only think i can think of is to block the incoming IP, which then again might not be a good idea
Someone can correct me if I'm wrong, but SESSION stores a cookie (or some other way) with the session id (a very long hash string), The SESSION variables are stored on the server. So even if they handled SESSIONs they would have no control over the server stored SESSION variables.
If I were you, I'd set CAPTCHA to always be on...
What about just implementing the CAPTCHA?

How to use sessions in place of a querystring

Using PHP.. I have a small app that I built that currently uses a querystring to navigate and grab data from a database. The key in the database is also in the string and that is not acceptable anymore. I need to change it. I would like to hide the db key and use a session in place of it but I'm not sure how to do that. In fact, there are also other variables in the query string that I would like to use sessions for if at all possible.
page.php?var1&var2&id=1
This is what my string looks like. I am looping through the results in the database and have given each row the id so that when the user clicks the row they want, but I'm not sure how I could do this with a session.
Does anyone have any ideas?
Thanks
EDIT:
I'm developing an email type system where senders and recipients are getting and sending mail. Each piece of mail that is stored on the server will have its own unique key. Currently, I am using that number to retreive the message but the problem is that I don't want people to change the number and read other people's mail. I can probably use a GUID for this or even some sort of hash but I really hate long query strings. I was just thinking it would be so much cleaner if there was a way to "hide" the id all together.
UPDATED (Again ... Yeah, I know.)
Allowing access to a particular set of data through a $_GET parameter is much more accessible to any user that happens to be using the application.
UPDATED
For storing a private record key, you are probably going to want to use post data, and if you really want it to look like a link, you can always use CSS for that part.
Honestly, the best way to stop people from reading other people's mail is by having a relationship table that says only X person is able to access Y email (by id). That or have a field that says who is the 'owner' of the email.
The fact is that users can still get access to POST parameters, and can easily forge their own POST parameters. This means that anyone could realistically access anyone else's email if they knew the naming scheme.
In an ideal system, there would be a Sender, and a Recipient (The Recipient could be comma separated values). Only the people that are on one of those columns should be allowed to access the email.
How To Use Sessions (From Earlier)
First start off with calling session_start(), and then after that check for variables from previous scripts. If they aren't present, generate them. If they are, grab them and use them.
session_start();
if(!isset($_SESSION['db_key']))
{
$_SESSION['db_key'] = // generate your database key
}
else
{
$db_key = $_SESSION['db_key'];
}
Sessions are stored in the $_SESSION array. Whenever you want to use $_SESSION, you need to call session_start() FIRST and then you can assign or grab anything you like from it.
When you want to destroy the data, call session_destroy();
Also check out php.net's section on Sessions
Your question isn't too clear to me, but I understand it like this:
You need some variables to decide what is being displayed on the page. These variables are being passed in the URL. So far so good, perfectly normal. Now you want to hide these variables and save them in the session?
Consider this: Right now, every page has a unique URL.
http://mysite.com/page?var1=x&var2=y
displays a unique page. Whenever you visit the above URL, you'll get the same page.
What you're asking for, if I understand correctly, is to use one URL like
http://mysite.com/page
without variables, yet still get different pages?
That's certainly possible, but that means you'll need to keep track of what the user is doing on the server. I.e. "user clicked on 'Next Page', the last time I saw him he was on page X, so he should now be on page Y, so when he's requesting the site the next time, I'll show him page Y."
That's a lot of work to do, and things can get awkward quickly if the user starts to use the back button. I don't think this is a good idea.
If you need to take sensitive information out of the URL, obfuscate them somehow (hashes) or use alternative values that don't have any meaning by themselves.
It completely depends on your application of course, if the user is accumulating data over several pages, Sessions are the way to go obviously. Can you be a bit more descriptive on what your app is doing?
Edit:
but the problem is that I don't want people to change the number and read other people's mail
If your primary concern is security, that's the wrong way to do it anyway. Security through obscurity is not gonna work. You need to explicitly check if a user is allowed to see a certain piece of info before displaying it to him, not just relying on him not guessing the right id.
There are some examples on how to use $_SESSION on php.
Registering a variable with $_SESSION
The issue with using sessions for using it in place of S$_GET or $_POST is that you need some way to read the user's input so that you can store it in the session, and you need a way to trigger a page refresh. Traditional means is via hyperlinks, which defaults to GET (unless you use Javascript) or forms, which defaults to POST.
Maybe ajax will help you here. Once the user has enter info into a form or a checkbox, use JS to send a request to insert the info to the PHP and send info back, whether it is to refresh the page or to fill a with content.
Hope this helps

Categories