Welcome Guest, Not a member yet? Register   Sign In
Authentication and Sessions
#1

[eluser]Joseph Wensley[/eluser]
I've built my own authentication system for a project but I just realized I have a security hole I'm not completely sure how to fix it.

I'm using CI's built in session management and checking the session to see if the user is logged in.

Code:
function is_loggedin()
    {
        //Get an instance of the Codeigniter object
        $CI =& get_instance();


        if($CI->session->userdata('logged_in') == TRUE)
        {
            return TRUE;
        }else{
            return FALSE
        }
    }

But I've realized if a user is deleted they won't be logged out until the session expires.

My two solutions that I've thought of are to only store the users id and check the database every time this is_loggedin() is called OR check the user_data of every session in the DB and delete any that are from the user being deleted.

Any thoughts about which of these would be the best way to go about it or is there another option I am not thinking of.
#2

[eluser]Ben Edmunds[/eluser]
Truthfully most auth libraries probably don't account for this. I know Ion_Auth doesn't...

The best way is to probably just check the session against the db on the is_loggedin() call.
#3

[eluser]Peng Kong[/eluser]
am i missing something or is it just as simple as calling logout() before calling delete_user()?
logout() in your case would mean something like

Code:
$CI->session->unset_userdata('logged_in');

well, that's if the user is deleting himself/herself.

if the admin is deleting the user... we'll let me think about that =p i'm doing a authentication library too. But in my auth library you can't delete a user (as in delete row from database) you only can flag him as 'deleted'.
#4

[eluser]Peng Kong[/eluser]
Instead of storing a boolean in session i'm storing the logged in user's ID.
With that ID i can pull the logged in user object from the database.
Then i can check if $user->is_banned() or $user->is_deleted()
When logging out i delete the user's ID from session.
so if the admin ban of deletes the user... the user will know straight away (when he refreshes the page)
#5

[eluser]Michael Wales[/eluser]
Holy smokes... so many things wrong here. I'm not trying to offend, but this is why you should not build an authentication system unless you understands the ramifications of doing certain things. Just the thought that I may have accidentally registered on one of your sites frightens me:

Quote:if($CI->session->userdata('logged_in') == TRUE)
You're telling me all I have to do is flick a variable and I am logged into your site? I don't need a username/password or anything - all I have to do is spoof a session?

Quote:But I’ve realized if a user is deleted they won’t be logged out until the session expires.
Exactly - for that reason, and the reason above, you need to check it against the database every time.

Quote:Instead of storing a boolean in session i’m storing the logged in user’s ID.
Oh hell's yeah - now I can login as any user I want just by changing an integer! SWEET!
#6

[eluser]Peng Kong[/eluser]
Sorry Michael, maybe there's something you know that I don't. Don't worry there's really no offense taken, maybe I can get to learn something new here.

Please teach me how to hijack and spoof a CI Session that uses encrypted cookie and database.

And EVEN if the cookie wasn't encrypted... and EVEN if you could spoof the session (by stealing or recreating the cookie before the 5 min refresh, and matching the ip address and user agent) how would you change the "integer" in the database for the session you managed to spoof and be logged in as anyone you like?

Also isn't that what dx_auth, tank_auth and all other auth libs do?

dx_auth

Code:
// Set session data array
        $user = array(                        
            'DX_user_id'                        => $data->id,
            'DX_username'                        => $data->username,
            'DX_role_id'                        => $data->role_id,            
            'DX_role_name'                    => $role_data['role_name'],
            'DX_parent_roles_id'        => $role_data['parent_roles_id'],    // Array of parent role_id
            'DX_parent_roles_name'    => $role_data['parent_roles_name'], // Array of parent role_name
            'DX_permission'                    => $role_data['permission'],
            'DX_parent_permissions'    => $role_data['parent_permissions'],            
            'DX_logged_in'                    => TRUE
        );

        $this->ci->session->set_userdata($user);
Code:
// Check if user is logged in
    function is_logged_in()
    {
        return $this->ci->session->userdata('DX_logged_in');
    }


tank_auth

