No subject


Fri Jul 9 09:46:20 CDT 2004


there is no way to get a cookie header through to an HTTP proxy. Still,
you are right, this is aesthetics, so I won't forcefully argue this
point.

Security, on the other hand...

> Unless you do this for every poll request, you're not avoiding the 
> hijacker.  And if you're doing this with every packet, not only are you 
> taking on tremendous overhead, you are providing many many opportunities 
> to snag your username/password.
> 

I'm exactly proposing that you do this for every poll request. The
username/password is of course not transmitted cleartext with each
request! Let me be more explicit about the problem, and about what I am
proposing.

The attack is very simple. An eavesdropper watches the traffic and sees
that the username is some string u, and the Session ID is some string x.
The attacker does not know the password because digest authentication
was used. Since the protocol is well documented, the attacker knows that
this is the session ID. She can then write a simple program in, I would
conjecture, less than a dozen lines of code, going something like:

socket = connect("webim.jabber.com",80)
send(socket,"<HTTP stuff>")
send(socket,x)
send(socket,"<iq type='set'><query
xmlns='jabber:iq:register'><username>"
send(socket,u)
send(socket,"</username><password>You've been
owned!</password></query</iq>")
close(socket)

Thus changing the user's password to whatever she likes. This attack is
much easier to carry out than an equivalent attack on one long TCP/IP
connection, since it has become at least moderately difficult to spoof
such a connection.

The solution I propose is to add a hash over the user's password, the
session ID, and a request sequence number to each request. The password
is the shared secret, and the session ID and sequence number prevent
replay and foreplay (*giggle*) attacks. So the new send-request would go
something like:

send-request(socket,password,session-id,request-body)
  static seqnum = 0
  auth-token = Hash(password,session-id,seqnum)
  send(socket,"<HTTP stuff>")
  send(socket,session-id)
  send(socket,auth-token)
  send(socket,request-body)
  seqnum = seqnum + 1

The server would be responsible for keeping track of the same sequence
number for the session and verifying the correctness and uniqueness of
the token sent with each request.

I am pretty sure there is no opportunity for an eavesdropper to learn
the user's password or spoof future tokens provided that a secure hash
function is used. I am pretty sure there is no opportunity for an
attacker to use a replay attack so long as session IDs are not reused.
Thus, I am pretty sure that the security of this protocol with this
mechanism in place is on par with that of the long TCP connection.

Now to address "tremendous overhead". I would first submit that the
overhead is worthwhile given that it significantly improves the security
of the protocol. I would then conjecture that the overhead on the client
side is negligible if the polling interval is on the order of seconds,
which you and Joe have both indicated it is. As for the server, I agree
there is a significantly greater amount of computation that must be
done, however, I would also point out that it is easily optimizable. The
values of all the authentication tokens (Hash(password, session-id,
seqnum)) for the entire session are determined as soon as the session-id
is determined. Thus, the server can precompute as many of the
authentication tokens as it wishes, and simply check each one with
precomputed values as they come in. You could have an idle thread
running in the server that just precomputes these tokens for the
sessions when it's not busy doing other things. Obviously we can't know
for sure without testing, but I conjecture that this type of
optimization would make the load quite bearable.

> Nothing is preventing digest or 0k authentication.  Over SSL.  While I 
> admit that this may not be an adequate solution for the department of 
> defense (Note: IANAL), it has proved sufficient for any number of 
> financial applications.

I *do*, however, think that the computational load for using full SSL
for each request would be prohibitive, since this type of optimization
is not possible.

Do the people using this for financial applications know how easily
their accounts can be hijacked?
 
> Like I said, JIM does not support HTTP polling.  Try out our web client.

It is an interesting fact of life here at MIT that using POP3 from
virtually any machine on campus will cause your password to be e-mailed
back to you by an automatic daemon set up by some enterprising nerds. In
this type of environment, I would not try a client that uses this
protocol under any circumstances. While obviously this is somewhat of an
extreme case, I would be suprised if anyone who fully understands the
security issues with this protocol uses the web client for financial
applications.

Again, since this is an informational JEP, I'm willing to totally
concede all the aesthetics points. The protocol works. But, unless I am
heinously mistaken, I find the security problems extremely serious.

-Mike




More information about the Council mailing list