Are sessions modifiable by the client/user? - php

In my PHP Web-App I use sessions to store the user's data. For exmaple, if a user logs in, then an instance of the User class is generated and stored in a Session.
I have access levels associated with each user to determine their privileges.
Store the user in a session by:
$_SESSION['currentUser'] = new User($_POST['username']);
For example:
if($_SESSION['currentUser'] -> getAccessLevel() == 1)
{
//allow administration functions
}
where getAccessLevel() is simply a get method in the User class that returns the _accesslevel member variable.
Is this secure? Or can the client somehow modify their access level through session manipulation of some sort?

No, the client cannot modify their access level. The only thing stored on the client is the session key which is either propagated via cookie or GET parameter. The session key ties to a corresponding session record which is a file stored on the server side (usually in a temp directory) which contains the 'punch'.
What you don't want, is for a session key to get leaked to a third party:
A leaked session id enables the third
party to access all resources which
are associated with a specific id.
Take a look at this: http://www.php.net/manual/en/session.security.php

The session information is stored on the server and the user only has access to a key. In practice I have used something of this sort, with extra steps. After validating the user details and storing the User object, I would have a query that is run when viewing any of your protected pages to validate what is in the session is okay with what they're trying to view.
In the top of your page.php
if(!validUser($user)){
// Relocate the user
}
where
validUser(User $user)
{
// Some query to verify the information in the session
// Return the results of verification
}

I thought the only way for the user to manipulate something like that was if it was stored in a cookie on the users computer.
Is the getaccesslevel stored to a cookie or is it called from the server only after checking the login cookie and not stored on the users computer?
I would assume that if it is called on the server only after the user is logged in then they would not be able to easily manipulate that other than through other means of security holes.
Just my guess tho, im not that great with security myself yet. I will keep an eye on this to see what others have to say and maybe I can learn something.

Related

How to add security while using GET and POST method?

I developed a small application Contact Manager and while updating the contacts, the contact id is being sent using GET method. But a user can change the Id and edit any contact, how can i add security to it?
<td>
Update
</td>
http://localhost/contmanager/home.php?action=update&contactid=1
If i change the id to some other number, another contact will show up.
You can't control what the client asks the server to do.
If you want to add restrictions on who can modify particular contacts then you need to Authenticate (username + password, client SSL cert, OpenID, etc) users and then check if they are Authorized (this will depend on the business logic you decide on) to modify the entry in question.
As Quentin pointed out, your logic is going wrong here, data like these should be stored inside sessions and shouldn't be passed using $_GET or $_POST, unless and until required, if you still need to pass for some reason, than you can read my answer ahead for a solution.
Store the user id in a session, so when the user updates, just compare the session id and $_GET id, if it matches, update the entry else throw an error.
When the user logs in
$_SESSION['user_id'] = $db_data['col_name'];
Now, before the entry is updated...
if(!empty($_GET['user_id'])) {
//First validate, you can check whether the id is only numeric, is valid db entry etc
$user_id = $_GET['user_id']; //Store the id in a variable
} else {
//Invalid
}
if($_SESSION['user_id'] == $user_id) { //Compare the ids
//Process
} else {
//Not Valid
}
Note: Make sure you use session_start() at the very top of the page,
before you start writing anything.
You need to use session and to store the data inside like this:
<?php
session_start();
$_SESSION['contact_id']=$contact->contact_id;
<td>Update</td>
?>
use it like this:
http://localhost/contmanager/home.php?action=update
and when you need to use contact_id(after the GET) :
session_start();
if(isset($_SESSION['contact_id']) && !empty($_SESSION['contact_id'])){
$contact_id=$_SESSION['contact_id'];
}
A PHP session variable is used to store information about, or change settings for a user session. Session variables hold information about one single user, and are available to all pages in one application.
PHP Session Variables
When you are working with an application, you open it, do some changes and then you close it. This is much like a Session. The computer knows who you are. It knows when you start the application and when you end. But on the internet there is one problem: the web server does not know who you are and what you do because the HTTP address doesn't maintain state.
A PHP session solves this problem by allowing you to store user information on the server for later use (i.e. username, shopping items, etc). However, session information is temporary and will be deleted after the user has left the website. If you need a permanent storage you may want to store the data in a database.
Sessions work by creating a unique id (UID) for each visitor and store variables based on this UID. The UID is either stored in a cookie or is propagated in the URL.

