Is it safe to use variable session data? - php

I have a (hopefully) quick question regarding sessions. Whilst I have used sessions extensively, I have not used them in a situation whereby the values change depending on a users actions.
After logging in to my application, a user can select a company area, which has many levels of pages and folders. All of these pages will need this 'company_id'. At the moment I send the company_id via GET, but as I get deeper into the application this is becoming increasingly hard to maintain, with various other data being stored in the URL.
Therefore, when a user selects their company, I could set their company_id in $_SESSION array. However, when a user changes company, I would then need to change $_SESSION['company_id'] to the new value.
Is this a good use of sessions? I could potentially clean up my urls by using session data rather than always using GET, but I am unsure if this is a recommended way of using sessions.
Thanks in advance

This is a bad implementation of the HTTP design philosophy. All HTTP requests should be self contained, RESTful. All information needed to get a specific page should be present in the request itself (URL, headers and body), not dependent on hidden state.
Super trivial example: you can't copy a URL to someplace or someone else and have them see the same page. The content of the page is dependent on session state, which has been laboriously set through the visit history of several previous pages. To return to this same page, you need to retrace the same steps, recreating some hidden server-side state to arrive at the same page.
This gets even more complex and messier if you take into account that a visitor may want to open pages requiring different states in two or more simultaneous tabs/windows.
All this isn't to say that it can't work, only that it's hideously complex and will break the usual expected behaviour of browsers, unless you really bend over backwards to somehow prevent that.

If the many levels of pages and levels are per-company, you can put the company_id in a specific include file - this part of the site being dedicated to a given company.
However if they're shared by multiple companies, and this is probably what you want, this is potentially misleading, or even dangerous depending on the user actions, since the user may jump to a given page (link...) and access a page with unexpected data linked to a company which ID is provided by the session or cookie.
You could dynamically build the links on a page, based on IDs, to ensure consistency during the navigation from that page. Any direct "jump" to another part of the site will not carry the ID with it (and the page may offer to select a company).
Depending on your web server and if you have control over it you could build the URL having "company ID" as an element of the URL path, not the GET parameters
Eg
http://example.com/invoicing/company382/listprices.php
using a rewrite (web server configuration) to change the URL to be actually used to
http://example.com/invoicing/listprices.php?compid=company382
(URL not visible to the user) that informs of the company ID via the GET parameters.

Related

php variables - best way to pass variables over to another php page

So I am aware of these two common ways of passing variables across php pages.
1. PHP SESSIONS
I understand that $_SESSION is a php global variable that can hold variables across php pages during the session of the browser.
It works well but my concern with it is if a user for what ever reasons, decides to type the url of a page or goes into their history and accesses a url page for the website, the $_SESSION variable may not be set, if it was expecting the user to get to this page from a set route/path.
In addition, if a user goes into another page, and the page sets an already defined $_SESSION to another value, and then decides to go back to the previous page, the $_SESSION variable is not correct for that page, causing many errors.
2. URL passing
This is by far the most reliable in my opinion. The only concern I have with this, is the pages can get rather messy with long URL's.
page1.php?postId={variable goes here}
passing 4,5 or 6 variables can get a bit messy, I also need to encode then or encrypt them. The URL can get rather long, and I am not sure how I feel about passing variables across the URL.
My Question:
What is the best way to pass variables from one php page to another. Are the two methods above the best way to go about it, or is there another my efficient way. Also if efficiency isn't the issue, then what is the most secure procedure/method.
Thanks for your time.
This is largely going to depend what you're trying to do? $_SESSION variables and $_GET variables largely have different purposes in web programming (although, yes, you could force some sway between the two).
The question you need to ask yourself is "is the variable storing information on the user OR directing the webserver to do something" if it's the former then use $_SESSION if it's the latter then $_GET.
You wouldn't for example want to pass loggedon=true as a GET variable (ignoring the security implications) because you would have to update every single link on the page to have the query string appended to it which, as you say, would lead to some untidy URLs.
SESSION
Is most commonly used for storing information about a user. Some examples:
Log on status
Shopping basket
Session preferences
For example when a user is successfully logged on you will want some way to remember that between page loads:
session_start();
$_SESSION["loggedon"] = true;
In every subsequent page request you can then check:
session_start();
if(!$_SESSION["loggedon"] ?? null){
echo "ERROR: You shouldn't be here!";
exit;
}
Note that $_SESSION is only accessible to the server, can't be directly accessed by the website user, and is persistent until the session closes.
GET
On the other hand is sent with every request and is typically used when you want to pass non-sensitive information from the user to the webserver. Some examples:
Language preferences
User input (e.g. a search query when using a search engine)
Forgotten password secure codes
Suppose you have a cookery website and 1000 recipes. You would likely only have one page to show the recipe and pass a GET variable in the URL to indicate which recipe should be loaded
http://www.mycookingwebsite.com/recipe.php?recipeid=477
Note that GET requests are visible to the user, can be modified, and show up in history etc. as well.
N.B. Do not pass sensitive details (e.g. username/password) over GET - not least because they would show up in the browser history!
You mention passing variables from one page to another. But I'm not quite clear on whether you mean Server->Server (SESSION) OR Client->Server(GET)?
An example of this all coming together would be in the case of a shopping cart:
At the back end you have an array stored in your session with the items in the cart, this is persistent throughout the session. On the client side you have the ability to send a GET (most people would probably POST) request to tell the server about the new product you want to add to the list.
If your primary concern is that users may find themselves at the wrong "stage" then I suggest building in some checks to make sure that they are in the right place at the right time.
For example given a quiz with 10 questions... If the user clicks a link which drops them at question 5 you check to see if they've already answered questions 1-4 and then act appropriately depending on the answer.

