http://qs1969.pair.com?node_id=154108


in reply to Web based password management (or how *not* to blame tye)

I have one thing to add. When sending any data that is persistent (like a cookie) to the client, you should ALWAYS include a hash (like MD5 or SHA1) of the original value so you can easily see if the cookie value has been modified.

Also, you should use cryptographically sound session ids to lessen the chance of guessing a valid session. I came across a very good paper recently that talked about this. The URL is http://www.usenix.org/events/sec01/fu/fu_html/index.html.

Replies are listed 'Best First'.
Re: Check the cookie for changes
by maverick (Curate) on Mar 25, 2002 at 15:43 UTC
    The session ids that I'm using here are those generated by Apache::Session itself. They appear to be a md5 hash of some sort (I've not really looked into *how* they are generated). That's the only piece of info ever stored in a cookie, and validating if the cookie has been tinkered with is easy.
    eval { # tie to session_id (sorry it's monday morning don't remember the +exact syntax) } if ($@) { print "bogus session\n"; }
    basically if you ask apache session to access a session that doesn't exist it dies. Thus the eval...

    /\/\averick
    perl -l -e "eval pack('h*','072796e6470272f2c5f2c5166756279636b672');"

      True, that would work fine if all you're storing in the cookie is the session id. I usually put a little more in the cookie than just the id, so using a hash to verify the value I put there is second nature to me.

      Here's a scenario: User A get a cookie w/ the session and logs into a web app w/ sensitive data. User B has access to User A's computer (hacker, social engineering, etc) and gets the session ID. User B then creates a session cookie like User A's, and now he can see the sensitive data he should not have access to. Using a checksum on the cookie value can help to avoid situations like this. And there really is not a downside. You write the code once, it uses C based modules so it's fast, and you prevent one less possible security problem. Maybe you'll never run across this situation, but should you do so you don't have to worry.

      Just a thought...

      The default, Apache::Session::Generate::MD5, does MD5->hexhash(time(). {}. rand(). $$)/ Systems such as ASP under IIS appear to have session ID's that are partially determined by the client headers the (User-agent, Accept, etc.)

      PS> I was horrified re-reading the Apache::Session documentation that in the SYNOPSIS they place a cc number in the session data.

      --
      perl -pe "s/\b;([st])/'\1/mg"

Re: Check the cookie for changes
by no_slogan (Deacon) on Mar 26, 2002 at 17:13 UTC
    When sending any data that is persistent (like a cookie) to the client, you should ALWAYS include a hash (like MD5 or SHA1) of the original value so you can easily see if the cookie value has been modified.
    Anyone who modifies the cookie can also recompute the hash value so that it matches. To prevent that, you need to include secret information in the hash itself -- see Digest::HMAC. If you go that route, you can eliminate the need to store session information on the web server at all.
    $cookie = join(",", $user_name, $time, $remote_ip); $cookie .= "," . unpack("H20", hmac_sha1($cookie, $secret));
    (I cut the hash down to 80 bits, because that should be enough to prevent a brute-force key search.) Then your only problem is keeping $secret synchronized, if you have a pool of load-balanced servers. Verifying the cookie against both the current secret and the previous secret should give you some leeway so the servers don't all have to be updated at the same instant. It'll also avoid invalidating everybody's current logins when you change the secret.

    Update: Yes, that's basically what I meant, drewbie. HMAC is a construction that avoids some possible weaknesses when using a hash as a MAC.

    Possible Objection: An attacker who breaks into the web server and learns $secret can log in as anyone.

    Response: He can probably forge himself a new Apache::Session, too. Or trojan the login cgi so it saves the passwords in a log file.

      Anyone who modifies the cookie can also recompute the hash value so that it matches. To prevent that, you need to include secret information in the hash itself -- see Digest::HMAC. If you go that route, you can eliminate the need to store session information on the web server at all.

      I'm not sure if we're talking about the same thing here or not. The hash I mentioned is a MAC of the cookie value you are sending along w/ a secret string stored on the server. This MAC does prevent the attacker from regenerating the cookie. A good example of this in Apache::TicketTool::make_ticket discussed in the mod_perl book (Writing Apache Modules in Perl and C by Stein & MacEachern) page 317.

      So I think we're talking about the same thing. I haven't had time to finish reading RFC 2104 (which Digest::HMAC implements), so I can't be sure. But I know the method I mentioned has been widely discussed as reasonably secure.