Security in php session cookies

I am trying to understand security when it comes to session cookies in php. I've been reading a lot about it, but I still lack the specifics. I need the basics, someone to show examples.
For example: Do I place session_regenerate_id() before every session cookie? What more shall I think about. I am asking about specifics in code - examples if possible.
Thank you very much.
I am using 4 session cookies after logging in.
SESSION "site_logged_in" = true
SESSION "site_user_nr" = the number of the user to access user_table_nr
SESSION "site_user_id" = the user's id to use when changing data in tables
SESSION "site_user_name" = the name of the user to display on page
When I check if the user has access, I check if all 4 cookies are set, and if site_logged_in is set to true.
Are there better ways? Do I have the completely wrong idea about this? Can users easily be hacked?
In fact you need to have only one session in your website. When you call session_start() session is being created on server and user automatically gets session cookie. Think like session is a some sort of container that placed on the server, you can put whatever you want in that container. However session cookie is just a key to access that container on the server.
It means that you can safely put some data in the $_SESSION and only the user that have cookie with matching session id can read it.
About users being hacked. Yes they can be hacked as long as you don't use HTTPS connection, because cookies and all other data is being transferred in clear text, so if someone intercept users cookie he can access the data stored in the session.
Always use a security token for logging users. This security token could be generated by using crypt(). After logging users in, change the security token periodically until they log out. Also keep the server backup of all the session variables including the security token (in a database). This would also help you to track user login history.
One more personal suggestion: Never use any data from the database as session variables without encrypting it with any of the hashing functions or functions like crypt().
The session information is stored server-side. What you should check is that they're logged in, and that they exists/can log in (in case of deletions/bans).
As you're checking they exist/can log in, you can pull the other information from the database such as name, nr and so on. All you really need is a key called 'logged_in_user' or something that stores the ID of the logged in user. As Alex Amiryan said, the cookie can be copied, so you might also want to store the IP address of the last accessing view in the session, so you can try to ensure security.

How to destroy a specific PHP session

I am looking for insights into how to destroy a specific session in PHP. Through a partner website a user logs into the main website using a token and obtains a full session.
It is also possible for the partner website to call a destroy function if the user logouts from the partner website. We should then also log out our own user.
What is the best approach to this? The Zend_Session destroy method does not accept a parameter, similarly the PHP function session_destroy does neither.
I am considering two options:
Removing the session information directly from file/memcache but would prefer a "cleaner" approach than this.
Checking at every page request if this is a "token" user ; and if then check if their token was expired by maintaining a list. This adds overhead to a busy website, but might be my only option.
Or is there a third / better approach I am not seeing?
There's no need to roll-your-own session handling.
session_id() can take a parameter, the session id you want to work with.
So, when you pass the user off to the partner site, pass along their session_id (or some token, or whatever).
Then allow the partner site to hit a script like this:
kill-user-session.php
<?php
/**
* Destroy any active session identified by $_POST['sid']
*/
session_id($_POST['sid']);
session_start(); //this line may not even be necessary
session_destroy(); //destroys that session.
So when the user logs out on the partner site, the partner site POSTs the session_id (that you gave them) to your kill-user-session script, and the user's session is destroyed on your server.
Of course, you probably want to limit access to kill-user-session.php via some method or another.
If you wish to be able to 'kick' the sessions of a user(s), the only way you can do it is if you use MySQL (or someother db, sqlite even) for your session storage.
Then you can simply remove entries from the db to kill a session.
This also allows you do do things such as, 'take control' of a specific user's session and other stuff :)
See this for a very basic run through: http://www.devshed.com/c/a/MySQL/Custom-Session-Management-Using-PHP-and-MySQL/ (not the best example but good enough full example to start you).
EDIT
Also, if logging out through the partner site, another method I have used in the past (which was with O2 and other such sites) they were given a 'callback' (REST API call in most cases) which they would also need to call when the user logs out of their site.
The database solution means that the session database needs to be shared between mainwebsite and the partner site, which frequently isn't the case etc. Maybe something along these trivial lines would suffice?
<img src="mainwebsite/logout.php">
mainwebsite/logout.php:
<?php session_destroy(); ?>

