security with login, capabilities and session key

security with login, capabilities and session key

by Johannes Burk -
Number of replies: 4
Picture of Core developers Picture of Plugin developers

I have a question concerning the moodle functions require_login, require_capability and require_sesskey.

Moodle core code fires the require_sesskey function (or an if statement with confirm_sesskey) before executing some code that changes the database. It is also recommended by this dev doc site: https://docs.moodle.org/dev/Security#Don.27t_trust_any_input_from_users

The PHP Doc comments says for
require_sesskey:
Check the session key using confirm_sesskey(), and cause a fatal error if it does not match.

confirm_sesskey:
Check the sesskey and return true of false for whether it is valid. (You might like to imagine this function is called sesskey_is_valid().)
Every script that lets the user perform a significant action (that is, changes data in the database) should check the sesskey before doing the action. Depending on your code flow, you may want to use the require_sesskey() helper function.


Why is this required and is it really needed when I already checked with require_login and require_capability? IMHO require_login have to deal with the session key also. I couldn't find any helpful documentation about how moodle handles with the session key in the actual functions. 

Average of ratings: -
In reply to Johannes Burk

Re: security with login, capabilities and session key

by Davo Smith -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

require_login does not check the sesskey, otherwise every URL in the whole of Moodle would need to include the sesskey - it is only checked when you are doing an action that could cause a change (e.g. delete a user, add a forum post, etc.)

The sesskey is there to stop problems if a user posts a link like this in a forum:

[URL of moodle site]/admin/user.php?delete=2&confirm=1

and then tricks an admin into clicking on it.

The reason the link doesn't work is that the user posting the link won't know the sesskey for the admin user's current session, so the 'require_sesskey' check will fail (yes, you should probably also check for the data being 'posted', as an extra precaution, but even that is fairly trivial to work around, so the sesskey is still needed; if you're also wanting to be very picky, in this case confirm should be md5('2'), but you get the idea ...).


Average of ratings: Useful (1)
In reply to Davo Smith

Re: security with login, capabilities and session key

by Johannes Burk -
Picture of Core developers Picture of Plugin developers

The sesskey is there to stop problems if a user posts a link like this in a forum:
> [URL of moodle site]/admin/user.php?delete=2&confirm=1

Ah ok, I don't thought about cross site request forgery. Thank you!


if you're also wanting to be very picky, in this case confirm should be md5('2')

Why does this make it more secure? Even if I take an information that is unknown to the attacker (courses/delete.php does this with md5($course->timemodified)) it is just a second secret. When the attacker is able to get know about the sesskey he would also be able to get the second secret. Or miss I something again?

Another thing I have just recognized is that sesskey != MoodleSession cookie value. Simple but significant (and not well documented).

In reply to Johannes Burk

Re: security with login, capabilities and session key

by Darko Miletić -

session key is not the moodle cookie and nobody said it was. It is just a unique value that should be used to protect form submits or ajax calls from forgery. No more, no less.

In reply to Johannes Burk

Re: security with login, capabilities and session key

by Johannes Burk -
Picture of Core developers Picture of Plugin developers

I think I've got it. The md5 hash prevents an admin itself from e.g. deleting a course unwanted by modifying the url (just changing the id but use the same confirm request will not work).