Is Basic Authentication Really Insecure?

The other day I was thinking about basic authentication. You know the one, the most simple authentication scheme built into the HTTP protocol, and it struck me that it has undeservedly been getting a bad rep. Ask anyone – who is in the know – about basic authentication and the first thing you hear would probably be the fact that it is insecure (it is basic after all). But is it really? Lets examine the facts.

It’s Only As Secure As Your Transport Mechanism

Just because we store something in plain text (or base64 encoded) does not mean it is inherently insecure. When we get the users credentials we want to safely (without anyone stealing them) be able to transport them to where we are. You can think of it like transporting gold (or at least some sort of precious object) in the real world (meatspace :)). We normally try and protect our gold when we transport it, by putting it in an armored vehicle and maybe having a security guard or two around. We certainly don’t load our pickup truck full of bullion and ask our cousin Billy to shoot it down the east coast. A similar situation applies when it comes to user credentials. It does not matter what form the credentials are in (plaintext or not), what we really need is a secure method of transportation.

This is why we have HTTPS, right? When we want to protect against eavesdropping, we use a secure protocol. When we want to protect against stealing, we use a secure transport. Sure we can melt out gold down and combine it with lead (and then figure out some way to pull them apart later), that would make it harder for people to get at it if they steal it. But we already have a secure transport, so perhaps that might be overkill. In similar vein we can get the credentials a different way and then obfuscate them somehow (encrypt) before we send them down, but we already have a secure connection – so overkill again? End of the day you don’t really care about the security of the credentials, you care about the security of the connection over which the credentials are transported.

What If The User’s Machine Is Compromised?

Well in this case, no matter what you do you’re pretty much stuffed anyway so worrying about it is pointless. You can’t really control what goes on with the user’s machine. If malicious code already resides on the machine the user can say goodbye to his credentials (and to whatever the credentials are protecting). A simple key-logger or trojan will defeat the most brand-spanking-awesome crypto-obfuscation system you can think of, unless the user is particularly savvy. Even a secure connection matters nothing in this case as the credentials are compromised before they are transported.

The point here is, figure out what you need, as far as secure connections go, and why you need. Chances are, you might find that basic authentication may serve your needs. It is not the authentication scheme that is insecure, it’s how you implement it!

  • I agree with your post. Some people would argue that it is possible for an intermediary server to be hijacked in order to intercept traffic but I think the odds of this happening are slim.

    In many ways, we have the tendency to over-architect things. I’m not saying that digest authentication (or any other form of securing the “message”) is bad, but making sure the transport mechanism is secure is far more important. Use HTTPS.

  • Michael Wright

    While I think you’re correct as to secure transportation being one of the most important facets of security for a website, I’m not sure you quite grasp what SSL/TLS exactly does.

    SSL/TLS does provide a “secure connection”, but does so by /using/ encryption/decryption on either end. If you’re implementing Basic Auth over SSL/TLS, you are effectively implementing what this article has described as possible overkill. You’re combining the gold with lead on your end, and separating them back out on the server end.

    Furthermore, the issue with basic auth is not only that it typically provides a plaintext login, but also that it does so within every single packet because it does not save a session’s authorization credentials. By utilizing basic auth over ssl, you’ll have to provide valid SSL certificates for every page of your website that requires authentication, which is a hassle and can provide a vector for attack if there is an incorrect link or incorrect apache config.

    I also think it would be important to pay attention to the server side of this interaction, as well. When passing login information to the server, the server should be comparing this information to a hash, and not the plain text password itself. Apache at the very least does this by default if creating an .htpasswd file using the htpasswd utility, but you should check this before implementing a basic auth solution with any web server.

    Finally, thanks for the blog, I’ve been enjoying it so far!

    • I do understand that ssl encrypts at either end, what I was trying to say was if you add your own encryption into the mix as well, that might be overkill.

      As far as having to have a valid SSL cert for every page, that is a good little piece of info to keep in mind, thanks for sharing.

      I do agree with you about being more rigorous on the server side.

      You’re welcome, I’ll do my best to make sure you keep enjoying it :).

  • Miikka Koskinen

    Basic authentication indeed suits many situations, we use it at work for many internal services (over HTTPS naturally). But I think it has at least one problem: logging out. There aren’t any easy ways to log out, as far as I know.

    • Yeah that one is a bit of an issue :(. There is no good way that I am aware of, besides closing the browser on the user end.

  • Pingback: Dew Drop – August 12, 2009 | Alvin Ashcraft's Morning Dew()

  • Pingback: Destillat KW33-2009 | - GNU/Linux, Open Source, Softwareentwicklung, Selbstmanagement, Vim ...()

  • Paul Noeldner

    Basic Auth over SSL is great if you happen to agree that system enforced security is just as desirable for internet facing apps and resources, as it is for internal facing apps and resources – and even moreso as the line between the two fades, and the external risks grow. Arguably SSL encryption should be active for every page accessed via a logged on session in any case, for both privacy and security reasons. System security is going to be generally better tested, more centrally auditable, more securely implemented (the person applying the security does not need to be the same as the person creating the application) and more robust (fewer back doors), than any security implementation lower down in the application stack. And it can be extended to new models – for example trusts and federations – by extending and configuring system supported interfaces, without modifying applications.

  • Bob

    If you assume that your transport is secure, all sorts of problems become much easier. But responsible security doesn’t rely on a single point of failure. For instance, you shouldn’t assume that your firewall is perfect, and therefore you can just store all user passwords in plaintext. As I understand it, this is why the PSN hack was so bad, and so effective.

    The best security is layered security. There are well known mechanisms that let you authenticate a user without ever passing the user’s credentials in a form that can be used to recover the plaintext. That’s a much more responsible way to authenticate, rather than a mechanism which, if the transport’s security fails, leaves the attacker with the keys to the kingdom.

  • Mike

    The biggest problem with storing passwords in plaintext is that it makes it possible to compromise every user’s password, instantly, should the server be compromised. Heck, an employee can then steal the info. This is why we have hashes and key strenghening functions: hashes are (in theory) non reversable. Add a salt and now you increase the time required to derive all of the secrets enough to make it impossible. Add a KDF, and you now have made it impossible to derive even a single password in a lifetime, unless both (a) it is a simple password and (b) it is guessed early.

    Add to it that if the passwords are plaintext, accountability regulations cannot be followed (for there is none). Finally, if the passwords are hashed, salted, and ran through a CPU-bound KDF, the investigation process for finding a breach is significantly simplified. As someone who has cleaned up after several such breaches on other people’s networks who have had a relaxed stance towards security, I have seen it happen many times where the guilty party was never found, because literally everyone had access—daily!—to the information used to actually create the breaches.

    The net result here is that fifteen to thirty minutes of developer time saves liability, increases accountability, and truly does increase the overall security of the system. It is really simple to ensure that credential forging is an improbable event—so why not just do it?

  • ankush jain

    But what if I create an API with basic authentication and on other hand one of my customer is consuming this api in his front-end app. Now the third person, who is running my customer’s app in browser say google chrome can easily see encoded string from network tab and can decode it to get actual API’s username and password. How can we prevent from this scenario?