Codeigniter/PHP sessions security question

I'm developing a web application using Codeigniter. When a user authenticates with my site I'm currently storing their 'user-identifier' in my session cookie (which I have enabled encryption on). Several of my model classes use the value in 'user-identifier' parameter of the session/cookie to make changes to properties of user accounts.
My concern is that I'm wondering if it's possible for someone to take a valid codeigniter-session cookie with a user-identifier that I've set, change the user-identifier's value to the value of a different user, and make changes to another user's account. Would codeigniter/php sessions create an error if someone attempted to change a property of a session cookie?
Open your /application/config/config.php, locate "sess_use_database" and change it to "TRUE" if you haven't already. This way all session variables will be stored in a database table and session cookie will only contain session id string.
For added security, you can also change "sess_match_ip" to TRUE. This way if someone steals your user's cookie and tries to pass it as their own, session will be destroyed.
"if
it's possible to take a
valid codeigniter-session cookie
change the user-identifier's value to
the value of a different user, and
make changes to another user's
account."
My answer is not really CI related, so please bear that in mind.
When you auth the user "username1" what should be sent back to the client, for auth purposes, should be a hash that the server correlates to that user. All communication between the client and the server will rely on that hash.
The server will generate a unique hash per user and the hash should have a short time to live. Can someone capture a hash and pass as that user? Certainly. That's why you should also check for the user's Agent and IP to check if they match the hash in order to prevent session hijacking.
NEVER DO THIS:
If seen some new developers storing the username in a cookie and reliing on that client sent variable to update their databases. Never do this. Do not ever, ever trust the client. When the server gets the client's hash it should check if it belongs to an authenticated user and grab the user_id (variable to update the user data) from the server. NEVER from the client.
I'm not sure what your "user identifier" is exactly. The general rule is, don't store anything in the session cookie but the session ID. Store everything else (like a user ID) internally on server side, and retrieve it using the session ID.
If the user changes the session ID (which is a random string), a new session will start. The idea behind the session ID is that it's impossible to guess other user's IDs - that's why it's random, and so long.

Update another user's session - best practice?

