SitePoint Sponsor

User Tag List

Results 1 to 14 of 14
  1. #1
    The Hiding One lynlimz's Avatar
    Join Date
    Jul 2000
    Location
    Singapore
    Posts
    2,103
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi,

    Is there a secure method of using a cookie to store Login Information? Like encrypt the password, then store in a cookie.

    or using sessions...etc.?

    Advise please? Thanks
    "Imagination is more important than knowledge. Knowledge is limited. Imagination encircles the world."
    -- Albert Einstein

  2. #2
    The Hiding One lynlimz's Avatar
    Join Date
    Jul 2000
    Location
    Singapore
    Posts
    2,103
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey! I found an article which addresses my queries...so here's it!

    http://www.zend.com/codex.php?id=250&single=1
    "Imagination is more important than knowledge. Knowledge is limited. Imagination encircles the world."
    -- Albert Einstein

  3. #3
    SitePoint Zealot
    Join Date
    May 2000
    Posts
    150
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Correct me if I'm wrong, but... won't this code break up if the secret hash is found out!

    For example, if the php source is compromised, anyone can login as anyone else.

    Also, the session times out 36,000 seconds after a user logs in. It doesn't refresh itself whenever the user requests a page. It would be better if the session timed out after 3600 seconds of inactivity.

    Regards,

  4. #4
    Database Jedi MattR's Avatar
    Join Date
    Jan 2001
    Location
    buried in the database shell (Washington, DC)
    Posts
    1,107
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wow!

    That's my code! (click on the mailto: if you don't believe me )

    It won't totally break up -- you still need to know what the original string (password) was to "forge" it. If someone finds out the key then it is as secure as any other MD5 cookie. With the string (server 'salt' it is called) someone couldn't brute-force your passwords since an MD5 hash of their passwords would never match my MD5 hash + another server-only hash.

    As an example assume my password is "bobross" .
    MD5( "bobross" ) is something like :
    123445465546lkfdjglkdjfg

    So if you had enough time you could continually run random characters through a generator and guess what the password was eventually.

    However with the salt you'd end up with:
    MD5( $password + MD5( "something secret and no one will guess" ) );
    234kjdflkjsdfkljlk3jlkjlkjdfklj

    So even if you find a match (say with "ihatespam") you still can't log in with it.

    There are also quite a few other security mechanisms built in with the $hash and I'll leave that as an exercise for you to figure out how it tries to defeat hackers in interesting ways.

    If you do somehow get PHP "broken" then someone forging a cookie is the LEAST of your worries. But all you have to do (and I should have specified) was place secret.php outside of the web tree so that if this does happen you still can't get users viewing secret.php and finding out your magic key.

    However this method will disallow users from, say, copying the cookie over to a different machine and logging in from there and such.

    I wrote this for a company intranet where it was assumed that we don't want employees left logged in for more than 8 hours or so (I think 36,000 seconds is 8 hours, not sure).

    To make it update you'd just insert some code into verify( ) that would update all of the cookies (essentially reset them) with the current time + something.
    Last edited by MattR; Apr 16, 2001 at 22:45.

  5. #5
    SitePoint Zealot
    Join Date
    May 2000
    Posts
    150
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Updating the cookies everytime they are verified will solve the second problem. If you keep the secret.php file
    outside the web readable space, it would help.

    However, I still think there might be a problem if the hacker manages to get the secret key. Say hacker requests a password protected page:

    http://mydom.com/protected/adMANAGE.php

    The above file calls function 'validate' to see if the user has logged in.

    Code:
       adMANAGE.PHP
       --------------
    
        <?PHP   
          if( validate( $username, $session_key, $expiration_time, $hash ) ) { 
          ?> 
    
          Yes you are! 
    
          <? 
            } else { 
          ?> 
    
          No you are not! 
    
          <? 
            } // end if 
          ?>
    Assume hacker knows secret key:
    $secret = md5( "sdfkjsdkflhkh23hkjsdk#$@%$#%DSF" );


    - Hacker requests password protected page.
    - Passes cookies:

    $username = 'victim'
    $session_key = 'somesessionid' . $username
    $expiration_time = CURRENT_TIME + 36000
    $hash = md5 ( $username . $session_key . $expiration_time . $secret );

    - adMANAGE.php validates user:

    Code:
          $h = md5( $username . $session_key . $expiration_time . $secret ); 
    
          if( $hash == $h && time( ) < $expiration_time ) { 
            return 1; // WILL ALWAYS RETURN TRUE!
          } else { 
            return 0; 
          }
    Won't this validate the hacker and let him through?

    There will be absolutely no need to know the victim's password since none of the hashes are a function of the victim's password.

  6. #6
    SitePoint Enthusiast nguip's Avatar
    Join Date
    Apr 2001
    Location
    Malaysia
    Posts
    95
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wow...

    That's an amazing code But, I'm still a newbies... can you show me some example how to use this code ?

    Thanks
    Ngu I.P.
    Web Developer

  7. #7
    The Hiding One lynlimz's Avatar
    Join Date
    Jul 2000
    Location
    Singapore
    Posts
    2,103
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    that makes sense arpith


    so many we should make the session key...part of the password and the secret code too?

    wow...cool MattR!!!!!
    LOL

    What if someone disables cookies? then the whole authentication would break...hmm..that what I'm concerned too..
    "Imagination is more important than knowledge. Knowledge is limited. Imagination encircles the world."
    -- Albert Einstein

  8. #8
    SitePoint Zealot
    Join Date
    May 2000
    Posts
    150
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes, the password should probably be included as part of the hash.

    It would be nice if you actually verified that the hash was valid by storing it locally on the server. Then, during validation, the script would not only verify the hash, but also check to make sure that the session from the user was created locally. The timeout check should also probably be implemented on the server side (instead of depending on the client to hold the expiry date value).

    I reckon without cookies, it would be very messy to implement such a system... perhaps one holding the session ID in the query string,?? :-)

    Cheers,

  9. #9
    Database Jedi MattR's Avatar
    Join Date
    Jan 2001
    Location
    buried in the database shell (Washington, DC)
    Posts
    1,107
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well I'll be.... All my talk of passwords and I didn't even include it in the hash!! How did I leave out the password!

    Basically this code is secure if you assume that people can't get to secret.php which, depending on your view of life, is a good or a bad thing. I'm kind of leaning tward bad thing but if your site is hacked in the first place it's time you looked at the way you do things.

    I guess the thought was is that if you secure that PHP file w/ the hash in it, you can create relatively secure sessions w/o having to continually check a database and see if the username and password combo is valid.

    I've seen a number of sites where they have a single ID which is set when a user logs in, the site then assumes that $userid is secure for the rest of the time. If not, they set a $password and verify that each time leading to a number of database hits.

    I'm trying to think of a way to integrate the password like I thought I did (I haven't used this code in a long, long time) so we could save a DB query on each page that wanted to know.

    Maybe:
    PHP Code:
    <?PHP  
    // secret.php: 
      
    $secret md5"sdfkjsdkflhkh23hkjsdk#$@%$#%DSF" );  
    ?> 

    <?PHP 
    // validate.php 

    /////////////////////// 
    // Function Name   : validate 
    // Function Purpose: Validates the user's ticket and makes sure they are logged in 
    // Recieves        : $username - the username of the current user; 
    //                   $session_key - the session key of the user; 
    //                   $expriation_time - how long till the ticket expires?; 
    //                   $hash - hash of all three of those + server secret;
    //                   $passhash - password of the current user
    // Returns         : 1 if validated, 0 otherwise 
    /////////////////////// 
    function validate$username$session_key$expiration_time$hash$passhash ) { 

      include 
    "secret.php"

      
    $h md5$username 
                
    $session_key 
                
    $expiration_time 
                
    $secret.
                
    $passhash ); 

      if( 
    $hash == $h && time( ) < $expiration_time ) { 
        return 
    1
      } else { 
        return 
    0
      } 
    // end if 

    // end function validate 

    // end validate.php 
    ?> 


    <?PHP 
      
    // login.php 
      // do some login type stuff 
      // username and password verified via some method; 
      // $username holds the contents of their username 
      // $password holds the contents of their password
      
      
    require( "secret.php" ); 

      
    $session_key microtime( ) . $username

      
    $expiration_time time( ) + 36000

      
    $passhash md5$password $secret );

      
    $hash md5$username 
                   
    $session_key 
                   
    $expiration_time 
                   
    $secret .
                   
    $passhash ); 

      
    setcookie"username",        $username,        time( ) + 36000"/"""); 
      
    setcookie"session_key",     $session_key,     time( ) + 36000"/"""); 
      
    setcookie"expiration_time"$expiration_timetime( ) + 36000"/"""); 
      
    setcookie"hash",            $hash,            time( ) + 36000"/"""); 
      
    setcookie"passhash",        $passhash,        time( ) + 36000"/"""); 

    // end login.php 
    ?> 

    <?PHP 
      
    // make login.php the result of some sort of form, or just include it and add a username var 
      //require( "login.php" ); 
      
    require( "validate.php" ); 
    ?> 
    <HTML> 
      <HEAD>Logged in?</HEAD> 
      <BODY> 
        <P>Are you logged in?</P> 
        <?PHP 
          
    if( validate$username$session_key$expiration_time$hash$passhash ) ) { 
          
    ?> 

          Yes you are! 

          <? 
            
    } else { 
          
    ?> 

          No you are not! 

          <? 
            
    // end if 
          
    ?> 
        ?> 
      </BODY> 
    </HTML>
    That seems like a good way to integrate the password into the hash so that you don't have to go and make DB reads every time you want to validate the user.

  10. #10
    The Hiding One lynlimz's Avatar
    Join Date
    Jul 2000
    Location
    Singapore
    Posts
    2,103
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmm...Yeah...
    It seems that I can't venture beyond my registration...or my project...lol

    I need to get these sorted out first. Well...simple...why don't we work by example..How does vBulletin Authenticates users? Is it session id too? From what I see...there's this..

    s=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX code in the query string...moving along any link I click on....what you guys think?
    "Imagination is more important than knowledge. Knowledge is limited. Imagination encircles the world."
    -- Albert Einstein

  11. #11
    Database Jedi MattR's Avatar
    Join Date
    Jan 2001
    Location
    buried in the database shell (Washington, DC)
    Posts
    1,107
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    vB's session thing works OK, but the problem with they way that they do it is if you have two users who are behind a proxy or something so that their IPs are the same you can EASILY assume someone else's identity (and by easily I mean it will log you in and everything, you don't have to do anything!)

    Not a problem in the real world you say? Check out their support forums, AOL apparently sticks users behind a proxy and it's happening already.

    I'd say stick with cookies.

  12. #12
    Database Jedi MattR's Avatar
    Join Date
    Jan 2001
    Location
    buried in the database shell (Washington, DC)
    Posts
    1,107
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally posted by arpith
    Yes, the password should probably be included as part of the hash.

    It would be nice if you actually verified that the hash was valid by storing it locally on the server. Then, during validation, the script would not only verify the hash, but also check to make sure that the session from the user was created locally. The timeout check should also probably be implemented on the server side (instead of depending on the client to hold the expiry date value).

    I reckon without cookies, it would be very messy to implement such a system... perhaps one holding the session ID in the query string,?? :-)

    Cheers,
    I think storing some stuff in a database would work -- my main reason for this was that you won't need a DB hit each time you want to validate, it's all in PHP.

    Check out my reply to lynlimz, there are problems with the "one hash fits all" style of approach -- the AOL thing is quite worrisome as it is already cropping up on servers that I know of and the only method is to just disable the session hash for everyone until a proper method could be determined.

    On our forums I've just disabled the "log in w/o cookie" portion. If users are too paranoid that we're going to do something evil with cookies then they'd better get over it if they want to log in and post, plain and simple. Looking at our server stats, I'd say 99.999% of our users have a browser that is cookie-enabled.

    However, as long as you can keep the server secret a secret then you can reasonably assume that the ticket is valid w/o any further verification (now that we've stuck the password in there).

    If a user modifies the expiration date of the cookie by hand then the stored $hash and the derived hash will be different, therefor it will invalidate the ticket.

    Obviously in the authentication failed portion you could clear the cookies out if they exist to "spank" users who try and break it.

  13. #13
    SitePoint Zealot
    Join Date
    May 2000
    Posts
    150
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That looks good MattR!

    The way I've done it is to make DB Calls to verify that the session exists in my SESSION table (as an added security level). Of course, this adds one more DB call... but IMHO its a little more secure.. :-)

    The way you do it should work fine though.

    Anyway, very lively discussion. I picked up the secret key from your code. Thanks!

    Regards,
    Last edited by arpith; Apr 17, 2001 at 07:36.

  14. #14
    Database Jedi MattR's Avatar
    Join Date
    Jan 2001
    Location
    buried in the database shell (Washington, DC)
    Posts
    1,107
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally posted by arpith
    That looks good MattR!

    The way I've done it is to make DB Calls to verify that the session exists in my SESSION table (as an added security level). Of course, this adds one more DB call... but IMHO its a little more secure.. :-)

    The way you do it should work fine though.

    Anyway, very lively discussion. I picked up the secret key from your code. Thanks!

    Regards,
    Extra DB calls!! :gasp:

    Just kidding. If it makes you feel happy then by all means use the DB for fun stuff!

    Now all that is left is to make it update the exipry time dynamically and I think I can put a fork in it (it's done!)


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •