Client access to Superglobals - php

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

Related

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.

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

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^

How to keep track of one php variable in another php file in command line without any session concept?

I am trying to give user an option to register into the system and want to link the page to another php file say detail.php page with all the database variable remain active in that file. Please anyone can help me out..??
Other alternatives are cookies, (encrypted) POST parameters sent to that page or if you are using include statement to include the contents of that file in the current page, you may as well define your variables just before include and those can be used in the included file.
P.S.: Use of sessions is recommended; though its not clear from your question, why you dont intend to use sessions.
Any options you may have rely on the client sending some form of way of identifying the initial user.
You basically have 3 options:
Keep resending all of the data you need to complete the registration to every page via a form (i.e. as either GET or POST data).
Storing the data in a COOKIE and sending that with each request.
Storing the data serverside and using the session (and PHP session COOKIE)
Personally, I'd recommend sticking with using the session as it limits the amount of data being sent between requests. The only reason I can think of not to do this is if you multiple application servers and no shared storage for your sessions (i.e. memcache or database)
If you want to elaborate on your OP and explain why you don't want to use sessions, I'd be happy to give you a more indepth answer.

Sessions without passing SID - is it reliable?

I'm working on a project that keeps some user information (non-sensitive) in a php session. As it is my first time working with sessions, I never bothered to pass any Session ID, but it still works - is that right ? I couldn't find any information about that.
I'm using some parts of the information in the $_SESSION variable to navigate and influence some of the sites' behaviour, and it sometimes is crucial for the page to interact with the user. Meaning without the correct informatin of the current session the navigation will be broken.
So, can I rely on the existence of Sessions ?
And can I rely on the server to automatically pick the right session without passing the SID ?
I'm working only on one server and I don't need the session to be restorable (meaning that when a user leaves the application the session can be destroyed).
If you couldn't find information about that, you probably skipped the most obvious reference: the official PHP manual. It's right there in the Introduction of the Sessions chapter:
Session support in PHP consists of a way to preserve certain data
across subsequent accesses. This enables you to build more customized
applications and increase the appeal of your web site.
A visitor accessing your web site is assigned a unique id, the
so-called session id. This is either stored in a cookie on the user
side or is propagated in the URL.
If your question is whether cookies are reliable for this purpose, in fact it's the de-facto standard nowadays. You'll hardly find PHP-powered sites that still transmit the session ID in the URL. The reason is that it's a problematic technique: it's too easy to give away your session ID. If you copy the URL and send a link to a friend or post it in a forum it's very easy that any stranger is able to access your private data, even inadvertently (you don't need a malicious guy here) if they visit the site before the session has expired and the site does not implement further verifications (which is the usual situation).
Yes you can rely to having the server to pick the correct sessions for you. I have in my 10 years of php coding not experienced a faulty session yet.
However, if you choose to pass the sessionid to the next page, be ware of the risks. Session hijacking is a very serious business if you have any sort of private data.

store authorization object to session?

I've built a class that provides some basic "can I do this?" authorization functions for my site, stuff like "can this user view this resource?" or "can this user add an image?"
So the class object is instantiated in quite a few pages (potentially, every page that has a user interaction) using $authorize = new myAuthorizationClass();
The myAuthorizationClass class then looks up the user's ID and check their access level.
I can then say something like
if ($authorize->canAddImage()){
// do image add stuff
}
Is it possible, secure and "best practice" to store this $authorize object into the session? Is there another way to avoid the overhead of building this auth object on every page, and doing the DB interactions etc?
I don't think it can be as simple as just saying "set the user's auth level to A, B, or C, and set that in their session!" since their access to a particular resource depends on who owns the resource, what role the user has in the site, etc. and we have to check a few different things depending on what type of resource is being accessed.
Thanks
Storing user data within a session (not cookie) is acceptable, as this data is stored on the server side and randomly generated for every user, and as long as your session handling storage is protected, will not be accessible to other users.
If you want to reduce database load by not having to look up the users role/access for every page request, you may want to consider pulling the information upon successful login then storing the (in serialized format) into a session variable. Then, for protected resources, you can unserialize the data stored within the variable, do your check, and proceed accordingly.
I believe it is considered bad practice to store authorization data within sessions.
The reason is quite simple, while the data itself is stored on the server side, where it's safe, the weaker link is actually still (like always) on the client.
The server must identify the client who owns the data somehow, that is usually done in a form of a session_id cookie sent to the user. That cookie will be sent to the server in each request, and the server will be able to figure out who you are by the (very random) ID.
However, over an unsecured WiFi (or a computer), that cookie can be rather easily stolen by an attacker, which will cause the server to identify him as you.
There is no simple way around this, other then SSL and user education. If your site requires very high security (such as money transactions or critical database operations), inform the users about it and advise them to confirm their local security measures.
Also, if your site deals with critical database operations, don't allow anything critical (deletion, table drops etc) done from the web application. Only via the root user.

Categories