One, you don't use MD5 to "encrypt" or "store" your passwords. MD5 is a digesting or hashing function (hence the name Digest::MD5, which means that the process is definitely a one-way street: you can't undigest a hash value and learn what the original password was.
Two, while you're not concerned about "many users using the same password," you ARE concerned with the back end, where someone has access to your password store. This doesn't have to be direct database access or file access. Depending on protocol, this may also be a man-in-the-middle who might get to see unencrypted rsync activity from one server to another within your enterprise.
There are two key weaknesses in unsalted hashing: (1) someone looking at the hash values and deducing which users use the same password, and which users use different passwords, and (2) someone creating a useful dictionary of possible passwords and their associated hash value. Salt solves both concerns.
Let's compare passwords using three approaches. We show a table with the original passwords for several accounts, the password when passed through an encryption (and thus reversible) transform, the password hashed without salt, and the password hashed with salt.
USER PASSWORD ENCRYPTED UNSALTED SALTED joe GoJets STEjOg 32F8ABC2 $&AB3A262C frank Br1tney YENT1Rb 5158BAD3 ^%1340CF01 mary GoJets STEjOg 32F8ABC2 (*7638BA7D
From this table, we can see some flaws.
I've picked a trivial function for encryption but more complicated ones would suffer the same vulnerability: figure out the key and you can unencrypt to restore the original passwords.
Users mary and joe use the same password, and you can see that with unsalted and encrypted password stores, but you can't see that with the salted store. If you used the unsalted store, then the a dictionary can list hash value 32F8ABC2 and the password "GoJets".
Okay, why is knowing common passwords a concern? If you wanted to socially engineer other things that only user mary can access, you might find talking to user joe to be a softer target, and user joe might leak other facts about user mary (her basketball team, her birthday, her dog, etc.) without anyone realizing it. Out of a list of fifty different users with forty-nine different passwords, the one guy who uses the same password is more likely your weak user joe.
Adding salt makes a dictionary have to store a much larger number of hash values for each possible password. Hopefully, with enough salt, the dictionary must be many terabytes or larger, which makes dictionary attacks far less tenable. Better encryption OR hashing functions will also make the hidden value longer, which is to reduce collisions (two different real passwords with the same hidden value), as well as make dictionary computation harder.
Update: Yes, salt must be chaotic/random to be of any use at all, it's really part of the definition of salt in this context.
[ e d @ h a l l e y . c c ]