8

I'm working on a web project that will connect to a database. For that, I will have to store the login/password of that database user in clear (encrypted in a symmetrical way) in order to be able to reconnect for every action (like creating table, adding entries, etc) without having to ask for those credentials everytime.

I'm aware that storing the password in clear is way too insecure and out of my possibilities.

Here's what I thought, could you tell me if it would be correct or/and if there is a better possibility? thanks :)

The application will be splitted in two independant parts : the frontend and the backend.

When the user log in via the frontend, the login and password are sent in clear (I will recommand the use of HTTPS). The backend will try to connect to the database, if it's successful, it will encrypt the login and password using Blowfish, and return them to the frontend.

For any subsequent requests, the frontend will have to send the encrypted login/password, without ever knowing the clear one, just the encrypted one.

If someone get access to the data of this user (XSS for example), he only will be able to access the encrypted credentials, not the clear one.

If an attacker can do a MITM, only the initial log in is risky, all the next requests will be with the encrypted credentials.

I thought about using cookies/session, but it's the same : values are stored in clear or base64 encoded. Not really secure!

The idea of Blowfish come from how PhpMyAdmin use it (aka, the same). Moreover, even on PhpMyAdmin, the login part is also sent in clear.

Do you think my implementation is correct, or do you have something better to suggest? I'd really like to do something as secure as possible. So far, only the login part bothers me :/

Thanks for your ideas.

EDIT:

Apparently, my question is not clear enough, I'm gonna try to be more explicit :

I want to build an alternative to PhpMyAdmin. PhpMyAdmin is a middleware that connect to a MySQL server by giving the login/password of any user in that database. The credentials asked in the web form are the one used for the MySQL database.

So, during the whole session after the user successfully logged in, PhpMyAdmin store the login/password in the session by encrypting the password using Blowfish.

This CAN NOT be avoided, because every time the user make a request (like creating a table, inserting data, updating or deleting data), PhpMyAdmin NEED to reconnect to that database using the credentials given at login, and then do the action the user requested.

It's then not possible for PhpMyAdmin to only store a hash of the credentials because it won't be able to reconnect to the database during subsequent requests made by that same user.

I'm aware storing password that can be retrieved in clear is not a good solution at all, and that is the reason of this question : not telling me that hashing is better, because it's absolutely useless in my case, but to know if there is a better alternative than symmetrical encryption + HTTPS for keeping a password that is needed for every actions the user make.

