Random Thoughts on Improving Internet Security

Disclaimer

IANACSE (I am not a computer security expert.) But…

When I was in my final year of high school, I had the opportunity to study with the Australian Mathematics Olympiad Squad. I didn’t make it into the team, but a friend of mine and I got close enough to be invited to the training, and be lectured to by Paul Erdos for a week. I’d love to say that this was an inspiring experience, but unfortunately the impenetrability of his accent was exceeded only by the material he was covering. It didn’t help that, alone among the participants, my friend and I hadn’t spent years in gifted programs and/or at universities getting exposed to graduate-level math.

For me, the highlight was a field trip to a presentation at a math conference about cryptography. I only understood the outlines of what the speaker was talking about at the time, but the subject matter was the theory underlying what is now known as public key cryptography. So, attending and not understanding that presentation, and a hazily recalled education in Pure Math, are my only special claims to domain knowledge.

The Problem(s)

The most commonly used internet protocols — http, ftp, and POP/IMAP/sendmail — are hopelessly insecure.

The standard solution for http is to switch to https.

With ftp at least there’s sftp. If your ISP doesn’t support sftp, use another ISP.

Email is pretty much a lost cause because even if your connection to your email provider is secure, the email transmission is not going to be, so anyone who cares about email is encrypting their email content using PGP or something similar.

I haven’t had an email exchange with anyone, ever, that required me to use PGP, so it’s obviously not very popular. By now, PGP should be built into every mail client and operate transparently (it would make spam harder and more expensive to send, too), instead our best option is usually webmail via https, or a proprietary solution like Microsoft Exchange or Lotus Notes (which has, laudably, been secure from the beginning — it’s a shame it sucks dead dog’s balls in pretty much every other respect).

OK, let’s ignore everything except http

I’ve recently been looking at implementing some kind of security for logging in to websites over http. The usual, simple solution for this is to switch over to https, but the vast majority of the world’s web servers are serving http, and this includes all kinds of services with logins and passwords that people don’t really think too carefully about. How likely is it that some username/password combination a given person uses for an insecure website (e.g. a blog, forum, or whatever) is also used for a secure website somewhere else? Even if https is secure (which is open to doubt), it’s undermined by the insecurity of http.

Here’s the actual form code for Digg.com‘s login form (modulo whitespace):

<form method="post" action="/login/prepare/digg">
<div class="form-row">
<label class="dialog-label" for="login-username">Digg Username</label>
<input class="login-digg-username text" name="username" value="" type="text">
</div>
<div class="form-row">
<label class="dialog-label" for="login-password">Digg Password</label>
<input name="password" class="login-digg-password text" type="password"> <a class="dialog-link forgot-link" href="/login">Lost username or password?</a>
</div>
<div>
<input name="persistent" checked="checked" type="checkbox"> <label class="inline"><strong>Keep me logged in on this computer</strong></label><br>
<input value="Login" type="submit">
</div>
</form>

I’m not trying to single out Digg — it’s just an example of a large scale, popular site that requires user logins and offers zero security. Facebook — a very high profile, popular site — is just as stupidly insecure (the relevant code is a bit harder to read). Why isn’t this a scandal?

