Questions answered by this recipe
- What should I do to protect my wiki sessions, and PHP sessions in general?
- What's a session key?
Session IDs and keys
A session ID is some data that tells a server which session you want to use.
A session key is data that you show to the server as proof that you're allowed to use that session.
In PHP, usually the session ID is also the session key: Anyone who manages to guess the session's ID is assumed authorized to use it.
What kinds of session attacks are there?
That's when an attacker manages to select which session ID and key the victim will use for their next actions. Usually aimed to have the victim increase the privileges of that session, e.g. by login. Since the attacker knows the session ID and key, they can then benefit from the newly unlocked privileges as well.
- Standard defense: Assign a new session key often, and especially each time the associated privileges change. Invalidate the old session key very soon, ideally even before assigning the new one. (You'll need to balance paranoia vs. stability here: What happens if the browser fails to receive the new key? Should failure to write the new session be able to prevent invalidation of the old session?)
- If you change multiple privileges in one request, one key change is enough, since from the client side it looks like one operation. You can thus save system resources by only regenerating the key on the first privilege change.
- If you're concerned about race conditions, and invalidation of the old key cannot be guaranteed to take effect immediately accross all involved server instances, try to sort all changes that remove or degrade privileges to apply before the key change, and all additions or upgrades of privileges to apply after the key change.
- Standard PHP defense:
- PmWiki's primary method for adding privileges is the
Session theft / Session hijacking
That's when an attacker manages to obtain a user session's ID and key in order to send it in their own requests. In default config, PHP (and PmWiki) will accept this and grant the attacker's request all access and identity privileges that have been unlocked for that session. It's basically one method of impersonation.
In the beginning of the 21st century, a popular way of having one's website compromised were "stolen cookies", which usually meant cookies with session ID and key in it. Earlier, when websites commonly used the URL to transmit a session key, it often leaked via HTTP referer.
- Standard defense: Depends on the transmission channels available for the session key.
- Standard PHP defense: See the Session Management Basics chapter in the manual.
- Mitigation recipes:
- SessionGuard: Verify some HTTP meta data in addition to the session key.
That's when an attacker uses one service to modify session data of another service. We're gonna focus on the cases where the latter service is your wiki. So it's about an attacker modifying sessions for your wiki using some other service.
- Simple example: The other service could be another wiki in your farm where the attacker can legitimately login with a username that has admin access in your wiki. If both wikis use PHP session files in the same directory, the attacker can configure their browser to send the session cookie for the other wiki to your wiki as well, with adapted cookie name if required. Your wiki will then search for that session ID in the shared session data directory, will find it, read it and use the username and access privileges stored in that file.
- The other service doesn't need to be…
- … a website: It could be some regular program on the server (e.g. FTP server) that can be convinced (FTP: e.g. via symlink attack) to store an attacker-chosen data record (FTP: uploaded file) in your wiki's session data store.
- … malicious: Doesn't even need to know that your wiki will understand the attacker's data as session information, as in the FTP server example above.
- … on the same machine: The session data storage could be shared accross servers via network file systems or databases.
- Shared hosting: On badly configured servers, an attacker might obtain (access to) a webspace on the same webserver as your wiki and install PHP scripts especially designed to meddle with other people's session directories.
- Standard defense: Give each of your wikis (and other services) their own session data storage that only it (and legitimate admins and tools) can access.
- Standard PHP defense:
session_save_path()+ appropriate file system access control.
- For simple PmWiki setups, the appropriate file system access control is usually the same as for your
wiki.d, since they're equally adequate for permission injection: The other service could be used to modify pages' password attributes or content of
Site.AuthUser. (Unless the pages have additional protection other than just their parent directory's permissions. However, if you adjusted permissions in that detail, you should know yourself what's best for your session directory.)