In response to question #2, your digest algorithm could be chosen to work with longer strings. MD5 (Digest::MD5) is more suitable to long strings than is crypt(). MySQL even supports an md5() routine, but I believe it's not an SQL standard feature if that matters to you. If using MySQL 4.0.2 or newer (and you probably should be), you can use SHA-1 instead. There is also the password() routine which is how MySQL hashes passwords for MySQL user tables (and there's encrypt() which is the same as crypt() in Perl).

As for question #1, that requires a little deeper probing. You do realize that having the unhashed version of the session ID is pretty much the same as having the hashed version under this scheme, right?

You need SSL if you're actually trying to prevent session hijacking while passing a session ID back and forth. If you're using this scheme over a plaintext wire, you're essentially protecting the browser session from the people who have access to the database directly. It'd be easier to hijack the session by sniffing the unencrypted session ID from a plaintext IP stream than by getting it out of the database and brute-forcing it, but anyone who has full access to your database isn't concerned with hijacking a single session anyway.

If you're not trying to eliminate session hijacking but just to shorten the window of opportunity, then you don't need to hash the session ID on the server. Picking a reasonably short time frame that the session is valid can do that. It would help if the session ID changed every time the user loaded a new page so that one intercepted or stored in a cache would be invalidated with every new action by your user. Hashing an ID that was stolen in plaintext and sent in plaintext will result in the same hashed value as a legitimately sent plaintext ID, so why slow your server with the hashing?

You could get fancy and make a JavaScript front-end handle shared secrets. Instead of passing the password and session IDs across the wire to the web server, the user could enter the password into a prompt for the JavaScript app. Then, the page requests a random string from the server and either hashes the random string with the password as a salt or uses it as a shared key in a reversible encryption. Then, the encrypted or hashed version of the random string is sent to the server, which either decrypts it or hashes using the shared secret as a salt to find a match. Since the shared secret never passes between the client and server, it's down to a brute force attack against the hashing or encryption algorithm.

The question of "good enough" security is largely up to your client or employer, even if they don't understand the technology. SSL is a good way to get some additional security that's already designed and implemented, and the annual cost of a signed certificate is generally cheaper than having the developer fret for a long time about it. It's definitely cheaper than a security incident that releases any kind of personal information about your client's clients, especially if you're talking about a banking or healthcare field even when transfer of money is not involved. If your form has personal information in it like date of birth, mother's maiden name, or a government identification number (think SSN in the US), then that's just asking to be an identity theft target even if the session isn't hijacked. That information needs to be encrypted.

If by "personal information" you just mean screen name and "about me" information that's displayed on a forum anyway, then that's no big deal. If it gives the intruder a chance to change that information or to log in on the forum, that's somehting more serious. If it's something that you could use to get a credit card, then it's something anyone else could use to get a credit card in your name. That means that any time you have that information involved, you need good security.

I'm not a professional security researcher, but I've read lots by them and I've been doing web sites and other types of Internet-facing servers for a decade. My three best general bits of advice are:

  1. When dealing with security, assume the worst about people, because someone out there is like that and it only takes one.
  2. Read Schneier and others on the topic before doing anything, and read security sites like Security Focus to see what mistakes others are fixing so you don't make those.
  3. Never assume securing your application isn't important just because the data isn't important. Nobody would make any money just from having hijacked a Perlmonks account, for example. However, they might land a freelance job from another member based on the account owner's credentials or might try to ruin another's relationships with the rest of the community.

You're right that there's no point in going overboard for a page that doesn't need much security, but cheap and simple security like SSL shouldn't be flippantly passed over if it's a good idea to secure it at all. Never count on the information being passed being the cost of a breach, either, since much information can be used to springboard into other illicit (ad)ventures.


In reply to Re: Using crypt for 'reasonably' secure session management w/DB by mr_mischief
in thread Using crypt for 'reasonably' secure session management w/DB by punch_card_don

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.