6
  • Looks fine to me. HTTPS is needed for security though, to prevent the cleartext password from being sniffed.
    – user10211
    Jul 27, 2012 at 8:49
  • Yeah I agree. What's odd is that PhpMyAdmin apparently does the same, but without https required :/
    – Cyril N.
    Jul 27, 2012 at 9:06
  • 1
    it's on you to configure phpmyadmin to be accessed via https not http. you should disable *80 and enable *443 virtual host. Also if you want a secure communication create ssl key bigger than default 1024 bits.
    – mnmnc
    Jul 27, 2012 at 9:20
  • 1
    yeah I was speaking for the general public! Too many PhpMyAdmin access aren't with https!
    – Cyril N.
    Jul 27, 2012 at 9:39
  • Are you sure you need to store the username/password in the clear? Can you elaborate on why you need to do so? (For instance, if you control the database you're connecting to, you don't need to store the user's password in the clear.)
    – D.W.
    Jul 28, 2012 at 18:37

7 Answers 7

5

Now that the question has been revised, I understand what you're trying to do much better.

The short answer is: Just store the database password in the clear, in the (server-side) session object. You cannot do any better.

If you want, you can encrypt the database password and store the encrypted password in the session object, but there's really no point, because where are you going to store the key? There is no place you can store the key that is much more secure than the session object. You could store the key in a configuration file or a global variable, but really, I'm not sure that this adds any security against any realistic threat. It's hard to see why to bother -- it feels like security theater to me.

So, just have the user enter the database password at the beginning of the session, store the database password in the session state, and be done with it. There is nothing better you can do.

And for heaven's sake, use good web application programming practice. Check out the OWASP resources. Make sure you are familiar with the common web vulnerabilities seen in the web world. Write your code carefully, using good security practices. And ask someone else who knows something about security to do a security review of your code. If there's a security vulnerability in your code, bad things are going to happen.

4
  • Your answer is very interesting, because I was going for using a symmetrical encryption for storing the password in the session, in case a XSS was found. I try to be aware of the most known web vulnerabilities, but I'm sure I will miss some of them that can be fatal. That's also a reason why I'm planning to open source my code : let others views/reviews and fix the code where it's necessary. Thanks for the answer ! :)
    – Cyril N.
    Jul 30, 2012 at 18:11
  • 1
    @CyrilN., an XSS attack cannot read data stored in the server-side session object.
    – D.W.
    Jul 30, 2012 at 23:53
  • @D-W It depends : In PHP, session are stored server side, with a Unique ID cookie for the client, but in other languages/framework, like Play!Framework (java) or Flask (Python) the session is directly written in the cookie. For Play! it's the clear values and the same hashed (to ensure integrity) and for flask, it's base64 encoded. So an xss could gain access to the clear password in those cases.
    – Cyril N.
    Jul 31, 2012 at 8:09
  • @CyrilN., Thanks for the explanation. I wasn't familiar with those frameworks. That's pretty wild. It seems to me like a poor design decision, from a security perspective. I would not recommend you use a framework like that for anything security-critical, as it is going to open up the web application to unexpected attacks that violate developers' reasonable expectations. In any case, if you are using a framework like that, then store the data somewhere that it remain in server memory, not in client-side cookies -- but better to simply avoid those frameworks for anything security-sensitive.
    – D.W.
    Jul 31, 2012 at 18:18
2

You shouldn't need to keep credentials in a recoverable format, even if they are encrypted. If your backend application could decrypt something, then so could anybody who can hack your backend application. Really, you have to assume that sooner or later, your backend application will be compromised and design with that in mind.

The most secure method would probably be to store the passwords as salted and hashed using an algorithm like bcrypt or PBKDF2. These days, regular hashing/salting using something like MD5 or SHA1 is not secure enough. Programs like hashcat can churn through cracking passwords files really fast. This article about hashcat is an excellent read.

It's good that you're worried about somebody getting access to the cookie store. The cookies are basically password equivalents, so if you're storing these, they should probably be salted hashes as well.

And really, this seems very easy but there are a lot of corner cases. If your application framwork already has a way to do session management, you should probably just use that instead of rolling your own.

Check out the OWASP Session management Cheat Sheet to see some good recommendations.

0
1

First: Are you sure? First, check to make sure whether you really need to store passwords in cleartext, or in recoverable form. Your question did not explain why this is necessary. If you have a security breach, everyone will be second-guessing your decision, and if it turns out you stored passwords in recoverable format, your organization may suffer some reputational loss. So, make sure this is really necessary.

Next: Define the problem. So, what exactly are you trying to do? The question wasn't very clear, so I'm going to make some guesses. If these guesses aren't accurate, edit the question after giving this some more thought.

Assumption: users log into your web application, let's call it CyrilApp, using a username and password for your application. You want your code to be able to access some other account of theirs -- say, their email via IMAP -- so you ask them to enter in their email username and email password, for your server code to use later. Now you want to know how to store the email password as securely as possible. Is that about the idea?

If that is the issue, then you have several problems to consider: how to store the email passwords? when retrieving the email passwords, how to use it securely? how to restrict access to the email password?

Storage. One option is to store the passwords in a hardware security module (HSM), or encrypted under a key managed by a HSM. However, HSMs are very expensive, so this may not be feasible.

