0

Software development environments seem to benefit when problems can be solved "higher up the chain".

For example, many web platform features that are now natively supported in both JavaScript and CSS used to require much labor and expertise from developers to implement, but are now as simple as adding a new HTML attribute or CSS property.

Authentication is a problem that can be time consuming, error-prone, or insecure if not implemented correctly. It seems like password management could benefit from being moved "higher up the chain" from the application layer to the database management system.

By providing password management at the database layer, one could simply treat passwords as plaintext for purposes of READ / WRITE operations and the database layer could manage all of the details of hashing, salting, peppering, timing attacks, hashing costs, updating algorithms, hash history, etc. Specifically, it seems like this could be as simple as changing a column type to PASSWORD (for RDMBSes).

Perhaps there are non-security constraints that would make this undesirable (e.g. performance or other implementation problems). For instance, resolving timing attacks might need to occupy database server threads for longer than necessary.

Are there security reasons that would prevent a database management system from providing a PASSWORD data type?

2
  • Note that the database is further down, not up. Commented Aug 21, 2021 at 5:22
  • The application is between the user and the database. For this reason, my mental model says the database is "higher up". However, none of them are affected by gravity. Commented Aug 22, 2021 at 14:35

2 Answers 2

1

There are a bunch of practical problems with this approach if you implement it securely, and the only way to avoid those is to implement it insecurely, which is likely how people would end up implementing it.

First, in order to securely store a password, you need random salt. That means that a function like PASSWORD('password1') is not deterministic, and a database lookup like SELECT id, user, password WHERE user = ? AND password = PASSWORD(?) is going to require a lot of custom logic to implement correctly and it's going to be inefficient to look up, which leads to the possibility of DoS attacks on the database. Of course, if you're using an insecure password function that's deterministic like MySQL's PASSWORD, then this problem goes away, but you have an insecure solution.

Second, there is no agreement on the single right password hashing approach. Argon2 and scrypt are memory hard and are preferred these days, and bcrypt is still a robust choice, but for FIPS-certified software, only PBKDF2 can be used. It would be irresponsible to use PBKDF2 when there are more robust alternatives that are more resistant to attack, but also people want to be able to sell software to governments. Thus, the choice that will probably be implemented is the one that works everywhere, and will be worse for security as a result.

Third, there is no agreement on the right parameters for all environments. Even assuming we got everyone to agree on something like Argon2, the amount of memory and CPU to use when you're hosting a small site on shared hosting versus when you run a top 100 site on your own machines is going to differ. The latter site is going to have much more memory and CPU available to it and will be able to achieve a better level of security than the former. However, if we use one parameter set everywhere, we'll decrease security for large sites, which are a bigger target, when we don't have to.

Fourth, I would suspect most users do not have encryption set up on their databases, and as a result you're shoveling plaintext passwords over the network when you could not do that. By not sending passwords to the database, we avoid the situation where someone breaks into our network and siphons up plaintext passwords.

Fifth, we know full well that database developers are not well versed in cryptography. PostgreSQL for a long time used MD5 for passwords, and it currently uses SCRAM-SHA-256, which uses PBKDF2, when as mentioned we have better alternatives. MySQL and MariaDB, last I checked, both use unsalted schemes which are not suitable for non-pseudorandomly generated passwords. Thus, it is unlikely that we will get good quality, secure implementations representing the state of the art in cryptography.

Sixth, if passwords are hashed securely, then there can be no good reason for practical limitations on the set of password characters. Any reasonably sized normalized UTF-8 string should be acceptable. However, since we know developers are bad at passing strings securely to the database, we're likely to end up with either SQL attacks from passwords, or overly cautious developers who aggressively restrict password characters, both of which are bad for security. If we hash in our application, then we never have to worry about that.

So while these are mostly practical problems, they end up intersecting with the security problems in unpleasant ways, and as a consequence, you're likely to end up with insecure solutions that happen to be convenient to implement.

2
  • That makes me wonder why some banks still limit the characters you can use in client's passwords. Clearly, the entire UTF-8 encoding needs to be accepted. I suppose COBOL has issues with such advance technologies... Commented Aug 21, 2021 at 16:51
  • Thanks @bk2204. Regarding salt, I was thinking some prior requirement would be necessary (like having a primary key), similar to how MySQL handle's AUTOINCREMENT or ON UPDATE CURRENT TIMESTAMP. That said, the need for an encrypted connection alone is good enough reason to not implement this at the database layer. Commented Aug 23, 2021 at 19:09
0

A personal thought about this, already many people don't know how to safely send a regular string to the database... let alone sending a password. (See Is single quote filtering nonsense? as an example of issues with strings.)

That being said, MYSQL has a PASSWORD() function¹ that you can use to save a password in a string. Pretty close to what you're talking about.

Most languages now have extensions that will hash the password and give you a string to save in the database. They may even have a compare function so you don't have to do much to know whether a password entered by the user is a match.

In terms of security, I think the main issue is that you often open your database without encryption. So hashing the password beforehand is safer. Having encryption on your database connection is also going to slow down the queries. Everything will have to encrypted/decrypted before it gets transferred.

¹ As noted by Gh0stFish, the PASSWORD() function uses SHA1. They also offer a few other functions such as MD5(), SHA1(), and SHA2(), all of which are not considered good enough for password security. For much more about password hashing, I suggest this question and its many answers with many updates: How to securely hash passwords? — I guess this means database systems are slower in adopting new technologies because updating their code is more costly (takes more time to make sure it all works properly) so it's easier and safer to have it in your language (i.e. adding some functions in a language is safe if you don't call said functions so your old code continues to work as expected).

1
  • 1
    Worth noting that the PASSWORD() function is based on SHA-1, which should not be used for storing passwords. Nor should the MD5(), SHA1() and SHA2() functions in newer versions of MySQL.
    – Gh0stFish
    Commented Aug 21, 2021 at 8:50

You must log in to answer this question.

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