How To Keep A Secret

Obviously, the real-world advice "Don't tell anyone!" wouldn't work in the online world, because you have to use your secret to log into a web service and to access private information after login. Using your secret often and still keeping it private, so only you can use it, that is the challenge all web applications must live up to.

And many fail in this regard.

Let's assume you will be using an online application to read personal information, that is meant for your eyes only, then your secret will be used at some point to encrypt the private information in order to protect it.

Let's assume, there is a reliable standard solution in place (SSL/TLS) that protects your secret while it travels safely from your browser to the web server, it is the secret's life after having arrived at the server that is really difficult to secure. But I'll show you exactly what it takes to protect your secret while it is used by an online application.

What's The Problem?

Well, you've already provided your secret to log in, why can it be used to grant you exclusive access to some private information ten minutes later?

The answer is, because it is stored somewhere, and that's where things get pretty tricky.

Your secret must be stored in the server's memory, otherwise it would be impossible to decrypt protected information you want to read. The safest way to keep your secret private is to make the server forget it after it has been used. This would turn out to be a major nuisance for you, as the server has to ask you again and again to resubmit your secret if you decide to read a different piece of information that has to be decrypted.

To save you the hassle of entering your secret again and again web applications tend to introduce a mechanism to store your secret for a while to make your life easier. Nice idea, isn't it? But the place where your secret is being stored, as well as the length of this while makes quite a big difference when it comes to protecting your secret.

The Bad Idea

You might think that storing your secret unprotected in the server's file system is the worst idea a web application could possibly come up with? Actually, it's quite easy to let your secret end up in files that are not being deleted properly. In particular, when a web application adds your secret to the PHP $_SESSION variable, it will be stored in the file system, inevitably. How could anyone come up with such a hazardous security design choice? Well. ask your favourite web application developer and listen carefully to what his justification will be, in case you get an answer at all.

How To Protect Your Secret Online

By now, I hope I've made it clear that instead of storing your secret on the server, something has to move from your browser to the server to enable the decryption of your protected information, when decryption is actually required.

This "something" must be derived from your login secret and its lifetime must be limited, and under no circumstances must this something end up anywhere, except in memory when the process of decryption needs it.

As I said previously, you will rely on the existence of a safe tunnel between your browser and the server, because this "something" must be resubmitted many times during an online session. If you wonder if there is such a reliable encrypted tunnel, I have discussed issues with the HTTPS protocol in a separate posting here.

Before you actually start to pick your brain on how to establish such a secret-protecting mechanism for your own web application, let me tell you that you can see all the details in a demonstration web application, I have developed to show how protecting a secret is done properly.

Getting Into The Details

I will briefly outline the details of my secure web application demo. Within the demo, you can enter text and encrypt it to be stored in a file, and you can also read the plain text content after decryption. The demo's main purpose is to demonstrate that your login secret can be used to create a cookie in your browser that enables the use of a RSA private key which is stored in encrypted form in the server's file system.

Without the cookie, provided by the browser, the server will not be able to use the RSA private key, as it's stored encrypted. In case an attacker manages to read files on the server, your private information is still secure, because the crucial part, a secret that comes from outside the server is still missing, and the attacker's attempts to decrypt your files will fail.

 

So anyone who thinks about storing sensitive information in the PHP $_SESSION variable is advised to look at the code and see how the secret is being handled in the secure web application demo. The code is designed to make sure, that the secret information is being encrypted before it is added to the $_SESSION variable, and most importantly, that the key needed to use this information always comes from outside the server.

It's the only way to keep an online secret, over time.

If you wish to use this code to secure your own web application, that's fine, the code is licensed under the GPL. Just learn from the code and make sure you include a decent authentication mechanism, as this is only a demonstration for one single user.

In short, this is what the demonstration application does:

First, it checks whether or not HTTPS is being used. If not, the app dies immediately, there is no way to keep a secret without using HTTPS.

Secondly, if you're not logged in, the app asks for your secret and uses it to decrypt the RSA private key, preparing the RSA private key to be used in memory. The RSA private key will be destroyed a split second later. Now, a fresh randomly chosen 128 bit session key is created and will be used to AES-encrypt the RSA private key again. This protected key can now be added to the $_SESSION variable. It wouldn't be of any use without the session key, so it doesn't matter if it ends up in the file system.

After wiping the RSA private key from memory, the web app makes sure that the session key leaves the server as soon as possible. Thus the session key (the "something") will be transferred via HTTPS to the user's browser and stored in a cookie. At this point the encrypted RSA key (in $_SESSION) and the cookie are separated and the server as well as the user possess only half of the information necessary to use the RSA key later again.

Every time a decryption of personal data takes place on the server, the combination of the user's cookie and the server's $_SESSION information is necessary to recover the RSA private key in memory to make decryption possible.

For demonstration purposes the decrypted personal information will replace the encrypted information in the file to emulate a mini cloud application. It might depend on the purpose of your own web application, whether it's safer to display the decrypted information to the user in a separate browser window instead.

At the bottom of the demo's screen there are buttons that allow you to inspect the content of the PHP $_SESSION variable and the contents of session files stored by PHP directly as well as the source code of the secure web application.

Have a look, and tell me what you think.