It seems to me that it’s criminally negligent of the folks running these sites, and the people developing the most popular open source website software — phpbb, wordpress, drupal, etc. — not to have addressed this, when the solutions are so very straightforward and have been publicly and freely available for so long. Apple got into quite a bit of hot water — and rightly so — for (allegedly) not sufficiently securing MobileMe chatter between web apps and servers, but many of us spend a lot of time on all kinds of websites requiring passwords that make no real attempt at keeping our information safe.

  1. By default, during the setup of any of these programs, the admin should be forced to provide an encryption key, or — better — set parameters for automatically generating such a key for the website. Ideally the key would be refreshed periodically (or even created on-the-fly if the horsepower is available). Some security is better than no security at all, so even if the default key is “only” 64-bit this would be very helpful.
  2. The login page (and any other page where the user enters sensitive information) should simply incorporate JavaScript that takes the public key supplied by the server and encrypts it before posting it back to the website. Encryption in JavaScript, even on fairly slow machines and browsers, is close to instantaneous, and could be done in the background. If JavaScript is disabled, the code can warn the user and fall back to the usual (insecure) method.
  3. The web server then decrypts your private information using its private key.
  4. All such programs should make it easy for users to have their password sent to them encrypted via a supplied public key. (I.e. tell the user where to go to get crypto software to make their own key, and then allow the user to provide a public key (perhaps even store it in their profile) and use it to encrypt password reminders, etc., when necessary. The same techniques should be used to handle “secret question” transactions and the like (obviously).

Correction: as Andrew, my loyal reader, points out — servers shouldn’t store passwords at all. The server should store the hash, and for login attempts the server should ideally provide “salt” which should be added to the hashed password and encrypted before sending. Then, a hacker probably can’t “replay” the encrypted/hashed username/password combination to break in (since they won’t usually be able to enter the session which had that particular salt). Even if the server is totally compromised, no cleartext passwords are stored in the system. It follows that users can never have their old passwords sent to them, they can only be given an opportunity to reset their passwords. If a web service offers to send your password to you, avoid it if you can and treat it as utterly insecure otherwise.

The problem is that, in the end, the password restoration process is only as secure as email, so while the server shouldn’t store passwords and should allow resets instead of sending old passwords, ultimately you’ll need some mechanism to restore access, and if it goes over email we’re back to hopeless insecurity.

Steps one to three, of course, are essentially what https does (but only applied to sensitive data, rather than the whole web page), but has a number of added benefits. It allows reasonable levels of security on commodity http servers. And it will make https even more secure, since https is currently a single point of failure. Here are random hackers discussing methods for cracking or spoofing https. (Do you think your local Savings and Loan or Credit Union paid to have any additional security beyond https for its online banking software?) And it will give criminals headaches in trying to deal with a bizarre cornucopia of — possibly layered — security protocols. (It’s better to have ten different and not entirely reliable layers of security than one that you’re convinced is incredibly good — even if it is incredibly good.)

If nothing else, it’s a competitive advantage. After all, no security is impregnable — the trick is to be secure enough that would-be hackers pick an easier target.

  • Andrew Barry

    My extension would be that the server should never get the password sent to it anyway – ie it’s perfectly sufficient for the client to send an encrypted hash of the password.

    That way you don’t even have to worry about the server being compromised (at least with regard to hackers stealing passwords).

  • Well there’s no good reason to store passwords in unencrypted form in any event. But even if you send password hashes, you want to encrypt the hashes to prevent someone breaking into the account simply by sending the hash.

  • Andrew Barry

    That’s why you need the server to provide a salt for the client to use when hashing the password, otherwise you are vulnerable to replay attacks as you note.

    Servers should never store passwords unencrpyted or even two-way encrypted, though a depressing number do. i.e. never trust a site that offers to email your password back to you.

  • It’s not like you know whether a site will email your password back to you until after you register, and in any event this eliminates many sites it’s hard to live without.

    You can’t salt the hash or you’d need to store the password (to create a salted hash to compare to), so you need encryption (i.e. store hash, encrypt salt + hash, decrypt to retrieve hash) … or am I missing something?

    If I were truly careful I’d use a disposable password when first registering, then after figuring out how good (or bad) the security on a site was I’d either leave my disposable password in tact or upgrade to an appropriately secure password. (With my limited mental faculties, I use a fixed, slowly rotating set of passwords for material of varying sensitivity — but my least secure password is hopelessly compromised by the phenomena we’re discussing.)

    Anyway, we can’t make the system perfect, but simply encrypting sensitive information dispatched from client to server (even with a static key and no salt) is a huge step up from sending cleartext name and password from an html form via POST, which is what Facebook (no. 4 in traffic rank today) is doing.

  • Andrew Barry

    It’s also valid to apply the salt to the hash instead of the original pwd.

    e.g.
    http://en.wikipedia.org/wiki/Rainbow_tables

    look under “Defense against rainbow tables”

  • It’s interesting to note that by using a well-known hash function you open yourself up to rainbow attacks in the first place. I’d suggest using a standard encryption key to store and transmit passwords and simply throwing away the decryption key — then one-size-fits-all attacks will simply bounce off you. You can then use whatever technique you like (hashing or more encryption) to add salt — it doesn’t matter.

    Suppose you use a hash function for storing passwords and hash + salt to transmit passwords. An attacker with an unusually large rainbow table can break your security _for free_. Now this may seem like a small risk until you allow for the passage of _time_. Servers will be around, presumably in many cases without much reconfiguration, for a long time. Also, the ability of human beings to memorize longer passwords is not going to benefit from advances in computer hardware.

  • Pingback: Tonio Loewald’s Blog › Web Site Design Advice That Sucks: Cleartext Passwords()

  • Pingback: Tonio Loewald’s Blog › Secure over http()

  • Firesheep is Firefox extension that makes hijacking accounts on insecure social media sites point-and-click easy to do. If I can fix this problem in an afternoon, why can’t “billion dollar” websites.