Should GET requests store to database?

I’ve read that you should not use GET requests if you are modifying the database. How would you record analytics about your website then?
For example, I want to record page views whenever someone visits a page. I would need to update views = views + 1 in the database. Is this OK, despite using a GET request, or is there another technique? Surely, not every request should be a POST request.
The general advice about how to use POST vs. GET shows up in RFC 1945 from 23 years ago:
The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI.
 
POST is designed to allow a uniform method to cover the following functions:
Annotation of existing resources;
Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles;
Providing a block of data, such as the result of submitting a form [3], to a data-handling process;
Extending a database through an append operation.
These guidelines remain in effect to this day, but they cover the primary purpose of the user's page request.
The act of incrementing a view counter is incidental to the primary purpose of the request, which is to view the page content. Indeed, the user is likely unaware that this database update is occurring.
(Of course, you must expect that you will receive duplicate requests as users move through browser history, caches are populated, or spiders crawl your pages. This wouldn't be the case if a POST request was made.)
It's ok.
When you make POST request, you actually wait for POST params to come and you build your database insert query based on parameters which you've got from browser.
On GET request you actually implement your own business logic, so user won't ever know what is going on the side.
And for the finish, actually sometimes you can do something, what's going against rules, rules are good, but we are able not to follow them, that's what makes us human, if we would strictly follow all the rules, it would be cumbersome.

Embedded iframe - Verify source/origin of GET request

I'm seeking to utilize an iframe to embed some html in customers websites that will list some information from my database using a simple GET request like so:
// customer would copy/paste this code onto their site
// value of key would be unique key for that customer
<iframe src='http://mydomain.php/api?key=1234j1lj1hj124kh' ></iframe>
Now I want to be able to verify that the request is coming from customer that owns the key, and not just anybody who copy/pasted that code onto their page.
I've done some research and found that $_SERVER['HTTP_REFERRER'] can give me this information, but with mostly mixed reviews saying it isn't always reliable (and most of the questions I came across were a couple years old).
QUESTIONS
1.) Is this method of using an iframe/GET request the standard way of achieving this functionality?
2.) Is there a standard, SECURE and RELIABLE way to verify the origin of the GET request?
Unfortunately this is not possible in a secure way.
To answer your questions: In fact this is not a standard functionality itself. I mean, there is no standard secure way of allowing content to be loaded only through iframes from allowed websites.
There are three parties in this communication:
1) Your website
2) Customer website that loads your website's data in an iframe
3) End user visiting customer website
When an end user visits customer web site, he will perform a GET request to your website through the iframe. At this connection, 2nd party above (customer website) is not involved. In this case, there is no reliable way for your website to know whether this request is coming through the iframe or not. Only favor that party 2 does here is adding HTTP_REFERER header to end-user's request. But this header cannot be trusted.
For example, if I want to abuse this and show that content on my website, I can create a proxy page on my application, where I perform a back-end call to your app (adding a valid HTTP_REFERER header) and display results back.
Personally I would never use iFrames for this functionality. I am assuming that this has to be reasonably secure, which is why only your specified customer can view it? If for whatever reason you can't use PHP to embed the content you need to display (through the use of an "included" file for example), I would instead use AJAX which would still use any PHP user verification you have in place to dynamically load content into a secure webpage.
This is because your PHP user verification will (should!) use cookie/session information to determine which customer is viewing the page and therefore decide whether the content should be delivered, since Session variables are determined by a single unique code stored client-side, which match up to as much information as you want to collect about a user server-side (Which could include the last page they visited, which is what the "HTTP_REFERRER" variable would give you, if they came from another page on your website).
'$_SERVER' variables aren't reliable because they rely on the information given to them by the web browser when the request is made, and such information can easily be forged, by most people who have a basic understanding about how headers are sent.
In summary, use a NONCE (cookied), validate IP and user agent.
Steps:
When you deliver the outer frame, generate a unique identifier
(totally random, long string) and return that in a cookie with the
HTML content.
At the same time, note the IP and the user agent string you have
sent that unique identifier to, and store in a DB with the time.
When requesting the inner frame, assuming the same domain, the
cookie will come too. (If a different domain, you'll need to attach
the unique identifier as a visible string, but that's not really of
concern, just uglier)
If the user agent or IP do not match those you stored against the
unique string, or the request is too long (i.e. after an hour, or
whatever is reasonable for your application) or the unique string is used more than once
(or whatever other restrictions you place on it) then reject the
request and invalidate (delete) the unique identifier.
Not 100% foolproof, but just combine more options to make it less and less likely to be abused.

