PHP sessions and security - php

I'm trying to decide on the level of security with regards to session management on my php site. at the top of every page is a php tag where I run
if (!isset($_SESSION["user"])) {header('Location: login.php');}
The User session is created on login, do you guys think this is secure enough? The whole site runs in SSL.

Well, being secure has 100's of different topics... But in terms of what you are trying to achieve, yes I think that's fine
I would add some additional validation to checking that $_SESSION['user'] is definately a correct user, and try to compare the session user's IP Address, USER AGENT and other things to detect Session Hi-Jacking
You should also EXIT; after header("Location: X"):
header("Location: xyz.php");
exit;

Yes that will work. To make it less error prone put that snippet in a file and include it at the top of each page. That way you just edit one place to make changes to the logic.
Also, your Location header is supposed to contain the entire URL starting with https: according to the RFC specifications. It may still work for some browsers but should not be depended on.

I think it's better to create a random token string when your user wants to login to your website. Then check it in every page beside your previous code. I used $_SERVER['REMOTE_ADDR'] , $_SERVER['HTTP_USER_AGENT'] and a random string to make it.

Well, at least once per load you will need also validate the user, otherwise you are just checking if the session exists.

Related

Block access of a PHP page if visitor doesn't come from a certain page (on same domain)

As title says, I'd like to block visitors from viewing content of a page if they don't come from a specific URL. How can I achieve this? I have PHP over Nginx. Would it be better to use PHP or Nginx?
I read that using HTTP_REFERER is not the best idea because it's not mandatory for the browsers... what would you do (code examples)?
The most bullet-proof solution is to pass a _GET parameter that is not trivial to guess from one page to the next, a-la unique tokens.
It, however, takes a hell of a lot of effort to implement correctly, as it's not the simplest solution, and by far not the simplest to implement either.
In order of complexity, with the simplest at the top, your alternatives are:
Referer
Using a fixed GET parameter
Cookie placed on the user on the first page. Doesn't work for visitors not accepting cookies, and you'll need a cookie policy if you work in the EU.
Using nonces as GET parameters
The last solution in detail
your initial page generates a one-off string, and appends it to every link. You then check if this string is matched with an entry in a database/flat file, and if so, allow access. If not, you deny access. You then invalidate the token so users have to go through the page again.
Probably not perfect, but I would set a $_SESSION on the initial page and then check and remove it on the linked page.
$_SESSION['allow'] = 'yes';
then on the next page
if(isset($_SESSION['allow']) && $_SESSION['allow'] == 'yes') {
$_SESSION['allow'] = 'now viewing';
}
Or something like that....
The only way to restrict access to pages is by using someone's credentials, there's no reliable way to detect where the user came from since that can be spoofed.
Therefore there is no way to allow access to a page B only if the user just came from page A (unless you do it unreliably through HTTP_REFERER
You could also set a cookie (or session variable) on page A and not display page B unless the user had the cookie (session variable) set, but that would not require that the user be going straight from page A to page B
A simple way would be to set a one-time session variable on the first page, and read that variable on the second page.
For example, page 1:
$_SESSION['viewed_page1'] = true;
Page 2:
if(!$_SESSION['viewed_page1']){
echo 'You need to visit page 1 first!';
}
.
you can use a session variable and pass a particular 'key' from one page, and require it on the following page in order to display it.
you can find info on sessions here

PHP Beginner Security Fear

I'm a tech writer who has done a lot of HTML/CSS but have been thrown into a pressure cooker to rewrite a web app in PHP and have done fairly well, but I'm a bit concerned re the security.
Specifically, the main page is INDEX.PHP, where the user logs in. Once they are logged in, the page rewrites portions of itself and shows menu options not available to users who aren't logged in. About 50% of the users will never need to login since they'll be viewing public documents for which no security is needed. The other 50% of users will have restricted viewing access to certain documents/pages and be able to write to a database.
I got all of this working fine, but am concerned about two things I'm doing and whether they're proper:
A logged-in user might get redirected to another page, say PAGE1.PHP. I don't want them to be able to save the URL for PAGE1.PHP and just go directly there, bypassing security, so on PAGE1.PHP I have a check for a log-in cookie I created on INDEX.PHP. If the cookie exists they can go to the page, if not they can't. Is this the right way to do this type of thing?
How do I stop a malicious user from inserting a redirect into one of the many text boxes on my various forms? I need to allow HTML, such as strong, font, background, etc. I've been running all the text box values through a function that checks for possible malicious things, one at a time, such as "meta http" or "anchors" or "java script" but I'm not sure this is the best solution.
Thanks for your help!
$_SESSION will be your friend. In a normal shared-hosting environment, $_SESSION may not last any longer than, uh, the current session so plan accordingly. (IE, don't rely on it for anything more than logging in.)
You'll need to read up on session_start and friends.
In addition, check out this discussion: PHP HTML sanitizer for sanitizing HTML input. (Just as an FYI, there is a reason why bbcode and markdown are so popular.)
No - every client can manipulate his cookies and send everything they want - even a invalid "login" Cookie. You have to store those Information serverside in sessions
You could use strip_tags to only allow some Special tags or use a html sanitizer
1 . Upon successful login, store a new $_SESSION variable, say, the user ID (since that seems to be needed often)
Example:
if(login is successful)
{
$_SESSION['userId'] = $userId;
}
Create a php auth page that checks to make sure the session var is populated. If not, redirect to access denied or login page.
Example:
if(! isset($_SESSION['userId']) || $_SESSION['userId'] == '')
{
header("Location: accessDenied.php?msg=Not logged in");
}
On each secure page, require('auth.php');
2 . You can use strip_tags on the textbox, and mysqli_real_escape_string on user-input that ends up going to the database. (Or use prepared statements, see Best way to prevent SQL Injection in PHP)

When to create sessions in PHP (somewhat specific situation)?

I have a large number of pages, each of which use a common header/footer. My wish is to keep the header and footer standard regardless of which page the user is on.
To access administration functions, the user presses an administration link at the bottom of the header. I would like this administrative login link to change to a log-out link after the user is logged in.
If I use session_start() in the header, then every page is going to have a session. I was told (I'm not sure if this is true or not) that it is bad practice to always have a session open.
Making matters worse in this regard, many of my pages use sessions (specifically all the administrative ones), and if you try and call start_session() after a header is sent (which obviously happens because my common header is parsed prior to the page content script sections being run, then it is an error.
To this point, I had been calling start_session() before the require line for the header on pages that would need sessions - but if the header now starts the session then this becomes an error.
If I need to know when an administrator is logged in within the common header code, how do I handle my session creation? Am I looking at this wrong?
I was told that it is bad practice to always have a session open.
yes. start your sessions only if you really need them.
otherwise it will make your site unnecessary slow, forbid browser from caching your pages when possible and such.
although you can't serve registered users without sessions, all other requests to the site (especailly from search engine bots) require no session support and there is no reason to start it.
how do I handle my session creation?
thre is a very simple solution.
call session_start() only on 2 occasions:
when user actully logs in.
when your script recieved a session identifier (means there is an active session running)
So, just add session_start() call right after the code checking user's password and modify all other calls this way
if (isset($_REQUEST[session_name()])) session_start();
There's the simple way of looking at sessions. If the page a user is on requires sessions, use sessions. Even if the page a user is on does not require sessions, if that page is one that a user reaches after a session has started, and it is reasonable to assume that a user will go from that page to another page that requires sessions, maintain the session. Don't keep starting and stopping your sessions. Just, as a rule of thumb, don't start the sessions until you need them and end them when you can be very confident that a user will not be needing them again during their visit.
In general, you are reinventing the wheel. Not using a CMS for these tasks is a waste of time and effort. In specifics, ob_start() is your friend.
I was told (I'm not sure if this is true or not) that it is bad practice to always have a session open.
That is hugely false. StackOverflow, Google, Facebook, etc. would all cease to function without an always-on session.

PHP security question

If I want people only accessing a certain page on my webpage by using a link within my website, and not typing it in the address box then would this do...
Please note that the user would first have to login to their account and all member pages have been set so that the user must login into their account before accessing member pages.
if (isset($_SERVER['HTTP_REFERER'])) {
// show page content
}
else {
header('Location:http://');
exit();
}
Am I correct in saying, that if a link is clicked then the page will show, but if the link is not clicked and the address of where the link points to is typed in the address bar it will do a redirect.
I am asking as the link will direct people to a form, and I don't want that form being accessed without first having some variables set on the previous page, or being accessed without logging in (as people could create their own link on another website which points to the same location)
Thanks
It is not secure in any way. From here:
The address of the page (if any) which referred the user agent to the
current page. This is set by the user agent. Not all user agents will
set this, and some provide the ability to modify HTTP_REFERER as a
feature. In short, it cannot really be trusted.
Users can set the referrer to whatever they want, so no, checking that that's set is not a secure way of checking that they came to your second page via the first.
HTTP_REFERRER can be spoofed pretty easily. When you want forms to be secure, implement some sort of CSRF protection by adding a hidden token to the field and ensuring it matches when you submit the form. Your best bet is to make sure their credentials are actually valid.
This seems very buggy to me; if you want certain variables to be set and / or a user to be logged in, just check for all these conditions at the top of the form-page and redirect the visitor somewhere else if the conditions are not met.
I'm unsure what you mean about having variables set from the previous page, or how you are achieving this. Its possible of course, but I would be interested how you are going about it.
You are correct in your question however, that when coming from another page the referrer will be set to that page. In terms of security however, its not a good idea to rely on it as it is easily spoofed. The only sure way is to ask for credentials (a username and password etc) which it sounds like you are already doing.
Could you not test to see if the variables are set, and if they aren't then redirect?

The best way to create log-in realm in PHP

I can do login realm in PHP and the way that I do it is by setting a session variable and check whether that session variable is set or not. On every restricted page, I check whether a certain session variable is set (or is equal to a certain value). If not, then i will send the user back to the login page. Is this the best way to do it? Is there a more secure way to do it?
This is fine and normal. At the top of the page, you have a header that starts a session and checks whether the user is authenticated. When they're not, make them log in.
A-OK and secure so long as your session IDs are unpredictable, expire quickly enough, and you are using SSL.
If someone can guess your session IDs, they can hijack another user's login.
If you are not using SSL, an attacker can steal the session ID when the client sends it to you.
If your sessions never expire the ID can eventually be guessed.
There's a lot to think about when you're setting up a login system. Here are some questions you want to answer:
Security: You need to encrypt passwords everywhere they are stored (cookies, database, sessions, etc.). How will you do that?
Will users be able to post login to every page? Or will there be a centralized account page?
Is there a remember me feature?
How will users logout?
Do you have activation at your site? How will it work? How will you deal with various scenarios such as unactivated users trying to login?
Will you have login/form redirection? I.e., if a user goes to a page without logging in will you send them there after they login? What if they try to send a form? Will you resend the form.
You have the basic idea right, but the way you structure everything depends on those and other questions.
I've got a similar question on SO before, and here are the answers from security guys.
Put it short, you should think other things like SSL and password hashing, etc...
Hope this helps :)

Categories