On password security.

From an AT&T Developer Program e-mail: How secure is your e-mail password?

If you want to be more careful with your e-mail on your mobile device, make sure you have turned on SSL. And you should never give your phone to others because turning SSL off is easy to do.

I have a few notes.

  • SSL is not a panacea. SSL does help slow down hackers. But not by much.

There are a variety of tools which can crack open SSL requests–and this has been true for more than a decade, though some commentators are only just now figuring this out. Symantec’s Endpoint Protection firewall, for example, scans for computer viruses in all HTTP transactions–including “protected” HTTPS requests. It does this by generating a trusted SSL certificate within the firewall which uses one of Symantec’s cert keys, signed using the web site URL of the web site you are accessing. Thus, the firewall can reach out, make a request against a web site, decrypt the traffic, scan it, re-encrypt it using the internally generated SSL key, and send the result to your computer.

There are a number of desktop tools which do the same thing, nominally designed to help developers understand the messages being sent by their desktop or mobile devices. I personally own Charles, a web debugging proxy application, which does more or less the same thing. (For debugging physical hardware you can set up your computer as a proxy for your mobile devices.)

Given this, you can pretty much assume any hacker worth his salt can easily peak into the structure of the requests and responses you make against a web site, reverse engineer your protocol, and make requests against your server–SSL or no.

And even if a hacker doesn’t have access to a certificate against which to generate signed SSL certs on the fly, a hacker can certainly insert a new root certificate into a computer he has access to, and sniff the traffic from that computer using the same techniques Symantec does with their Endpoint Security system. Bad if you run an IT shop full of computers.

  • There are techniques for encrypting a password sent to a remote computer to solve this problem. Various solutions for encrypting a password have been around for a while. Too bad no-one uses them.

One technique used to authenticate without sending a password in plain text is APOP protocol, first described in the e-mail POP3 protocol. Similar ideas (from more than a quarter century ago) have been floating around for at least as long. And the idea is this: when authenticating, instead of simply sending a command like:

{ "req": "login", "username": "woody@alumni.caltech.edu", "password": "Pa55w0rd" }

You’d do three things:

  1. Request a unique token. This can be a timestamp or a UUID generated by the server. The server stores the token returned associated with the current session.
  2. Use the token to generate a hashed response. For example, calculate SHA1(token + salt + password), where salt is an agreed upon constant common between the client and server. Both the client and server generate this result.
  3. Send the generated hash response to the server. The server then compares the hash with the client’s sent result, and authenticates if the hashed password matches.

In today’s world, doing this on a Javascript server is pretty trivial. And a hacker sniffing your traffic will see the following:

  "req": "login", 
  "username": "woody@alumni.caltech.edu", 
  "password": "9d6786ab1b8ded2e8ccb2079efafa18612c8c7b8f1888f3d25ee2c7528c164e9" 

This has a number of nice properties.

  • It is immune from replay attacks. A common technique for hackers to use is replay attacks; they record the packets going back and forth to a server, and replay the packets in order to gain access to the server. By obtaining a unique token from the server and using it to encrypt the password, you cannot replay the login packet to gain access to the user’s account.
  • It is hard to reverse engineer the password by sniffing packets. The next time the user logs in, the packet that gets sent for logging in looks like:
  "req": "login", 
  "username": "woody@alumni.caltech.edu", 
  "password": "5d12af8a0031f83c3e32c5513ecbabfec37fbef48b2b002ece20c7abab8e0e80" 

There is no pattern here that is easily discerned because the password being sent is a SHA-256 hash of a UUID + a token (can you guess the token?) + the password we used above.

There are a number of other techniques, but most of them are variants of the above. Some variants encode the password first (for example, the password is first hashed with a salt so that the password is never stored in plain text).

Side note: There really are only three encryption techniques that are used in encryption, which underlies all security. Most security techniques basically are an arrangement of each of these encryption techniques, each of which have their own strengths and weaknesses:

  • Hashing which converts some data into a hashed value. Hashing is a one-way technique; you can hash a value easily, but it is nearly impossible to unhash a value once hashed. (At best you can search for a “collision”; another string which generates the same hash. It’s one reason why you always salt your hashes–because most techniques used for finding a “collision” are much harder to execute if the input string must fit some specific criteria, such as containing a common well-known prefix.)

    (Examples include MD5, SHA-1, SHA-256 and bcrypt. Please don’t use the first two. Try to use the last.)

  • Symmetric-key encryption/decription where a string is encrypted and decrypted using the same encryption key. Symmetric-key encryption requires the common key to be shared between the code encrypting something and the code decrypting something–making the encryption key a weakness.

    (Examples include Blowfish and AES.)

  • Asymmetric-key encryption/decryption where a different key is used to decrypt a string from encrypting the string. Asymmetric-key encryption has the nice property that, if one key is kept private and another is made public, we can do all sorts of interesting things. For example, if the encryption key is made public and the decryption key private, then we can create a system where anyone can send a receiver a message–but once encrypted only the receiver with the decryption key can read the message. (This is how PGP e-mail encryption works.)

    Likewise, if the key used to encrypt is made private but the decryption key public, then we can create a mechanism for “signing” files: a file is properly signed if, once the encrypted message is decoded, the encrypted message matches some expected value–such as the checksum of the file being sent. This is how message signing is done for things like SSL certificates on the web.

  • There is a fourth technique that is used to help two clients agree upon a common key, and that is Diffie-Hellman and related algorithms, which permit the sharing of a shared secret without the possibility of an eavesdropper discovering the shared secret. It helps solve the problem of a client and server sharing a shared secret for symmetric key encryption of a message–and that is at the core of how TLS encrypts messages. (Add in public/private key signing to validate a certificate, and you have SSL and TLS in a nutshell.)

