Starting with the idea from Ed Avis in a slashdot post, I wasted a day thinking up
a password authentication method that would also defend against scam sites while
still avoiding a single point of failure by saving the passwords on the server.
Ed's original post is quoted below:
An HTML form could have a special control for password entry. Rather than sending
the whole password to the server when the form is submitted, the browser generates
a random salt and makes a hash of password+salt+current time. Then it sends the hash,
the salt chosen and the current time to the server, which can verify that the
password was correct. (This does however require the password to be kept in plain
text on the server.)
I am not a cryptographer so there may be some horrible flaw in the above scheme,
but I know there are ways to do this without sending your password to the server,
so you cannot accidentally give away your password to a phishing site. It seems
like the sort of basic and obvious thing that web browsers should support to improve security.
Using Ed's idea as a starting point, I've designed what I think is
a tight and workable solution. Although my system is much more complex than a simple
hash, it accounts for many more sophisticated attacks and thus is more of a completely
new idea than just a new trick. I mentioned Ed out of good sport since his post is what got me
thinking about the subject though.
1. Abstract
Scam sites are becomming increasingly popular these days. Deceiving people to enter their
personal information into a false website is becomming more of a shaddow business, and will
probably only get worse unless something is done about it. Furthermore, few technologies
today account for phishing since SSL only encrypts your data for the scammer to then unencrypt,
and other security authentication methods will not go into the realm of annoying the user and
thus are usually still easily mimiced. This paper outlines a method to not only give
servers the ability to authenticate a password without actually getting the password, but also
how to encrypt specified form elements in a way that render them unreadable to anyone who does
not already know the password. In layman's terms, The password and any other personal data is
unreadable to a server who does not already have the password to begin with,
rendering the data scam sites may receive into rubbish.
2. Pre-Requisits
To make my system work, browser support is a must. Server support can help makes things a
little easier, but in the end I decided it wasn't worth it, and so a few behavior
specifications will do fine for the server. Now I realize that browser support is not
an easy thing, especially considering IE is the biggest dog out there, but from
my experience just about any interface you can build on a website, a scam site can
either mimic, or get around mimicing it with some clever social engineering. For this reason,
my system depends not on the interface, but on how the browser handles forms, inputs, and
the both the data and how it is transfered to the server.
To maintain backwards compatibility, a browser must know what form elements
are regular HTML, and which are to be used with my system. To account for this,
a new attribute called "encrypted" can be added to HTML form element tags to signal
the browser to my system with them. The new attribute would be ignored by older browsers
as it is not part of the HTML specification for them, and hence it would maintain backwards
compatibility. Here is a sample tag with the new attribute:
<input type='text' encrypted>
Now for the major browser specific changes.
Form elements with the new attribute must be UN-readable by both javascript
and any plugins the browser might use. The browser must also pause all javascript, or any
other scripts that might be used in the future, while focus is on such a field.
These contraints are to avoid any keylogging or reading of the raw content entered. Without
such protection, using any kind of hash or encryption would be futile since a scam site
could just get the raw data and transfer it using any number of methods. Furthermore, the
encrypted password field must be UN-writable as well, for reasons given in section 4.
Also, the salt sizes that are used are based on a single start number, so that they may be changed
easily in the future as processor speeds continue to rise. For my example, I start with 32.
32 will thus be known from now on as the capital letter
N.
N = 32
3. Password Verification
Now lets consider a browser has the modifications detailed above. Lets start with the
obvious, and work through how a password is verified without giving an attacker
the password or anything that can be used to get the password.
First, the user will enter their password
P into the password box.
As stated before, nothing can read
the password so it is safe. On form submit, the browser kicks in and does some very cool stuff.
To start, it takes a HASH of P
with an output of 32 characters. The hash will be called
M.
The browser will then generate a SALT of
N*N characters. This string will be
very important for the rest of the website session. If the password entered was blank however,
no SALT is generated, and thus any
encrypted form elements do not display themselves as being encrypted since no
SALT exists to help encrypt them later.
The mannor in which a form element displays itself as being encrypted will be up to the browser,
but an example setup can be viewed in apendix A.
The browser will then create XX by
Blowfish encrypting SALT +
P using
M as the key.
Also note that when I use a plus sign, I mean to combine, not add, so "ABC"+"XYZ" = "ABCXYZ".
M =
HASH(P)
XX = BLOWFISH(
SALT +
P) using
M
Send XX to server.
The server will only store M in its system.
This is so that if the server gets hacked, the attacker only gets the hash, and so
the attacker cannot login using the data in the system alone. To varify the password, the
server will unencrypt XX using
M which it already knows, thus getting
the password P and
SALT. It can separate the password and salt
because the salt is a standard length.
Now this is very important: The server must then hash
P and verify that the output
equals M. If equal, the
SALT is kept for future encryption purposes.
If they do not match, the server should reject the SALT
and display an error message if it chooses to.
4. Further Data Transfers
Once the SALT has been transfered
to a site, the client can use it to encrypt further form data.
To begin, N/2 random numbers ranging
from 1 to N*N
are generated by the browser.
Then the corresponding characters in the SALT
are used to encrypt the data, and the combination of numbers and encrypted data is then sent.
TT =
N/2 Random Numbers from
1 - N*N CC =
SALT[ each(
TT ) ]
XX = BLOWFISH(
data, using CC)
Send TT +
XX to server.
The SALT is thereby used
as an encryptin alphabet, meaning that only some of the characters from it
would be used. This is so that if an attacker found a way to figure out the key from a
blowfish encryption which he knew exactly what the text that was encrypted was, he still could
not decrypt other things. Such a system could easily be done using a hidden encrypted form element
with a value set by a scam site. By using the
SALT as an alphabet,
and only using (for instance) characters 35, 208 ... 4, and 561 from the
SALT string,
you could still encrypt each data without giving away the entire
SALT if one data
encryption was cracked. Also, no more than 64 datas can be encrypted at once.
Attempting to encrypt more will cause the browser to not send anything at all.
Changing the SALT can happen one of two ways.
The server can request the user to enter their password again in an encrypted password form like
before, which will send a new SALT
to the server and overwrite the browser's SALT.
The browser can also generate a new
SALT, either by keeping
track of the password, or asking for it again,
and then simulating a password submittal using the same post/get method and name that was used
during the original password request. This client-controlled
SALT change is to protect the user
from an evil server encrypting "a" in 8000 hidden encrypted forms in groups of 32 per page
in an attempt to crack the entire SALT.
A browser could, for instance, change the salt after every 64 datas encrypted. Tracking the
salt and generating new ones can be done in multiple ways though, and so I leave the exact method
up to the browser.
Also, when a new SALT is generated,
it must be added to the old one. As an example using only letters, if the first
SALT was "ABCXYZ"
and the second was "DDDDDD", the new SALT
would be "EFGBCD". The reasoning here
is that a scam site could trick ther user to enter a known value into a password box, such
as typing a value shown in a picture into the box to verity they are not a script.
If the user has already entered their username and password to the scam site, entering a new
password would overwrite the SALT and
the scam site would get the new SALT since
the value used to encrypt it was known to the scam site. Adding the new
SALT to the old ensures that if the user
enters their real password (not known to the scam site) at least once, no further
SALT can be
known by the scam site without knowing the one sent with the real password. The reason for encrypted
password boxes not being writable is thus explained, since the ability to write to an encrypted
password and submitting the form with javascript could allow a scam site to generate a
SALT they
can decode while completely ignoring anything the user enters as a password.
Conclusions
Well, I think it's a pretty secure system, and would at least help the problem
phishing sites pose to people who don't know better. As long as people are taught not to
enter sensitive data into forms that are not encrypted, and that they always
need to enter thier password before entering the sensitive data, this sytem should work.
If you think of some way to get around such a system, or have extra ideas or just
comments, you can post to my forum under this topic, or email me at:
gte224v AT mail DOT gatech DOT edu