|
Cryptography
Security
Programming
Web Applications
Consultancy
Cryptography:
RSA
JavaScript MD5
Vigenere Cipher
Word Patterns
JavaScript MD5:
Scripts
Instructions
Protecting Passwords
Advanced Authentication
Other Uses
Browser Test
Protecting Passwords
Play real money casino games on the leading online casinos and online poker rooms
A user's password is the crown jewels of any password-based authentication system. Such an important asset needs protection; best practice is that a password is encrypted when:
it is transmitted over the Internet, or
it is stored on a server.
This is the bare minimum, that all sites should be doing. Some sites require strong security, such as online banking, and use SSL. SSL offers strong protection, but can be costly to implement. Many sites do not need SSL, which is a reasonable business decision. However, most non-SSL sites transmit passwords over the Internet without encryption. This is not reasonable - it's below the bare minimum that everyone should be doing.
By using JavaScript MD5, sites that do not use SSL can still meet these basic minimums. While this is not as strong as SSL, I recommend this for all non-SSL sites that use passwords.
Implementing Hashed Passwords
I generally recommend using an authentication library, rather than implementing authentication yourself. Most languages and frameworks have such a library. At present, few authentication libraries support JavaScipt hashing, only:
repoze.who-jscrypto - a set of plugins for repoze.who to support JavaScript cryptography (Python).
If you're involved in the development of a framework and would like to add this feature, do email me.
The instructions below describe in general terms how to implement an MD5 authentication system. They avoid referring to any specific server-side language, so apply equally to ASP.Net and Ruby on Rails. Some language-specific instructions are also available, from other sites:
PHP
Perl
Some notes on using PHP and Java. more...
Technical Details
Session Cookie
When the user does a successful login, the server issues a session cookie. This is effectively a random number that an attacker can't guess. The cookie is used to authorise subsequent access to protected pages. When the user does a logout, the cookie is deleted. This basic design is used by almost all web authentication systems.
Challenge-Response Login
The difference with an hashed login is the "challenge-response" exchange. The server generates a challenge and sends this to the client, as a hidden field in the login form. The simplest challenge to use is the server's current time. Once the user has entered their password and clicked login, the client performs a hash operation including both the challenge and the password. It sends the result to the server, and the server checks this against its own calculation. During this exchange, the password is never transmitted unencrypted. If the hash is captured, it cannot be used again, as the challenge changes for each login. I recommend using SHA1 as the hash algorithm, simply because it is the smallest JavaScript file.
Storing Passwords
The server stores password hashes, instead of unencrypted passwords. A random number unique to the server is included in the hash. This number is called the "salt", and it is not secret. It is also included in a hidden field in the login form. The purpose of the server-specific salt is to ensure that a captured password cannot be used on a different server.
HMAC
Both login and storing passwords require hashes that include both the password, and a random number. We could simply hash the two strings concatenated. However, there is an alternative technique called HMAC, which uses two hash operations and some extra logic. This is specifically designed to be secure for such purposes, making it preferable to simple concatenation.
Some further technical considerations are discussed in the advanced section. more...
Adding MD5 to an Authentication System
Store the server salt in global application configuration.
Modify the login form:
Add a hidden fields for: the server salt, the current server time, and the password hash
Add a script tag to link to md5.js
Add a JavaScript onsubmit event:
pwhash.value = hex_hmac_sha1(hex_hmac_sha1(password.value,
server_salt.value), server_time.value);
password.value = "";
Modify the handler that receives posted login data:
Check the time stamp received from the client is within the last 5 minutes.
Calculate hex_hmac_sha1(password stored on server, time stamp).
If this matches the hash received from the client, the login is successful.
Consider adding code to cope with JavaScript being unavailable. more...
Update registration and change password:
Add a hidden field containing the server salt.
Add a script tag to link to sha1.js.
Add a JavaScript onsubmit event:
password.value = hex_hmac_sha1(password.value, server_salt.value);
confirm_password.value =
hex_hmac_sha1(confirm_password.value, server_salt.value);
If you have an existing site. the main challenge is how passwords are stored in the database. If they are currently unencrypted, you can do a one-time operation to replace them with hashes. If the passwords are already hashed, you may have some difficulties. You will need to identify the hash algorithm in use, and create JavaScript code to match it.
Risks
The following technical risks affect this system, as well as all the general risks that affect web applications. For most sites these are not particularly serious. In general, sites that require greater protection should use SSL, although strengthening the system is possible. more...
Session ID is Unencrypted
Although the password is always encrypted, the session ID is transmitted unencrypted. If an attacker captures this, they can perform a "session hijack" attack, to access the user's account. The same risk exists for sites that use SSL to protect the login process, but revert to non-SSL after the user has logged-in.
Replay Attacks
If an attacker captures a login, it is possible to re-use the password hash, until the timestamp expires. This is generally a minor issue, as an attacker who can capture the login can almost certainly capture the session ID. For web sites that store sessions in a database, this can be easily fixed. more...
Active Interception
Over the web, JS cryptography can only protect against passive eavesdropping, as the JavaScript itself is downloaded over an insecure link. If an attacker can modify network traffic, they can make malicious changes to the JavaScript code.
Registration and Change Password
Both registration and change password transmit a "password equivalent" over the Internet. If someone captures this, they can use it to login to the site. The unencrypted password is still never transmitted over the Internet.
Brute Force Attacks
In a "brute force" attack, an attacker tries many different passwords for a user, until they eventually succeed. The use of challenge-response login creates a new risk here. If an attacker captures a password hash, they can later conduct an offline brute force attack, where passwords are checked without accessing the server. This bypasses any server restrictions, such as locking an account after three incorrect passwords. Some simple steps can make this harder for an attacker. more...
Stored Password Equivalents
The hash the server stores is a "password equivalent". If someone captures this, they can use it to login to the site. However, the protection is still worthwhile, because its main purpose is to stop an attacker using captured passwords on different sites. If someone has captured a stored password from your database, they have already compromised your site.
? 1998 - 2009 Paul Johnston, distributed under the BSD License Updated:30 Jun 2009 |
|