Currently, my authentication looks something like this:
Login over SSL:
- PHP checks username / password against database.
- If they match, a session cookie is generated, sent and stored on开发者_开发百科 the Db
- (A session cookie looks like userID:IP:random_characters:timestamp)
Perform action over SSL:
- PHP checks cookie against session database.
- If the session matches, is under an hour old, and the user id & IP matches it is considered valid.
- If the session is valid the action is performed and a new session cookie is generated.
- (If the action is a logout, the session cookie is set with an expired time)
If a cookie is hijacked and the IP is spoofed within an hour of the victims previous action, the attacker will be validated and a new session will be generated. Are there other possible issues I'm overlooking?
What's considered the best practices? I'd like to tighten up the security. Thanks!
You could tie the session not only to the IP but also to the user agent. Then a not-so-smart attacker has another obstacle.. not a big one though as he probably has a way to steal more session cookies if he could steal one and then just try various useragents. However, to make it not as easy as changing the useragent and retrying with the same cookie, delete the session to require a new login (using username/password).
Last but not least, there is CSRF: If the user is logged in an external site could make him perform an action. As the user's cookie is valid this action will be performed. You can only circumvent that by passing random tokens via URL. An easy way which even allows browsing with multiple tabs would be using a (random/changing) part of the session ID for that. Random tokens only valid for a single request would be even more secure but they are extremely annoying as they prevent people from using multiple tabs (even though the app could simply store e.g. up to 10 tokens and only invalidate old tokens if there would be more than 10 - that would allow you to use not just the most recent token but also the one from the page you've been on before opening a new tab). But most likely a token valid for the whole session is sufficient; assuming you use the session id or a part of it you have a bigger problem than CSRF if someone can get the session id of other people
Regarding logout, I would not only use an expired time but also an empty value - so if something goes wrong (I've seen both servers and users with horribly incorrect (days+) clocks).
精彩评论