My website has a header, footer, and main content. If the user is not logged in, for the main content a login form may be displayed instead of the actual content.
On that login form I write the $_SERVER['REQUEST_URI']
in the session variable $_SESSION['redirect']
.
My login form posthandler, which will log the user in, will send the user after successfully loggin in to this link via header('location: http://myserver.com'.$_SESSION['redirect']);
So if I go to myserver.com/somesite.php?somevar=10
it will show the proper site if you are logged in. Otherwise it will show the login form, however the URL in the address bar in the browser still says myserver.com/somesite.php?somevar=10
Then you enter your credentials and you are redirected to myserver.com/somesite.php?somevar=10
, which will then - since you're now logged in - fully display.
I do not use the REQUEST_URI
value for a form action or as a link href.
Also, any $_GET
variables I use I first check if they match a regular expression (usually the variable will be a sha1
string or a otherwise randomly generated string of numbers and letters only, no special chars), and I always use prepared statements if the get variable is used in a db query.
My question is if there are any security concerns with that? Any ways to exploit this, enter something malicious into the url and then send it to another user for example...? Should I escape something somehow somewhere along the process?
The key-rule is that you always check your input/outputs and see what you can and cannot control (and thus, what can be controlled by a user). On the basis of that, you apply security/sanitization measures.
If I understand your scenario correctly, you display the page, unless a user is not logged in. In that case you show a login box, and after succesful login you send the user back to the page he was trying to visit using the $_SERVER['request_uri']
(stored in a session).
So the user obviously can control this variable, he can browse to your page with some awkward characters. Thus you need to sanitize that. As @Wayne mentions in the comments, users can traverse your directory tree for instance.
Thus, like your $_GET
variables, you will need to sanitize the $_SERVER['request_uri']
as well.
There are many ways to do this. The most secure is arguably to check if the request_uri
is an existing page, after sanitizing with html_entities()
or something like that. Note that special directory traversal methods such as ../
, //
and ./
might slip through conventional sanization methods such as the aforementioned html_entities()
And to answer literally: Should I escape something somehow somewhere along the process?
- Yes, everything, at the beginning of each process.
------ EDIT @ 12-12-2013 -----
(too long an answer for a comment, so I'll expain here how potentially a user can use directory traversal, incl. potential dangerous situations)
from the PHP manual:
$_SERVER['REQUEST_URI']: The URI which was given in order to access this page;
for instance, '/index.html'.
So, say I want to go to yourdomain.com/posts/post.php?../../../ssh
your webapp will notice that i'm not logged in, store post.php?../../../ssh
in a session and process logging in, after which it sends me back to the url. Because of the ../../../ssh
part, I won't be send to post.php, but to a directory on your server named ssh
which is below your webroot. For your convenience you've stored your SSH keys there. This seems safe, because it's out of the webroot no webuser should be able to access it.
Yet, I can because of my ingenious addition to your url.
Although this is a little far-fetched, a properly configured http-server, chrooting environment etc. will prevent this, this example does show you that if you allow these characters to be added, they might make users access locations they are not supposed to.
Depending on your implementation, blindly adding $_SERVER['request_uri']
might also mean unwanted stuff gets added to a session, and if you store that session in a database, it will also get added to the database. I'm not really up-to-date how (in)secure PHP is, but I can imagine this allows for breaking out of session variables and potentially injecting stuff into your database.
Although not everything might be possible, and the example might not be really possible, it's better and not that hard to prevent this behaviour.
-- Small after thought: maybe the header('location'...
stuff is insecure, but this: Is this PHP redirect insecure? shows its not really. Yet, like a commenter states over there: it's not that difficult to type urlencode()
There are numerous security concerns with putting ANYTHING online. Having an identifiable pattern in post/get requests are a concern, but it depends on a lot of factors, mainly... what can a user get from messing with your site, and how liable are you for malicious intent of site users.
You should do some research in sanitizing your input, using session tokens would be the first thing you could do to ensure traffic to your login script is actually being generated by users on your site. These two common practices are the first steps in protecting agains sql injection, and cross-site scripting attacks.
proper steps to ensure your data is protected, both through good database design, and good code design.
One of my favorite techniques is to configure my application to use custom http headers, and any script that receives data from a Super Global checks to ensure the custom header(s) are correctly supplied as on component of my security. These headers can be seen and sniffed easily by any hacker, but many attacks of a malicious nature are first performed by a script, and it's just one more step that's easy enough to deploy that makes you a harder target for these types of attacks.
A quick google search on fortifying a php based site turned up this article, which has some good tips: http://www.noupe.com/php/php-security-tips.html
You'll never be 100% secure. You can have a look at OWASP Top Ten. These are the main security issues.
I think you should have a token (random number) associated to each user in $_SESSION, instead of $_SERVER['REQUEST_URI']
. You could pass the REQUEST_URI by GET and token by POST (in a hidden input), and then validate it. If user login is needed to this URI, ensure that the received user token is equal to the session user token.
You are redirecting to a relative URL, which is good because this means that an attacker cannot use a method such as this to poison the session variable using session fixation with a redirect to their own domain. You should not do any encoding on this value because it is a direct copy of the original URI and it is also the exact URI that you wish to redirect the user to. You should check that the PHP version that you are using is not vulnerable to header injection though. It appears that it was fixed in PHP:
4.4.2 and 5.1.2 This function now prevents more than one header to be sent at once as a protection against header injection attacks.
The other answers regarding path traversal should not be a concern here because there is no extra risk than the user typing the path directly in their address bar. The fact that they are being redirected using the location
header does not increase this risk. However, you should ensure your server platform is not vulnerable but keep in mind this is nothing to do with your method of redirection as location
simply tells the client to load another address.
Make sure to call exit
after setting your header, otherwise an attacker would be able to see your page contents by viewing the raw HTTP response:-
<html>
<?php
/* This will give an error. Note the output
* above, which is before the header() call */
header('Location: http://www.example.com/');
exit;
?>
I cannot comment on every vulnerability your site may have, but in essence the way you propose to do the redirect should be safe. You should however make sure that your site is only accessed over HTTPS which will encrypt the connection and ensure it is safe from MITM attacks. You should also set the secure flag on your session cookie to ensure it cannot be leaked over a non HTTPS connection.