All encryption techniques are basically built on these three tools (and network protocols may use the fourth).

Each of these tools have their own strengths and weaknesses. For example, asymmetric key encryption assumes at least one of the two keys are kept secret (either the encoding key or decoding key, depending on how the key is used), which means if you use asymmetric key encryption for sending secret messages to multiple receivers, either the message must be encrypted multiple times or the secret key must be shared amongst multiple receivers.

(It is this fact that made me raise an eyebrow when someone creates a messaging app which they claim is completely secure end-to-end. Because if the system permits a single message sent from a client to a server to be re-sent to multiple receiving clients, it means either the server actually has enough information to decrypt a message (and re-encrypt the message to multiple receivers), or it means the server has the ability to share the encryption secret amongst multiple receivers–exposing the server to all the information necessary to decrypt traffic.)

Let’s get back to the topic at hand.

  • Encrypt passwords on your database.

When securing passwords on your web server or server application, the other thing you need to worry about is properly securing passwords in your database. Assume a hacker will eventually read the contents of your database tables–which means all the password security in the world is pointless if you store passwords on your server in plain text.

This is a common mistake, and you can tell if a web developer made this mistake when, as part of password recovery, they simply e-mail you the password. (As an aside, nothing pisses me off more than a web site that demands your password be strong–demanding you use an upper-case letter, lower-case letter, punctuation mark and number–then they e-mail your password in plain text when you ask to recover your password. Fuck you for making me jump through hoops when you can’t be bothered to do the same on your web site.)

There are a number of ways we can secure passwords against spying eyes on a database server. At its core, looking at the list of encryption techniques above, it should be clear we can either hash passwords (again, using a salt of some form), or we can use symmetric-key encryption. (Asymmetric-key encryption certainly is possible, but if your server is the same thing encoding password and decoding passwords, going through the additional effort for asymmetric-key encryption seems silly. Under some circumstances, however, it may make complete sense–such as if you implement a separate sign-on server to handle a large web site.)

A big advantage of using hashing is that it is one-way. This is the technique used by nearly all secure web sites and is also behind the encryption of passwords in Linux and on the Mac. (The principle difference in various techniques involve the hash involved: secure systems use Bcrypt, which has the property of being computationally expensive–and thus very slow to calculate. Of course in today’s world where we can buy the equivalent of a room full of Cray X-MP supercomputers for less than 50 dollars, computational complexity is a shallow panacea: it’s not hard to imagine a dedicated hacker wiring up multiple dedicated processors to accelerate the calculation of a Bcrypt hash to look for collisions.

Ultimately security is not about guaranteeing that your system won’t be penetrated. It’s about increasing the cost of penetration. It’s a series of best practices–backed with knowledge as to how encryption and hashing work–which allow you to slow down a hacker.

Think of computer security very similar to the physical security of a building.

The point is not to make it impossible to break into a building; that is simply impossible. Someone equipped with enough time, enough equipment and the willingness to use force can break into a building.

The point is twofold.

  1. Make it hard. If it is harder for someone to break into a building than the value of the stuff inside that building, then they may not bother.

    You see this with houses verses warehouses verses banks: the more valuable the contents, the harder it is to break into that building.

  2. Try to capture information about who broke in. It’s why security cameras are employed around secure buildings. It may be impossible to prevent someone from robbing a bank–but if you can catch the robber, you can then punish him for the crime.

    (This is why computer logging is an important aspect of security: so you know who tried to break into your system.)

Sure, SSL is an important element of security.

But if you’re not thinking through your entire security stack, from the protocol used to send a password to the way you encrypt passwords in your database and way you physically isolate the database from the network, simply turning on SSL is just fooling yourself into thinking things are safe.

It’s the equivalent of locking the front door while leaving all the windows open.

Leave a Reply