Вопрос

I am interested in the subject of securing PHP sessions, without the use of SSL.

For my surprise, if a man-in-the-middle sniffs the packets exchanged between the user and the server it is very easy to steal the session, even if it is authenticated . I know that there are some tactics to limit damages, such as, changing sessionid when logging in/logging out, recording/checking user system parameters (e.g. OS, browser).

However if during a session ,which is already authenticated and not logged out (there was no time for time out also), the attacker is able to get the session id, then he can easily hijack the session (as far as I understand the problem).

I thought about a possible solution, where during the login authentication which is ciphered, the server could send a random session-password to the client. The session-password would be only valid during that login session. So every message exchanged during that session had to be signed using the session-password (e.g. MD5(session-password+message-contents)).

Is the problem fixed? What are the weaknesses of this approach, assuming the attacker is not able to crypt-analyse the initial login exchange?

Это было полезно?

Решение

Your proposed "signing" solution requires client-side behaviour - you therefore need a client-side application that can do the signing.

If you're writing Flash/Java applet/Unity or any of those plug-ins, then you can follow your plan as you can control the client more closely and add routines to do the signing.

But I assume you're delievering HTML pages to a browser without using a plugin? If so, you have two choices, really. The fist is SSL (that you're ruling out) as it's built into the browser. The second is Javascript. For maximum security you need to somehow mimic SSL, including with client-side storage of the encryption (public) key / algorythm (so that they never travel together with the messages). You'd want to get as close to the public/private key + handshaking of SSL as possible - which is no mean feat. As suggested by sarnold, you'd want a strong encyption key. Check out http://www.jcryption.org/ for an example - others appear with googling.

If that's a bit over-the-top, your most viable solution would probably to negotiate a simpler encyption algorthym using JS: you send a "key", store "key" in a cookie on browser, all communications via AJAX and you create a simpler signing machanism based on that key (plus possibly another variable that the client shared with you during an initial handshake). Anything that doesn't decode or match the key, then kill the entire session and start again.


sarnold has good points in his answer that md5 and SHA-1 are to be avoided; and some even consider SHA256 to be getting wesk for today's computers, but considering you need to implment a solution in JS, for speed you may be tied to something as "piddly" (my analogy) as md5. So your best defence for this is accurate logging and brute force / error detection. Any messages arriving garbled (and you could check at either end) should be logged and monitored. Too many failures and the IP address gets banned - and keep logging.

Другие советы

You'd want to use something like HMAC instead of your simpler MD5 -- and you'd want to use SHA256 or larger, since MD5 is known to have weaknesses and SHA-1 is starting to feel weak too.

But even with these changes, your scheme would still be vulnerable to replay attacks, where an attacker could re-send the request over and over again and your server would happily re-execute it every time. This is no big deal if it is just posting photos of the latest beach trip but if it is sending a purchase request for $1000 ponies, someone is going to wind up with a lot more ponies than they might expect.

So you'd need to add a nonce to the protocol.

There are liable to be other problems -- after all, TLS is now on version 1.2 after three iterations of SSL. Just stick with TLS and be happy.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top