17

I have a database which has stored procedures which take plaintext passwords. It hashes them and inserts them into the DB.

If an attacker has access to the DB connection, it is possible to intercept calls to the DB using SQL Server Profiler and see the passed in plaintext passwords. I understand that SSL will encrypt network traffic to the DB, but it won't stop an attacker sniffing the stored procedure parameters.

Is there a security risk in having these passwords sent through unencrypted?

  • 6
    I would say to hash the password before sending, since you don't have to worry with SQL injections after. Unless you send it in binary form, which I don't recommend. And it will likely be faster to run this kind of functions on your language (php, ruby, perl, python, c#, ...) since they are optimized for this kind of work. The database is optimized to deal with datasets and tables and the sorts. In my opinion, this is like fitting a square inside a larger circle. It fits, but it won't fill the whole area. – Ismael Miguel Dec 15 '14 at 10:47
  • 1
    I agree with Ismael. I would hash it by default - better be safe than sorry. If a injection attack was to happen, you can already minimize the damage. – Malavos Dec 15 '14 at 14:03
  • 2
    @IsmaelMiguel Whatever is sent over the wire is the password. If the client hashes what the user types, then sends the hash, then the attacker does the exact same thing: obtain the plaintext data and repeat it to login to the database. That this data is a hash of what the user typed doesn't matter. The solution is, use a secure channel to transmit passwords. Nothing more, nothing less. – wberry Dec 15 '14 at 19:00
  • @wberry For those problems, we use something like salts. Even without salts, the user may get the plaintext hash and nothing else. He still has to use pre-compiled rainbow tables to try to figure out what it is. With salts, this will fail miserably. Even if the attacker could watch the connection for hours and send his own password, every time he sent a new one it would be a different hashed result. – Ismael Miguel Dec 15 '14 at 19:03
12

SQL Server has the option to encrypt the connection between application and database. When you operate SQL server in an untrusted environment, it is recommended that you enable it. When you do, hashing the passwords before sending them to the database is unnecessary as long as you trust your DB administrator.

Additionally, most deployments of SQL server will have an application server in a DMZ and the SQL server on the LAN, which means you operate in a trusted environment. Unless you have a very high security standard, having no encryption wouldn't be a big security risk.

  • That's interesting. Somehow I have missed this nugget on my sql travels. – Fetchez la vache Dec 15 '14 at 10:43
  • 2
    I'd argue that nowadays, there are not many actual "trusted" environments out there, so everyone should default to encrypted connections and only use unencrypted if it's absolutely necessary. – Brian Knoblauch Dec 15 '14 at 15:34
  • 1
    If the DB admin is untrustworthy, wouldn't it be a security risk since the DB admin is still able see plaintext passwords with SQL Server Profiler? Do you think hashing would provide more security in this case? – Craig Curtis Dec 16 '14 at 1:18
  • 1
    @CraigCurtis If your DB admin is untrustworthy you have a problem which can not be fixed in a technical way. – Philipp Dec 16 '14 at 8:35
  • I disagree with hashing being unnecessary. Granted, you need to be able to trust your DBAs. However, DBAs nor anyone else should ever see passwords. There's a number of things that could make a trustworthy DBA untrustworthy. Trust is a terribly weak control to lean on by itself. If the password is hashed, trust isn't required to protect the password. – Paraplastic2 Dec 29 '14 at 13:40
9

Trust no one. Use secure strings to hold plain text passwords and hash them immediately. Gone are the times when you can hope your system is secure. It is not. It's just matter of time/money until a determined attacker can access your system.

Even when traffic gets encrypted with SSL/TLS I can come up with several scenarios, each leading to passwords leak, for example

  • The government captures SSL traffic and "asks nicely" for a private key to decrypt it. Is it all in a private network? Are you sure there is no off-site replication configured?
  • Your organisation installs hardware that performs man-in-the-middle SSL decryption to sniff what SSL traffic goes through its network. Suddenly more people, hardware and software are involved - do you trust them? Has it not been installed or perhaps not yet?
  • Server that holds SSL private keys gets hacked and the key is leaked. Privately. Quietly.
  • A disgruntled employee gets paid to copy the private key and sell it to competitor
  • 1
    In case of OP answer, I think some of these items would be Overkill; But surely, why not simple hash it? Better be safe than sorry. – Malavos Dec 15 '14 at 14:01
2

Yes, there are a variety of risks or risk increases here.

First and foremost, whether or not your DBA's can be trusted, they should be able to honestly tell any auditor (or regulatory investigator, or lawyer) that no, it is not possible that they impersonated user X, because they were never, ever able to see user X's password even if they wanted to, and even if they used their copy of the server's private key and a packet sniffer.

Second, if you're hashing passwords on the server, you should:

  • Read the canonical How to securely hash passwords? answer by Thomas Pornin, which boils down to "Use BCrypt, SCrypt, or PBDF2".
    • With as large a number of iterations as you can handle under peak load.
    • With an output length no longer than the base hashing primitive output length.
  • Since this is SQL Server, see my own pure T-SQL PBKDF2 implementation answer.
    • Note that it is horrifyingly slow compared to real implementations, particularly attack implementations like oclHashcat.
  • See oclHashcat for current single-machine, multi-GPU offline attack speeds. This is what attackers, researchers, and cracking competition contestants will be using after they grab a copy of your hashed passwords from some front end vulnerability, or a laptop with a database backup on it, or (pick your favorite scenario here).
  • Realize, based on the above, that whatever your application is, it can use far more rounds of BCrypt, SCrypt, or PBKDF2 to hash the password than your SQL Server database can for the same amount of computation time.
    • and it's almost always easier and cheaper to add more front end power by scaling out than it is to add more SQL Server power.

Note that a variety of PBKDF2 implementations are at my Github repository, including a C# variant based on Jither's work, which Jither released under the MIT license.

1

So it depends on the the trust worthiness of the environment. If you have zero trust in it, perhaps some encryption would be good. Additionally, the low branch set of configuration would probably be to restrict to only hosts that require SQL connectivity, though there are many different reasons why you'd want to open it up to access.

0

TLDR: As long as the network connection to the DB is secure, and as long as salted hashes are stored in your tables, calling a stored procedure with a plaintext password is fine. I think your time and effort is better spent protecting the database from unauthorized access of the kind that makes it possible to obtain a trace of stored procedure calls.

First, I understand the scenario in question to be that an attacker may recover the plaintext password by reviewing parameter values passed to the stored procedure, one of which is the plaintext password, and then use that password to compromise a user account in your application.

If that is correct, then the only purely technical solution I see is to implement a PK scheme within the scope of the stored procedure, so that the password must be encrypted with the stored procedure's public key, the ciphertext passed into the stored procedure, and the parameter value then decrypted by the stored proc itself with a private key before being used. (Or better, like TLS itself, you could negotiate a Diffie-Hellman exchange using other stored procs, and use a session key.) Unless you can find some open-source implementation of this out there, that you trust, and use it, this will be a very heavy lift. And you have to protect that private key now.

But consider what you are really trying to protect yourself from. In this scenario, the attacker can read your stored procedure calls and obtain the values passed in. Would any user with this privilege also have read access to whatever private key you use, or select/insert/update access to your tables? If so, then even if you go through the labor of implementing PKI at the stored procedure level, your efforts are instantly defeated.

Also let me respond specifically to the idea of hashing the password, with a salt of course, and passing in the hashed value to the stored procedure. If you do this, then the hashed value is now the password. All an attacker has to do, if he really can read your stored proc parameters, is repeat back those parameters exactly as he sees them to compromise the system. He doesn't actually need to reverse the hash and learn what the "plain" password is; the hashed value is the plaintext password now. So this scheme has no effect.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.