Robert Tweed wrote:
Does anyone know a good resource discussing the issues involved in session
theft? I've read a couple, but none that really address the problem apart
from acknowledging that it is a problem; you just don't seem to be able to
do much about it.
Session theft can be avoided with some scripting both in the client and
the server, at the expense of making the 'back' button unusable on the
client's side. Let me explain before you think I'm mad :-)
The trick is not to use one _fixed_ session id during the wholesession,
but rather a _different_ session id for every client->server interaction
(i.e. every time a new page is fetched from the server). In other words,
multiple single-use session-ids for each session.
A (single use) session id can be calculated from previos session ids and
a secret shared between client and server (e.g. the password used for
authentication of the user). This means that client and server must be
in sync. Along with each request, the client must send the next session
id that the server expects. This is why the 'back' button must not be
used: the session id of the previous page would be sent to the server,
but the server expects to get the session id for a new page. (I haven't
worked at fixing this at the moment.)
The generated session ids must be difficult to guess just by looking at
previous session ids, so a one-way hash can be very useful (my
implementation uses MD5).
To summarise, the steps are:
1.
- The (still anonymous) client requests the login page.
- The server sends back a login page, along with a random session id.
2.
- The user fills in a login/password (or similar).
- The client generates a new session id by mixing the received session
id and the password given by the user (i.e. new_sid =
hash(old_sid+pa ssword)). The username and the new session id are sent to
the server.
- The server gets the username, generates its own new session id by
mixing the (previously sent) old session id with the local copy of the
password. If both client and server agree on the same new session id,
the user is logged in. The server sends back to the client a welcome
page. The generated new session id is stored on the server.
3.
- When the (already authenticated) client requests another page, it uses
a new session id built from the previous session id and the shared
secret: new_sid = hash(previous_s id+password).
- The server works out its own new session id (same process of mixing
the previous sid and the shared secret). If both client and server agree
on the same new_sid, then the client is allowed to see the next page
requested.
4. Repeat #3 above until finished.
This method effectively prevents session theft when the thief has not
access to the computer. Each session id sniffed on the net is useless,
because the server will accept it exactly one time. The session thief
will find it very difficult to guess the next session id, because it
depends on the secret shared by the legitimate user and the server.
The main concern (appart from breaking the 'back' button) is hiding the
password on the client to prevent cross-site scripting attacks that
could retrieve it. This is caused by the need to keep the shared secret
in the client's memory to generate each one of the new session ids.
A working implementation (sorry, no demo) can be seen at
<http://mipagina.ath.cx/diario/adm/>. You can poke at the client-side
javascript to see the details. If enough people are interested I will
set up a demo site with multiple users and make the full source code
available (probably GPL'ed).
Any (constructive) comments will be welcome.
<snip rest of interesting OP>