Please, for f***'s sake, salt your passwords

Please, for f***'s sake, salt your passwords

In recent weeks, we were hired to check a security breach in a company systems. This company have a lot of projects running in a few servers. Each project is used for a different customer and each project has its own database. The setup of the databases was ok, the database technology they use is MySQL, each database has its own MySQL user. MySQL root user and linux root user are only accesible from the server itself. So, this far, so good.

The problem is that every project recycles the code that handles the system users, including the login. So every project's database has a table named 'user', like this.

CREATE TABLE user (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
name varchar(100) DEFAULT NULL,
email varchar(20) DEFAULT NULL,
password varchar(100) DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

And every project, uses the same code to handle this table data including the login. The issue is that the password was stored hashed using simple MD5. If you are not familiar with this term, check this link https://en.wikipedia.org/wiki/MD5

MD5 is a really insecure hashing function. It can be easily cracked via a collision attack with a resourceless computer. And also there are diccionaries, lookup tables and rainbow tables with millions of inputs that have already been cracked. Check this https://crackstation.net/

Before their systems where modified, the records in the 'user' table looked like this:

+------------------+----------------------------------+
| email | password |
+------------------+----------------------------------+
| [email protected] | e99a18c428cb38d5f260853678922e03 |
+------------------+----------------------------------+
| [email protected] | e99a18c428cb38d5f260853678922e03 |
+------------------+----------------------------------+

In this example, both users have the same password hashed in MD5, if you use the link that I wrote before, you will get the password in plain text: 'abc123'.

The security breach was made through a more or less elaborated SQL injection attack and we can assume that the 'user' table of every project was compromised.

In our final inform, we identified the posible SQL injection attack, we recommended to use a different hashing function (sha256 was our suggestion) and also we recommend to salt the passwords.

Salting a password is made to randomize the hashes by appending or prepending another random string (this extra string is the 'salt') to the password before hashing. This makes the same password hash into a completely different string every time.

We recommend an alter to the 'user' table:

CREATE TABLE user (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
name varchar(100) DEFAULT NULL,
email varchar(20) DEFAULT NULL,
password varchar(100) DEFAULT NULL,
salt varchar(100) DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

With this change, the records in the 'user' table look like this:

+------------------+------------------------------------------------------------------+----------------------------------------------+
| email | password | salt |
+------------------+------------------------------------------------------------------+----------------------------------------------+
| [email protected] | 3ccfc6d59d97b314d2f43afc326cfed126e0a094d2f61abb51b590ed1e52be5a | BGqNU2sxhXkhVw3hPFKPkt0wiAtpaSSgsOSGYhWDZLw= |
| [email protected] | b50a93f85f4722596ac453fd17bed870e2bbad25a04c5b0a7a427be6a3e7f0c5 | gkc/DrlyTQQeCAe9VMW6N0al9BqUl27m4DIqpTD8eqE= |
+------------------+------------------------------------------------------------------+----------------------------------------------+

In this example, both users have the same password ('abc123' again), but as you can see, the hashes are completely different. So dictionaries, rainbow tables and lookup tables are useles now.

For a more detailed information look at this link https://crackstation.net/hashing-security.htm

Please, if you are developing a system, consider this, is for our own good. Remember that United States is probably in its way to elect someone that said this about the internet https://www.youtube.com/watch?v=JcmiHx5Yf2I (and also a climate change denier, and is against women's rights to choose, against free trade, wants to bring coal back, etc...)

I hope someone finds this post useful.

20 Likes

Been there, done that. Could not agree with you more. Great post mate. Just the right amount information for a TL;DR on the subject. Seriously, great post. :)

Cheers,
-CloudPlumber

2 Likes

secruity n00b here.

What if you were to hash random wikipedia articles and throw the password at some random place in there?

You can use the wikipedia article html as the salt, but is overkill. Hashing functions are processor intensive, they make a lot of math operations

So it is all about adding random shit to the password before hashing?

Yep, that is the trick, it's simple and elegant. That way, two identical passwords have totally different hashes.

1 Like

Dear imaginary diary: Today I learned a thing

5 Likes

Thanks for posting this. In the process of rewriting a project of mine and this will be handy.

Feel your pain started working at a new company who needed a software dev. Nearly cried when I saw the DB and code using MD5 and no salt. Had to show them how easy it was to break into there system, literally had nearly everyones pw's by the end of the day.

Does amaze me how companies think they can get away with only paying for there website once and never have to upgrade it again (in this case an MIS). Not sure when salting came in but was shocked to find the code so poorly written even for 5 years ago (SQL injections possible all over the site, no sanitation at all). Maybe one day people will learn that you really can't scrimp on Software Development.

Question about this.

Are you able to obtain AD credentials from SSO with something of this nature? I'm unfamiliar with the inter working of our working softwares, but they authenticate with LDAP so I'm unsure if I need to dig deeper into that.

Spot on about MD5 though.

You will need an intermediate process, LDAP uses the users and passwords from the operating system. Linux users passwords are hashed bu default.

There is a good article here describing current best practices and upcoming methods for storing password hashes in several languages https://paragonie.com/blog/2016/02/how-safely-store-password-in-2016

1 Like

First place I worked out of college kept passwords in plain text for everything, I pointed out that this was crazy, but apparently the users forgot their passwords regularly and just wanted to phone up to ask what they were rather than reset them so it would be less convenient for them. Because of this the use any kind of encryption was forbade by the company owner.

I didn't stay there long.

allways atleast md5 your password before they're saved, atleast on a breach it will give more then one result of plain text as result.

I know if a couple companies that keep plain text passwords.

The objective is to add random strings to the md5 hash. Then they can't easily search a table of known password hashes. This also helps keep hash/email pairs to a minimum across many compromised databases.

We should plan on the database being stolen, and minimising damages.

MD5 is cracked sortta easily, but atleast it results in more then 1 result at times.
Best case you do some AES or what ever encryption string which is inserted into your database, but dependant on your system user base, this solution can cause some pretty massive computational problems.
Basically evaluate your usecase, then choose the level of encryption.

MD5 should NOT be used. MD5 hashes can be computed so fast that salting almost doesn't matter. Passwords properly salted and hashed using bcrypt can take days per password to crack, versus minutes or seconds for MD5. Please don't advocate for MD5 or even the sha functions. bcrypt should be the default method at a minimum.

4 Likes

As @SudoSaibot said, every system developer should consider the worst case scenario, there is no such thing as a completely secure system. Also we have to babysit users, because a lot of users (I will say almost all) use the same email and password for every service.

Multiple results in 'dehashing' MD5 depend on the entropy of the password, I agree with @candybar, MD5 is more or less like plain text (but I still consider sha2 family quite secure), bcrypt and argon2 are currently our best options.

1 Like

no

do not use md5 for passwords. it is unsuitable; to the point of being negligent.

further, do not invent your own salts. the salts you use need to be cryptographically secure (randomly picking indexes from an alphabet doesn't cut it). e.g., in PHP, you should be using something like:

$hash = password_hash($raw_password, PASSWORD_DEFAULT);

this (currently) results in a bcrypt hash with a cryptographically secure random salt and a reasonable cost (which can be changed via options as appropriate for your hardware).

There's a fundamental difference between encryption and hashing. hashing is not reversible. you should not be relying on encryption to keep your passwords secure, because encrypted passwords can be decrypted.

1 Like

Not my thread but thanks for responding everyone. Going to use some of this on future projects.