Limit user to their profile page - php

On my website I have a user login system, when they login they are taken to their profile page, which is deism ate by their uid. The thing is, there was nothing to stop a user just changing the uid and going to someone else's profile and Acting as them. To stop this I implemented a URL/MySQL system by which if the uid of the user is not the uid in the URL, they are redirected to their own profile. The problem here is that on the profile there are forms which change the URL, in doing so removing the uid query, resulting in the page (because the uid is missing) taking you to your profile and ignoring the form input.
The code is:
<?php
mysql_connect ('x', 'x', 'x');
mysql_select_db ('x');
if(isset($_COOKIE['wd_un'])) {
$un = $_COOKIE['wd_un'];
$pass = $_COOKIE['wd_pass'];
$cook = "SELECT * FROM x WHERE username = '$un' AND password = '$pass' limit 1";
$cookr = mysql_query($cook) or die (mysql_error());
if(mysql_num_rows($cookr) == 0) {
header ("Location: index.php");
}
else {
$urluid = mysql_real_escape_string($_GET['uid']);
$uidcheck = "SELECT * FROM x WHERE username = '$un' AND password = '$pass'";
$uidcheckq = mysql_query($uidcheck) or die (mysql_error());
while($rcu = mysql_fetch_assoc($uidcheckq)) {
$dbuid = $rcu['uid'];
if($urluid != $dbuid) {
header ("location: home.php?uid=$dbuid");
}
else {
}
}
}
}
mysql_close();
?>
Is there a work around?

This code block you have here is riddled with badness.
First, you should absolutely never store a user's password in a cookie.
You SHOULD store only a session ID in the cookie, then store the rest of the session data in a session table in your DB that contains the user's id and any other things that you may want to have basic access to... password should not be in this table either.
Now, you can use the user_id in the URL safely cause the cross reference will keep people out.
on load of course you cross reference the mysql result from your session table that was pulled based on your cookie id. Obviously boot them if they don't match.
As for your form redirecting, you need to restructure how you handle posting then. You can make your profile page always pull only the profile related to the session id in your cookie. That would remove the dependency on URL and solve this problem completely.
Also - Please look into mysql_real_escape_string() to sanitize your inputs. It is incredibly dangerous to blindly accept cookie info for a mysql query. Unless you really do aim to leave huge injection holes in your site.

You should be using the Cookie ID to identify the user rather than pulling the user if from the URL. If cookieID does not match UserID, then redirect to their own profile.
Basically, never use the url to pass user ids for private data. Always references the cookie.
Relying on only the URL string to identify a user is a HUGE security hole on top of the usability issue you've described.

Related

PHP SESSION Conflicts

I have this in my $_SESSION setting script:
<?php
//----------------------// Start session----------------------
if(!isset($_SESSION))
{
session_start();
}
//------------------------------------------------------------
//------------------// Check if Username $_SESSION is set------------------------------------------
if (!$_SESSION['Username']) { // If not current User
header("Location: ./logout.php"); // Session destroy file that leads to session logout landing page
exit();
}
//------------------------------------------------------------
?>
Now, what I basically do is just check if Username SESSION is set. But, I have come to notice something strange while putting another user through:
If we click the same link at the same time and arrive on the landing page same time, I noticed I can see my Username displayed as his Username and his personal data like email and phone replaced mine in my very own PC! This is really strange to me as we do not even live in the same country or even share same PC.
So, it is obvious I have not secured my SESSION and I have used a lame approach without thinking about security and this can be abused with SESSIONS hijacked.
How do I resolve this conflict? How do I restrict each logged in user to a particular session without conflicts if two or more users access the same resource at the very same time? I need help. I can't sleep since I found this.
After reading your responses, I will now show a snippet of the functions.php file which outputs Use data from DB.
First, I get the UserName value from session using:
$UserName = $_SESSION['Username'];
With this value, I query DB to get more user details:
//------------Get User Info -- All user column
$Get_User_Info = mysqli_query($conn,"SELECT * FROM customers WHERE User='$UserName'");
/************************************************************/
/************************************************************/
$Get_User_Info_row = mysqli_fetch_array($Get_User_Info,MYSQLI_ASSOC);
/************************************************************/
//---- Now list all user rows
$GLOBALS['Skype'] = $Get_User_Info_row['Skype'];
$GLOBALS['Jabber'] = $Get_User_Info_row['Jabber'];
$GLOBALS['ICQ'] = $Get_User_Info_row['ICQ'];
$GLOBALS['Join_Date'] = $Get_User_Info_row['Join_Date'];
$GLOBALS['Join_Date_Time'] = $Get_User_Info_row['Join_Date_Time'];
$GLOBALS['Balance'] = number_format($Get_User_Info_row['Balance'],2);
The above is what is contained in the functions.php which I require with each page I need protected.
As you can see, I barely see where I have done too much wrong there.