Code:
// Login user
                        $this->ci->session->set_userdata(array(
                                'user_id'    => $user->id,
                                'username'    => $user->username,
                                'status'    => STATUS_ACTIVATED,
                        ));
Code:
function is_logged_in($activated = TRUE)
    {
        return $this->ci->session->userdata('status') ===
($activated ? STATUS_ACTIVATED : STATUS_NOT_ACTIVATED);
    }
Simplelogin

Code:
//Set session data
                $this->CI->session->set_userdata(array('id' => $user_id,'username' => $user));

ReduxAuth
Code:
$this->session->set_userdata($identity_column,  $result->{$identity_column});

i could list 10 more example that store ID in session to consider a user signed in.

maybe we're all wrong and shouldn't write authentication stuff... =(

How would you consider a user signed in without storing ID in session?

Please enlighten!
#7

[eluser]Michael Wales[/eluser]
You're making a lot of assumptions here though - you are assuming the developer has session encryption turned on and is using database storage of the session (which has its own set of pros/cons).

Your post also made it seem as if your authentication library was only storing the ID - no other information, which is obviously a bad idea.

Wouldn't it be exponentially more secure to store the user ID and a hash of some of the user's data in the session? This simple change, regardless of the application's configuration, gives you the means to identify the user (the ID) and validate the session data hasn't been tampered with (the hashed data from their record).
#8

[eluser]Peng Kong[/eluser]
sorry i wasn't clear... haha i just trying to answer his question on how to not have the user still logged in after deleting user from db.

so my answer was store the id instead of boolean... then get the object from db.

you're right i was assuming db =x
#9

[eluser]Peng Kong[/eluser]
[quote author="Michael Wales" date="1265405068"]
Wouldn't it be exponentially more secure to store the user ID and a hash of some of the user's data in the session? This simple change, regardless of the application's configuration, gives you the means to identify the user (the ID) and validate the session data hasn't been tampered with (the hashed data from their record).
[/quote]

Interesting~... and that's an good idea Michael.

I didn't really think about "regardless of the application's configuration" part since I thought it was obvious you shouldn't store the id IN a plaintext cookie (which user can edit) and use it straight away to consider the user authenticated! okay never mind you're right... bad assumption.

i mean hell~ i wont even store it with some encrypted hash... someone might figure out how you're hashing it and there goes security. and isn't that still vulnerable to spoofing and session fixation?! even though you can't edit the id because you can't guess the hash?

Wow but it looks like alot of other auth libraries also didn't consider the fact that a programmer might have his ci session setting not using db.

using db for ci session does have it's pro & cons but NOT in the case where you're using it for authenication imo. There's no option you have to use db. don't store anything in a cookie seriously just store it in the database. cookie is just there to say you own this session in db. there's no security w/o db.
#10

[eluser]Michael Wales[/eluser]
Quote:using db for ci session does have it’s pro & cons but NOT in the case where you’re using it for authenication imo. There’s no option you have to use db. don’t store anything in a cookie seriously just store it in the database. cookie is just there to say you own this session in db. there’s no security w/o db.

I definitely agree but as library authors we have to assume the worst.

Quote:i mean hell~ i wont even store it with some encrypted hash… someone might figure out how you’re hashing it and there goes security. and isn’t that still vulnerable to spoofing and session fixation?! even though you can’t edit the id because you can’t guess the ash?

Remember the difference between encrypting and hashing - hashing is one way. Sure, a rainbow table is going to find the hash for integers pretty quick, but it would take quite awhile for a rainbow table to find the hash for an unknown combination of data (let's say, a concatenation of the user's salt, username, password, and timestamp of record creation). That's where the true security lies in this - you grab their ID and token (the concatenation hash), select on the DB, hash their record and see if it matches the token. If not, something has been tampered with.

Quote:Wow but it looks like alot of other auth libraries also didn’t consider the fact that a programmer might have his ci session setting not using db.

Yeah, I'm usually over-careful with working with sessions because I remember CodeIgniter when it didn't store custom userdata in the database. You could turn on database storage but it only stored the standard fields in there, all custom data remained in the cookie.




Theme © iAndrew 2016 - Forum software by © MyBB