php security & marking mysql records for deletion using a html link (GET)

Just wondering if people think it is safe for a website to use a html link to allow users to mark their documents for deletion from their secure account page?
I have a website where users can create documents once they have registered and logged in to the website. To delete a document I include links on their account page for each document to be marked for deletion as follows :
http://www.examplewebsitename.com/delete_document.php?docid=5
The delete_document script makes sure the docid parameter is numeric, then checks using a session variable of their user id set when they logged in, wether this person actually created this document by looking up the user id of the creator of the document. If they where the creator, then it marks the document for deletion, otherwise if the current logged in person wasnt the creator then it doesnt mark the document for deletion and returns an error page.
Do you think this is a valid and safe way to mark documents for deletion, or should I be using a form and Post to do this more securely?
Three main concerns I can think of about using GET as a delete operation for your app.
Semantic reason, GET, according to http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html, should be an idempotent method
the side-effects of N > 0 identical requests is the same as for a single request.
More prone to CSRF, someone could post a link to http://www.examplewebsitename.com/delete_document.php?docid=5 and wrap the link into a harmless looking anchor
Click here for free puppy!
If by any chance the user is logged in and clicked on that link on his trusted website, it would inadvertently get the user to delete the document.
Browser addon / plugin that crawls web pages and cache links might accidentally crawl the link, opens it and again, delete the document without your user knowing.
Generally I advice against using GET requests to manipulate data because that's not what GET is designed to do if you stick to the HTTP Spec. If you would go completely restful you should be using a DELETE request but in most cases i use a confirmation page with a form that performs a POST request to delete the record.
Read Why should you delete using an HTTP POST or DELETE, rather than GET? for the reasoning behind this. It's been asked before in some other contexts.
The main reason is because GET is meant to be a safe method that is used for retrieval only:
In particular, the convention has been established that the GET and
HEAD methods SHOULD NOT have the significance of taking an action
other than retrieval. These methods ought to be considered "safe".
This allows user agents to represent other methods, such as POST, PUT
and DELETE, in a special way, so that the user is made aware of the
fact that a possibly unsafe action is being requested.
User agents expect this method to have no side-effects:
Naturally, it is not possible to ensure that the server does not
generate side-effects as a result of performing a GET request; in
fact, some dynamic resources consider that a feature. The important
distinction here is that the user did not request the side-effects,
so therefore cannot be held accountable for them.
This means GET should no cause any server-side state change.
Another reason, but rather a minor one, is that GET is easier to exploit that POST as there are more ways to trigger GET request than to trigger POST request. But no matter which method, both are vulnerable to CSRF attacks.
So if you make sure you’re protected against CSRF, you could even use GET for state changing requests.

data between pages: $_SESSION vs. $_GET?

Ok, firstly this is not about forms this is about consistent layout as a user explores a site.
let me explain:
If we imagine a (non-ajax) digital camera online store, say someone was on the DSLR section and specified to view the cameras in Gallery mode and order by price. They then click onto the Compact camera's page. It would be in the users interests if the 'views' they selected we're carried over to this new page.
Now, i'd say use a session - am i wrong?
are there performance issues i should be aware of for a few small session vars ( ie view=1 , orderby=price) ?
Speaking of performances, there should not be much problems with either solutions.
Some things that have to be considered are :
With GET, if an URL gets copy-pasted (in a email or MSN), the other who will receive the URL will have the same GET parameters
is that a good thing, or not ?
On the other hand, session will not be shared, if an URL is copy-pasted
which means the first guy will say to the other "key, look at this", and the second guy will not see the same page ;; same thing with bookmarking, should I add.
GET is specific to each URL
While SESSION is shared accross all tabs of the user
Which means browsing with several tabs at the same time can cause troubles, when using Session, if you don't take care of that
I'd say use both. Store it in the session, but also put it in the get parameters for the page.
Why? This way the user is able to carry his options from page to page, but they are also in the URL so if he sends search results to his friend, his friend sees them the exact same way he did.
No, the session's performance will not degrade by putting those small variables in there. Unless you're storing monolithic arrays in your session, the vast majority of the time loading a session will be reading it from its storage medium (file, database, memcache, etc).
You should use GET in your case.
There is one simple rule in the web development: each page with different content must have it's own address. So, customer can save any page into favorites, send it to a frend. It's pain in the bottom then someone sends you a link to a particular page saying "Look!" but site uses frames and you land at the front page and dunno where to look.
You can save user's preferences into his profile/cookie (not session), but it should be reflected in the address bar as well.
Sessions being used for completely different purpose, shopping cart is an example.
It's a subjective question, it would work either way.
Personally I would go with sessions as it doesn't interfere with the URL so people can bookmark the url if they wanted.
However the argument for that would be if they bookmarked it they might see different things if it was done using $_SESSION.

Categories