As in many web applications, when my users log into my site, I set several session variables that control permissions for accessing site functionality.
Whenever a user undertakes an action that would result in a change to those permissions, I update the session variables as part of the normal processing flow.
But sometimes a user's session needs to be updated based on the actions of another user. For example, a moderator upgrades a user's permissions. The moderator does not have access to the user's session space, so the normal update functions cannot be run for the affected user.
I have considered a few ways of forcing an update to another user's session, but they all have drawbacks:
I could search for and delete their
session from the sessions table, but
this requires a full table scan
(where sessdata like '%user_id%'),
and it could cause the loss of
content that the affected user may be
engaged in generating.
I could force a session update
periodically, such as when
sess_time_to_update is triggered.
But there is no guarantee that this
will transpire prior to the user
attempting to access the
functionality for which the update is
needed.
I could run a complete series of
variable updates on every page load,
but the whole point of maintaining a
session is to avoid that overhead.
I could set a flag indicating the need
for a session update, but that signal
would have to be interrogated at every page execution, and in every controller. (I know that I could extend CI_Controller as MY_Controller, but I don't want to do that)
I'm already sending the user an email
notifying them of the change in
permission, and it's easy enough to
make them click a session update link
(or even log out and log back in).
But there's no guarantee they are
going to even read beyond the subject
line, let alone actually click the
link.
So is there anything I'm missing? Am I looking for a magic bullet that does not exist?
(Note that I've tagged this with CodeIgniter, and made reference to CI-specific technical details, because that's what I'm using. That said, this isn't a CI-specific (or even a PHP-specific) issue.)
Thanks for the help!
Well, one option would be to set an "ACL Version" number (either for all users, or for each user). Then when initializing the session (well, when you call session_start()) check to see if the stored version matches the session's version. If it doesn't, refresh the ACL.
Another slightly different way would be to add a column to the sessions table ("status" or "dirty", etc). Then, instead of killing the session, simply update that status to 1. Then when loading the session, check that flag to see if it's 1. If so, reload the cached data in the session and set it to 0. If not, continue on...
As far as updating another user's session, I wouldn't do that... If sessions are managed by PHP, then you'll need to kill the current session and start the one you want to modify. That's just asking for problems... (you need to do that, since PHP's mechanism does not use serialize.).
As far as deleting their session, I wouldn't worry about the full table scan. Unless you have a TON of users updating permissions all the time, it's not going to matter. The data loss is a significant concern, so that nicks that idea...
As far as the other 2 options, I think you hit the nail on the head, so I have nothing else to offer on them...
I'm going to take a stab, though my approach is not entirely applicable to Code Igniter.
The way I've solved this problem in the past is to make a User object model with a constructor that takes the UserID from the database primary key where the credentials are stored. I'll write a static login method that checks login credentials and then instantiates and returns an instance of user if the login is correct for a row and then sets the session.
So far so good, right? So all your permissions, access levels etc are stored in the database. Just like having a login method, we can have a refresh method that reinstantiates the object, re-fetching from the db off the already obtained primary key.
class User{
public function __construct($uid){
//fetch from the db here
$sql = 'SELECT FROM User_Table WHERE UserID = ?';
$params = array($uid);
//fetch and assign using your flavor of database access, I use PDO
//set all your object properties for access, as well as user_id, something like
//$this->user_id = $result['UserID'];
}
public static function Login($uname, $pass){
$sql = 'SELECT UserID FROM User WHERE Username = ? AND Password = ?';
$params = array($uname, md5($pass));
//again I'm going to employ pseudocode here, fetch according to your preferred system
if(!empty($result)){
$_SESSION['user'] = new User($result['UserID']);
}else{
//login failed!
return false;
}
}
final public function _refresh(){
//refresher method. Since the controller sets all the object properties for access
//reconstructing and assigning it refreshes these priveliges.
$_SESSION['user'] = new User($this->user_id);
}
}
Using this model, whenever I am performing an action with the user in the session that might potentially need time-sensitive permissions, I can call refresh on the user object all ready in the session. Let's say we have a controller function to access a restricted form.
function _topSecret(){
$_SESSION['user']->refresh();
if($_SESSION['user']->specific_permission_from_db){
//Perform the special action, get the view, whatever.
}else{
//redirect to an error page
}
}
So if you already have routines written for the admins, all they need to do is set the user's privileges in the database, and when the refresh method runs on the specific, time-sensitive functions, that data will be put in the session for the user. So you're not necessarily updating another user's session, you're just determining which actions are so chronologically sensitive they require the newest permissions and issuing that command to the user object in the session.
This has proven pretty efficient for me, since reconstructing need only be performed on actions that need the most up to date permissions. Again, I'm not sure how useful it may be in the context of CI and your individual application, but I figured I'd share. I'm assuming you've already done all the necessary session security measures and started the session - most frameworks like CI will handle this for you through their native means.
Add a column in the session table that can hold the primary key of the user object. Set it upon login and use it later to update the session.
Edit: If you don't want to extend the session table, make an additional lookup table where you have the user object id and the session key link.
If your're storing the session as a native php session I'd tend to leave it alone, and allow them to get some kind of notice that they need to login/out to refresh the setting. I've also had sites where the session data is stored in the db and then its much more trivial to just write the new setting in.

Categories