Let’s face it, we use passwords for just about everything these days. That will likely change in the future, but until then, how can you be sure that the companies and websites you entrust your passwords to are storing that information securely?
Well, one approach is to ask them directly how they store passwords.
However from experience, 99 times out of 100, you’ll receive a vague, generic, and dismissive response about password storage along the lines of:
“We can’t tell you how we store passwords for security reasons“
“We take security very seriously…“
“We store passwords securely“
…None of these responses adequately address concerns, or indeed answer the question!
Now, if a business is confident that they are storing passwords securely, there should be no reason not to let customers know exactly how their passwords are being handled and stored.
Here’s a great example from Dropbox who are totally open and upfront about how they encrypt and store user passwords – because they’re confident they’re doing it securely!
So if a business won’t give you straight answers when it comes to password security and storage, they either;
- don’t know how they’re storing your passwords,
- are paranoid that telling you would somehow make their password storage less secure, or
- they’re not confident that they ARE actually storing your passwords securely
If you can’t get straight answers from a business (Technically, under GDPR they should provide you with this information if you make a Subject Data Access Request), then there are a number of tell-tale signs you can look for that may indicate they’re not storing passwords securely….
1) If an arbitrarily low maximum password length is enforced
A low maximum password length is usually indicative that passwords are being stored insecurely (i.e in plain text) in a database.
Now, fields within databases have defined sizes (or lengths) of data they can store. For example, if a database field has a maximum length of 12 characters, it can only store a string of text up to 12 characters in length.
If passwords are being stored correctly, they will be hashed with a random salt before being stored in the database. The process should produce a “hash” string of fixed length.
For example, consider the passwords “password” and “This is a really really long password with some numbers added to the end as well: 1234“
In plain text, the first password is 8 characters long, whereas the second is 86 characters long!
But, if each of these passwords are bcrypt salted & hashed, they produce respectively:
…you’ll note that both of these strings are exactly 60 characters long, despite the first relating to an 8-character long password, and the second relating to an 86-character long password!
Therefore, if passwords are being stored correctly, the length of the hash will always be known and be of a fixed length, regardless of original password length.
As such, there is no reason to enforce a low maximum password length. Doing so indicates that passwords are not being hashed correctly (if indeed at all!)
2) If your password can’t start with or include certain characters
This can indicate that either passwords are being stored in plain text, and/or that passwords are not being correctly “sanitized” (escaped or ideally parameterized) when running database queries. Let’s take the first scenario:
Imagine using Excel (or another spreadsheet application). If you enter “abc” into a cell, it’s interpreted as being text. However, if you enter a “123” into a cell, by default the spreadsheet interprets that as the number one hundred and twenty three, rather than the string of characters “123”.
Some database’s which have not been correctly setup can behave the same, in that data fields which begin with a number are then interpreted as a numeric, rather than a string, value.
Now let’s take a look at the second scenario, and a couple of examples to illustrate….
Let’s imagine that a user’s password was the string “$mypassword”. In some programming languages, words that start with a “$” are interpreted as a variable rather than as “text”.
If we take the following simplified example database query:
SELECT * FROM
accountsWHERE email="x" AND password="y";
The above query would typically search an “accounts” table in the database and return an account record if both the user’s email address equals “x” and their password equals “y”;
If the password was “$mypassword”, the underlaying programming language could try to evaluate this as a variable containing a string, and as the variable “$mypassword” won’t have been defined in the code, it could be substituted for a blank value.
Taking the above example, let’s assume that user enters their email address ([email protected]) and password (F1dYnsSJo6). The following query may run:
SELECT * FROM
accountsWHERE email="[email protected]" AND password="F1dYnsSJo6";
The above query would typically search an “accounts” table in the database and return the single account record for the user matching both the email “[email protected]” and the password “F1dYnsSJo6”;
However, consider that rather of being “F1dYnsSJo6” the user’s password was instead:
F1dYnsSJo6" OR 1=1
This would result in the query:
SELECT * FROM
accountsWHERE email="[email protected]" AND password="F1dYnsSJo6" OR 1=1;
The above query would return a record from the “accounts” table where the user matched “[email protected]” and the password matched “F1dYnsSJo6”, but notice also the “OR 1=1” part – this will return records from the database whenever 1=1 (i.e. always). The result would be that the entire “accounts” table in the database would be returned.
This process is commonly known as an “SQL injection”, but it can be easily mitigated by “parameterizing” database queries, i.e.:
SELECT * FROM
accountsWHERE user=? AND password=?;
The “?” are then substituted with data when the query is executed with, but that data is confined to that parameter. Therefore instead of `F1dYnsSJo6″ OR 1=1′ being interpreted as two different parts of a query, it would be interpreted as just the password parameter.
So, if a website/business won’t allow you to enter special characters in your password, either they’ve not correctly setup their database architecture, or they’re not correctly hashing your password before storing it, or they’re not running safe “parametrized” database queries, which could potentially leave all users accounts open to exploit.
3) If when you login you’re required to enter certain characters from your password (rather than the whole password)
Once you’ve initially setup a password, some sites then only require you to enter a few characters from your password each time you login (i.e. the 1st, 3rd and 7th characters, etc).
If you’re ever asked to do this, this is a clear indication that your password is being stored insecurely.
“Secure” password storage should be achieved through a strong one-way hash. “one-way” means that a password can be encrypted but not decrypted.
In secure password storage, when you enter you full password, it is encrypted (hashed) and compared to the hash of the original password you set up. If the hashes are identical, then the password you just entered matches the original password you setup.
However, this secure (and correct) method only works for your entire password.
You can’t enter a subset of characters from your password and have the resulting hash match your original password hash – as it never will!
Therefore, if you’re asked to enter a subset of characters from your password, it means that the company/website can see/decrypt your original password back to plain text, Hence, they’re not storing your password securely!
4) If when you contact a business, you’re required to provide certain characters from your password
As per the above, and this is quite common when using Live Chat/help desks of various websites. Remember if they ask for specific characters from your password, then they are NOT storing your password securely for the reasons outlined above.
5) If they offer a way to “retrieve” a forgotten password
Let’s face it, we’ve all forgotten a password at least once, which is why websites and businesses try to help us out when we do.
If passwords are stored securely using a strong one-way hash algorithm, then the original password can never be “retrieved” or decrypted, and the only option if you can’t remember it is to reset it.
However, if a business allows you to “retrieve” your original password – perhaps by sending it to you via email, etc, then they are NOT storing your password insecurely. In these instances your password is being stored either in plain text, or in a way that the website/business can easily decrypt it.
So I hope the above tips of things to look out for if a business is being less than transparent and upfront about how they store your passwords help you make more informed decisions about the websites and services you use.
Perhaps my most important piece of advice though would be to ensure that you NEVER use the same password more than once.
That way if a particular business is storing that insecurely, then should it ever be revealed/breached/hacked, it won’t affect your accounts on any other websites/services.
Password Managers are a great way to generate and organize unique passwords for each of your websites/services.