Secure Login with PHP

I've been searching around for a long time regarding secure login with PHP. I've found some interesting content, though I'm still not entirely positive on the most secure and simplistic approach.
I've created a simple system, though I'm unsure where it's secure enough. I'll keep this brief as not to smother you with details:
My user table in the database contains a column named "loginToken". When the user logs in, a value is created(based upon that user's id, a random number, and finally sha1 hashed), which is inserted into loginToken of the database user table.
In addition to that, a $_CCOKIE is created with the same value. So these values are completely different to each user, and alternates each time the user logs in.
Now to check the user is logged in, I use this following code:
$user_id = -1; //By default, the user is logged out
if (isset($_SESSION["user"]) && isset($_COOKIE["ut"])) { //Check session and user token exists
//Get variables
$uid = $_SESSION["user"]; //Get user ID
$ut = $_COOKIE["ut"]; //Get user token
//Compare the user id with the user token in the database
$sql = mysql_query("
SELECT COUNT(*)
FROM `users`
WHERE `id` = '$uid' AND `login_token` = '$ut'
");
//Get result
$sql = mysql_result($sql, 0);
//Found!
if ($sql == 1) {
$user_id = $uid; //User logged in!
}
}
Is that understandable? If so, is that a secure enough method?
Thank you!
Your method is not secure. A user could set a malicious cookie, that can do SQL injection on your database.
Use a session variable.
if ($_SESSION['logged_in'] === true) { ...
This is frequently used method.
Generally you want the user to type in username and password over HTTPS secured form. When you receive the request, compare the username, and the hashed version of the password you store in the database, to the hash version supplied by the form. If the hashes match, set $_SESSION['logged_in'] = true.
Later in your code, check that session variable to ensure the user is logged in.

mysql and php - Retrieving data from database based on user logged in

before I go ahead and attempt to create a website, I wanted to know if pulling a users content from a database depending on which user is logged in can be determined by a $_SESSION variable. So for example if I want all the messages for user 'example':
$_SESSION['username'] = $_POST['username'] // set when the user logs in
$username = $_SESSION['username']
$data = mysql_query("Select * from messagesTable where username = '$username'")
while($row = mysql_fetch_array($data)) {
echo $row['message']
}
I wanted to know if this would be the right way to do something like this and also if its safe to return (personal) data based on a session variable.
I haven't got that much experience in either of these languages but I like to learn with experience, please tell me if it's not clear. Thanks.
It is safe to return user data based on a $_SESSION variable if you are certain of its validity because you set it yourself in code. It is not safe to return data based on a session variable that you get from $_POST.
You initially set
$_SESSION['username'] = $_POST['username'];
So unless you have verified with a password or otherwise that this user is who he claims to be, you should not use $_POST['username'] to return other information. If your login process (which we cannot see above) already verifies that $_POST['username'] is valid, you can use it as a source to retrieve additional information.
You will need also to filter against SQL injection:
$_SESSION['username'] = mysql_real_escape_string($_POST['username']);
that isn't standard and probably not safe since phpsession stay open even when a browser tab maybe not be open to the site since the cookie isn't eased until the browser is shutdown and also you could just send a post parameter to the site and get the info too so login scripts are a little more advanced, you could something like have a unique key that is generate upon logging in and when they leave the site using javascript delete the cookie something like that
It wouldnt be the correct way to do it no.
May i suggest you go read the php/mysql docs and or a good book before attempting a website.
You also need to look into security(session hijacking, cross scripting, mysql attacks, form tokens, login systems, user roles/permissions). Google search is your friend...
<?php
session_start();
$username="";
if($_SESSION['username']==true){
$username=$_SESSION['username'];
$conn=mysql_connect('localhost','user','passwd') or die("Unable
to connect to database" .mysql_error());
mysql_select_db('DBName') or die(mysql_error());
$sql="SELECT * FROM tablename WHERE username='$username'";
$retval=mysql_query($sql, $conn) or die("Could not perform query"
.mysql_error());
while($row=mysql_fetch_array($retval)){
echo {$row['message']};
}
mysql_free_result($retval);
mysql_close($conn);
}
else{
return false;
header("Location:login.php");
}
?>

Why does my session-based login system not work?

I have just started learning PHP, and I wrote an account system with PHP and mySQL for my website. I know the sql stuff is working fine, the problem is my PHP session.
When I go to test it, I can try to login, and it fails. Then, I try to login again, and it will succeed. It always succeeds on the second attempt to login. It never succeeds on the first attempt in Firefox, but it does in Chrome. Also, a couple of times in Chrome, after I succeeded in logging in, going to a some different pages on my site seemed to erase the session. Or, at least, that session was not registering on those other pages. I didn't have that problem on Firefox. I have checked, double-checked, and triple-checked, and all of my pages call session_start() before anything else, so I know that can't be the problem.
I must not have a full enough understanding of PHP sessions, as it's just not working consistently.
After posting this, I tested in IE, and everything works fine there. I log in on the first attempt, and any page I visit maintains my session.
Here is the code for the php script that actually "logs in" the user:
<?php
session_start();
//pass info to mysql(servername, username, password)
$connect = mysql_connect ("localhost", "ggstudio", "mtgertai1");
if (!$connect)
{
die ('Failed to connect: ' . mysql_error());
}
mysql_select_db("ggstudio_accountDatabase", $connect);
//capture data sent to page through login
//usernameField and passwordField
$usernameSubmission = $_POST[usernameField];
$passwordSubmission = $_POST[passwordField];
$validAccount = mysql_query("SELECT * FROM userAccounts WHERE userID = '$usernameSubmission' AND userPassword = '$passwordSubmission'");
$row = mysql_fetch_array($validAccount);
if (($row['userID'] == $usernameSubmission)&&($row['userPassword'] == $passwordSubmission))
{
/*********************************
**********************************
assign global variables to session
after starting session and then***
redirect to user homepage*********
**********************************
**********************************
*/
//get account number from database
$_SESSION['accountNumber']= $row['accountNumber'];
//get first name from database
$_SESSION['firstName']= $row['firstName'];
//get last name from database
$_SESSION['lastName']= $row['lastName'];
//save username into session
$_SESSION['username']= $row['userID'];
//save password into session (only really useful if user wants to change password)
$_SESSION['userPassword']= $row['userPassword'];
//get user's email address from database
$_SESSION['userEmail']= $row['userEmail'];
//get GP from database
$_SESSION['gpoints']= $row['userGloryPoints'];
//get user join date from database
$_SESSION['userJoinDate']= $row['userJoinDate'];
//get user rank
$_SESSION['userRank']= $row['userRank'];
header('Location: http://www.glorygamer.com/account_home.php');
}
else
{
$loginFailed= TRUE;
setcookie("incorrectLogin", $loginFailed, time()+20);
header('Location: http://www.glorygamer.com/shibboleth.php');
}
?>
If the session is working intermittently then I'd say there's one of two things happening:
Your session isn't being set in the browser correctly
Your session isn't being saved on the server in time.
One thing that can happen (especially when you're testing on localhost) is that an authenticated session isn't written to disk in time for the next request, hence the next request appears to be un-authenticated (remember that apache is multi-process; your second request could be handled by another process which isn't aware of what the first is doing). Here's one possible solution:
$_SESSION['userRank']= $row['userRank'];
session_write_close();
header('Location: http://www.glorygamer.com/account_home.php');
The call to session_write_close() should mean that your authenticated session is ready in time for the next request.
HTH.
The first thing I see are the lack of single quotes. Also, you should definitely escape these so that nobody can do any SQL injection on you.
$usernameSubmission = $_POST[usernameField];
$passwordSubmission = $_POST[passwordField];
should be:
$usernameSubmission = mysql_real_escape_string($_POST['usernameField']);
$passwordSubmission = mysql_real_escape_string($_POST['passwordField']);

Why do my sessions persist on other pages when visited manually but not when following a link?

I created a user account system for my website using PHP sessions and mySQL. I have been trying for SO LONG to get it to work right. The very first night it worked 'mostly' right. And I have made almost no progress since then. I've been researching and googling until I've burnt out, and I haven't figured it out.
The problem is, I can create user accounts fine, and it registers as planned in my sql database, and I can even login correctly. However, when I go to other pages on my site, the session doesn't seem to be registered on those pages. I check for the user's session with
if (isset($_SESSION['username']))
and if they are not logged in, a 'login' button appears in main menu on every page. If they are logged in, a button with their username appears that links to their account page. If you would like to see for yourself, www.glorygamer.com is the website and you can use testAccount with password as the password to login and see.
Here's the weird part. Today I made a discovery, and now I am CERTAIN it isn't a problem with my PHP script. If I manually enter in the page I want to visit (if I literally type "www.glorygamer.com/account_home.php" then it works perfectly. The session always starts properly with any page I visit in this way. However, when I click on links in my menu, it seems to work almost at random. Sometimes I will be sent to the next page and the session will be started correctly, and sometimes it won't be.
Is there some special way I need to link my pages, even though they all correctly session_start() before anything else?
Here is the login script:
<?php session_start();
//pass info to mysql(servername, username, password)
$connect = mysql_connect ("localhost", "***", "***");
if (!$connect)
{
die ('Failed to connect: ' . mysql_error());
}
mysql_select_db("ggstudio_accountDatabase", $connect);
//capture data sent to page through login
//usernameField and passwordField
$usernameSubmission = $_POST['usernameField'];
$passwordSubmission = $_POST['passwordField'];
$validAccount = mysql_query("SELECT * FROM userAccounts WHERE userID = '$usernameSubmission' AND userPassword = '$passwordSubmission'");
$row = mysql_fetch_array($validAccount);
if (($row['userID'] == $usernameSubmission)&&($row['userPassword'] == $passwordSubmission))
{
/*********************************
**********************************
assign global variables to session
after starting session and then***
redirect to user homepage*********
**********************************
**********************************
*/
//get account number from database
$_SESSION['accountNumber']= $row['accountNumber'];
//get first name from database
$_SESSION['firstName']= $row['firstName'];
//get last name from database
$_SESSION['lastName']= $row['lastName'];
//save username into session
$_SESSION['username']= $row['userID'];
//save password into session (only really useful if user wants to change password)
$_SESSION['userPassword']= $row['userPassword'];
//get user's email address from database
$_SESSION['userEmail']= $row['userEmail'];
//get GP from database
$_SESSION['gpoints']= $row['userGloryPoints'];
//get user join date from database
$_SESSION['userJoinDate']= $row['userJoinDate'];
//get user rank
$_SESSION['userRank']= $row['userRank'];
session_write_close();
header('Location: http://www.glorygamer.com/account_home.php');
exit;
}
else
{
$loginFailed= TRUE;
setcookie("incorrectLogin", $loginFailed, time()+20);
session_write_close();
header('Location: http://www.glorygamer.com/shibboleth.php');
exit;
}
?>
It sucks, I am lacking 6 points for commenting on questions, thus I have to use an answer… In my tests it rather seemed your problem is script dependant as I cannot see the logged in status on the top right even if I am visiting another URL (e.g. www.glorygamer.com/index.php) from outside. That’s obviously clear, as there is nothing different between a link and the same URL without a link except the Referer header.
The only site which I can see my logged in status on is the mentioned www.glorygamer.com/account_home.php
The session cookie is always existing and sent (checked with Live HTTP Headers) and therefore must also be reiceved on index.php (where the username is not displayed in the top right corner, but instead "Login").
So you should check if session_start() really works in these files. Also check for posibble surpressed error messages, as session_start() would throw an error if there was any output before session_start() (either via echo, var_dump, print, print_r or pure HTML outside of PHP blocks). I am not sure if you can oppress that error messages, but I guess you can with the "right" server settings.
Hope my hints can get you a little further to your solution.
This comment on php.net sounds like a similar situation to the one you're in, though I don't know why session_write_close would cause the problem you're having.
Rather than replace with session_regenerate_id() as the comment suggests, I'd recommend you simply remove session_write_close() to see if this bears fruit.
It's not an answer to the actual question, but nevertheless important:
Please always escape any user-input data before passing it along to the database.
This:
$usernameSubmission = $_POST['usernameField'];
$passwordSubmission = $_POST['passwordField'];
$validAccount = mysql_query("SELECT * FROM userAccounts WHERE userID = '$usernameSubmission' AND userPassword = '$passwordSubmission'");
should read:
// Any data entered by a third party is insecure
$usernameInsec = $_POST['usernameField'];
$passwordInsec = $_POST['passwordField'];
// Protect your SQL statements
$validAccount = mysql_query(
"SELECT * FROM userAccounts "
. " WHERE userID = '" . mysql_escape_string( $usernameInsec ) . "' "
. " AND userPassword = '" . mysql_escape_string( $passwordInsec )
. "'"
);

Categories