I know two ways to pass parameters between pages:
- using POST and
<input type="hidden">
- using
$_SESSION["variable_name"]
I find the second way easier, but I wonder if it is as secure as the first one, because in most tutorials I see, they use the first way.
Is there any important reason to prefer the first way to second?
To understand the difference, let's go through in detail how each of the solutions would work and their security risks. In this example we are going to store the count of page views of the user.
$_SESSION
We start the session, increment the counter and store it in the $_SESSION
array:
<?php
session_start();
if(!isset($_SESSION["pageviews"]))
{
$_SESSION["pageviews"] = 0;
}
$_SESSION["pageviews"]++;
?>
When a user visits this page for the first time, PHP will generate a random session identifier that looks like the following, and ask the browser to store this ID in a cookie:
fh4giqncq25ntgs7gjunvj6i33
On the server, it will store and remember that there is a pageviews
variable with the value 1
that belongs to the session ID fh4giqncq25ntgs7gjunvj6i33
.
The next time the user visits the page, his or her browser will send the previous session ID along with the request (given that the cookie hasn't expired or got deleted). PHP then recognizes this ID, and populates the $_SESSION
array with pageviews = 1
, then increments it: pageviews = 2
In terms of security, consider the following questions:
Is the user able to read the stored data? No – The only thing the client sees is the random session ID in the cookie; the data itself is stored on the server.
Is the user able to alter or manipulate the stored data? Again, no – If the session ID is altered in the browser, PHP will not be able to tie the browser to the stored data any more. In this worst case scenario the user will get a new session, starting with pageviews = 1
.
The main security risk of sessions is session hijacking, when an attacker somehow manages to get the session ID from someone else's browser and then presents it to the server, thereby impersonating the other user. In our example this would not make much sense since we're only storing a page view count; however, most sites use sessions to keep track of which user is logged on from which browser. In that scenario, stealing someone else's session would mean getting access to their account.
Hidden field
In this case we have a form with a hidden field:
<form action="..." method="post">
<input type="hidden" name="pageviews" value="<?php print($pageviews); ?>" />
...
</form>
On the server, we retrieve the pageviews
variable from $_POST
and increment it:
<?php
$pageviews = @$_POST["pageviews"];
$pageviews++;
?>
So, instead of storing it on the server, we essentially send the data down to the client and expect it back in the subsequent request. Apart from the fact that it only works with POST requests, let's look at the security-related downsides of this solution:
Is the user able to read the stored data? Yes – it goes straight to the browser in the HTML code.
Is the user able to alter or manipulate the stored data? Yes – there is nothing to prevent the user from opening up the developer tools in his or her browser and changing the hidden value to whatever he or she likes. Upon submitting the form, the server gets the altered data.
The problem with <input type="hidden">
is that you just can't trust the client, so you have to verify the data you get in every request. It might be reasonable to do this in some cases, such as filling out multi-page forms, but even that can often be better solved with sessions.
Summary
Persisting data via $_SESSION
is generally safer than using <input type="hidden">
because the session data is stored on the server, and thus cannot be tampered with by the client. Only a random session identifier is sent to the browser in a cookie which ties the data on the server to that particular browser.