Yargh! Unless you've omitted something, or I'm misunderstanding, I think you still have a leak in your design.
To the OP: that's a fairly big question, but here are some thoughts. Apologies in advance for the length of this. Here's the big thing about web security: *any* webpage that a user browses can make requests to your site using the user's (cookie based) session. If all you check for in a request is that there exists a valid, logged in session, you're asking for trouble. Now, other sites can't see the response from requests to your site, so "read" type requests aren't as big a deal, but "write" requests are. Imagine a banking type site. To transfer money from this user to another user the url is like: http://badbank.com/transfer?to=other_id&amount=1000 Even though Bad Bank checks for a user's session, if a malicious site included the above URL in, for example, an <img src="..."> tag, Bad Bank would still see the user's valid session and (incorrectly) assume it was a valid request. Yikes! Using POST instead of GET doesn't help at all since JavaScript can be used to trigger form posts. So a malicious page could still make a phony POST request. Checking the referer header might help, but it doesn't seem like a very robust solution. The saving grace is that malicious pages can't access the response from such requests. So one solution is to challenge all such requests and include a unique token that must be sent back to verify the request. This was fairly common pre-Web2.0, and is still pretty common now, in the form of "are you sure" type confirmations. So now the transaction is like: Webpage (malicious or legitimate): http://betterbank.com/transfer?to=other_id&amount=1000 Better Bank: Transfer $amount to $other_id? <a href="/transfer?to=other_id&amount=1000&token=unique_token">Yes</a> Webpage (legitimate): http://betterbank.com/transfer?to=other_id&amount=1000&token=unique_token Webpage (malicious): Stuck because it couldn't read the response from Better Bank so it doesn't know the token With the whole AJAX/Web2.0 revolution thing, much of these types of requests are being done "behind the scenes", and confirmation pages have gone the way of the dinosaurs. As a result, it's not uncommon for such sites to fall victim to this type of exploit. I think a sufficient solution is to always include a unique token with any "write" ajax request. The session ID is easy to use as the token, but isn't perfect. Really, using the session ID makes some sense conceptually. By forcing the client to send along the session id, the server is basically asking the client, "do you know who you are?" Malicious sites don't have access to the session id, so they don't know it, but your legitimate pages do. The problem with using a session id is if you're using URL rewriting based sessions (where you get something like PHPSESSID=<id> or _jsession=<id> added to your URLs), then links away from your site will include the URL of the current page in the referer header, so you might leak the session id there, and then you're back to where you started with not being able to tell legitimate requests from malicious ones. The best *best* way would be to generate a token for each request, but that adds a lot of overhead on your server to keep track of and verify all of these tokens. A pretty good solution would be to generate a token when the session is created, and store it in the session, but make sure that nothing ever "leaks" that token outside of your site. That's what I do. As far as a framework to do it for you... I don't know of any. In the long run, I think most of it just gets ignored because naive security usually ends up being "good enough" in "most cases". If you're building The Next Big Social Network or something, it probably doesn't matter that much. If you're working on anything related to money, hire an expert :) Good luck. --Erik On 6/5/07, Michael Price <[EMAIL PROTECTED]> wrote:
Hi Michael, On my website I have a lot of pages called via AJAX, some of which are quite sensitive (private messages, user submission data etc.). At the top of every page I have a PHP include which, as well as opening the database connection etc., also includes code to check and authenticate a user if login data e.g. a cookie or session is detected. I also include this include at the top of all my AJAX pages and ensure any database queries are tightly written to ensure they only pull out the relevant data. e.g. logged in user is ID number is 1234, trying to read private message number 5678, my SQL is: SELECT * FROM private_messages WHERE to_user_id = 1234 and message_id = 5678. If the user is then trying to hack the message ID it won't work. Additionally, if a user isn't logged in then the include and / or script knows this and can stop the call and print an error message. I guess what I'm trying to say is apply the same level of security to your AJAX scripts as you do to the rest of your PHP. Regards, Michael Price