A more pragmatic solution is to build a separate service, let's call it the EmailPasswordStore, which perform a narrow and simple function, is carefully coded, and is trusted to store email passwords securely. It might offer an API that allows the CyrilApp code to store a user's email password (when they enter it in), and an API that allows the CyrilApp code to request use of the password (for instance, the EmailPasswordStore might open an IMAP connection to the IMAP server, send the user's email username and email password, and then relay bytes back and forth between CyrilApp and the IMAP server.

In this architecture, the email passwords would never leave the EmailPasswordStore, and the EmailPasswordStore's job is to make sure that this remains the case -- even if CyrilApp is compromised or the rest of your servers are pwned by an attacker, the EmailPasswordStore needs to prevent the attacker from getting the email passwords. You could run the EmailPasswordStore on a separate machine (or possibly in a separate VM), with a VPN between CyrilApp and EmailPasswordStore, and do a careful security review of the EmailPasswordStore code.

Use. It's not enough to store the email passwords securely, because at some point you are going to want to use them. If you just store the email passwords in some encrypted form, and then decrypt them when you want to use them, you're not getting much security benefit: an attacker who compromises your web application could sit quietly and steal each password as it is used, or possibly even decrypt all the passwords itself. So, you need some use controls.

The proposed EmailPasswordStore architecture listed above provides these controls. It uses the email password itself, and never reveals the password to your CyrilApp web application. Try to see if you can do something like that in your setting.

Restricting access. Finally, you might want to limit who can request the EmailPasswordStore to use the password. A good starting point is for the EmailPasswordStore to authenticate the service who is connecting to it; for instance, you might set up a VPN between CyrilApp and EmailPasswordStore, and ensure that EmailPasswordStore will reject all other connection attempts.

A more sophisticated architecture might verify that the identity of the currently-logged in user, and restrict access to only that email password. For instance, the EmailPasswordStore could store a list of the hashed passwords that users use to log into CyrilApp, and require CyrilApp to send the user's login password to EmailPasswordStore for verification before unlocking the user's email password. However, this may be unnecessary in some settings.

Further reading. See also Where do I securely store the key for a system where the source is visible? and where to store a key for encryption.

4
  • I updated my question : I NEED to keep the login/password in clear at some time (after decrypting them), because they are the credentials used to connect to a database, and will be used for any subsequent request made to that database (create table, insert entries, etc).
    – Cyril N.
    Jul 30, 2012 at 6:47
  • Do you know PhpMyAdmin? do you know how they work? The solution I gave is the one used by them. I was wondering if it was a better alternative to something I can't avoid : having the password in clear during the session. I'm not looking to store it, I just need it when the user is logged in in order to avoid the need to ask for the credentials every time he do something on the app.
    – Cyril N.
    Jul 30, 2012 at 10:00
  • @CyrilN., I've posted a revised answer separately, now that it is clearer what you want to do. Thanks for revising the question -- that helped a lot. P.S. Please don't post the same comment multiple times on multiple answers. It clutters up the page unnecessarily.
    – D.W.
    Jul 30, 2012 at 17:19
  • I'm glad you understood my revision and sorry I wasn't clear enough before. I'll take a look at the answer :)
    – Cyril N.
    Jul 30, 2012 at 18:08
0
  • When the user log in via the frontend, the login and password are sent in clear (I will recommand the use of HTTPS). The backend will try to connect to the database, if it's successful, it will encrypt the login and password using Blowfish, and return them to the frontend.

You should instead use a salted hash.

  • For any subsequent requests, the frontend will have to send the encrypted login/password, without ever knowing the clear one, just the encrypted one. If someone get access to the data of this user (XSS for example), he only will be able to access the encrypted credentials, not the clear one.

By blowfish implementation in javascript? If an attacker knew the encrypted password he could just turn off javascript and send that without knowing the original.

  • If an attacker can do a MITM, only the initial log in is risky, all the next requests will be with the encrypted credentials.

If someone tries to MITM HTTPS you will get an invalid certificate warning (unless they managed to get your private key or forged it somehow, this is very unlikely) in which case you just stop trying to load the page and no damage is done.

4
  • 1. If the frontend send me a salted hash, how can I get the clear password back? 2. Blowfish will be made server side, the frontend will only have a encrypted text to send with all others requests
    – Cyril N.
    Jul 27, 2012 at 11:49
  • You don't get the clear password back. You store the hash in the database and compare the hash of the entered password to that. If they match, the password is correct.
    – Polynomial
    Jul 27, 2012 at 13:32
  • -1: This doesn't seem to apply to Cyril's question -- perhaps you meant to post it in response to some other question? Cyril's application is apparently running on a middleware server, talking to the user's web browser on one side and talking to the database server on the other side. The middleware app needs to send some sort of "password" to get data from the database server. If the middleware app only has a "salted hash" of the password, how can it get data from the database server?
    – David Cary
    Jul 28, 2012 at 6:35
  • @DavidCary, In that case I need more information that the question gives about the system architechture, I thought it was just standard web application.
    – user11101
    Jul 28, 2012 at 7:00
0

Your front end server should deal with authentication and should store passwords that are encrypted. The hashed password will be compared to the hash on this server.

Make sure that your encrypted password is salted. That way if the data is stolen, it will be harder to crack and rainbow tables will be less effective.

The back end server will contain the clear text passwords and will only accept connections from your internal network. Any password changes will be updated here first then updated on the front end server.

Make sure to write strict firewall rules for this server. Only allow updates to this server, drop all other packets.

This server shouldn't be able to be access from the internet and probably should be updated by your local servers.

As for MITM, there is nothing effective to prevent that.

1
  • Hashing is not the same as encryption; you might want to revise your answer to avoid conflating the two.
    – D.W.
    Jul 28, 2012 at 18:36
0

I have seen a setup where the passwords were encrypted with rsa in the backend db together with their hash representations and salt. The decryption key was kept on a separate machine without internet. It could fetch the passwords from the backend decrypt them and push them back encrypted. The backend server then could push the hashes to the front end server. The frontend server was the only one facing the internet.

0

First of all, NO. There's generally a better way.

For example, you store your password as a hash, and when the user logs in and successfully authenticates against the hash, you hold the password in memory for the session only, using it for whatever connections need to be made, and then forget the password as soon as you no longer need it. It never gets stored.

Second, if you need to store the password for some absurd requirement, a good way to make it semi-unreversible is to use public-key crypto (e.g. RSA). Encrypting with a public key (for which no private key is present) is not entirely unlike hashing. It's not quite as good as hashing, but it's hella lot better then symmetric encryption (such as blowfish, aes, etc.) because the password to decrypt it is not present. Which reminds me: the private key MUST not be accessible from the public environment, not on the same server, not on the same network, etc. The private key should only be used for whatever silly emergency your design requires.

But note that public-key crypto as commonly implemented is actually symetric crypto with an RSA wrapper. Know what protocols you're actually using.

4
  • Do you know PhpMyAdmin? The user's credentials are the one for the database. If I then hash them, how can I connect to the database again for the current session without having "absurd" requirements? I feel like you didn't read nor understand my question at all : you stopped at "I need to have access to the password in clear text" and jumped directly in the answer form.
    – Cyril N.
    Jul 30, 2012 at 9:57
  • 1
    @CyrilN. Did you read the second paragraph? I explained exactly how to what you're talking about. The key is (a) you absolutely do NOT store the password, and (b) you retrieve the password from when the user types it in to the session, which means you do not need to store it.
    – tylerl
    Jul 31, 2012 at 9:19
  • @CyrilN. BTW, this is exactly how PMA does it. PMA does not store passwords. Nor should you. Encrypting passwords does not make it secure.
    – tylerl
    Jul 31, 2012 at 9:22
  • Yeah I read your whole answer before commenting, but I think we (you? me?) don't understand each other ; "you retrieve the password from when the user types it in to the session", so the password is stored in the session ? (I believe the store part is the key to our non understanding)
    – Cyril N.
    Jul 31, 2012 at 10:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .