Note: You are currently viewing documentation for Moodle 4.0. Up-to-date documentation for the latest stable version of Moodle may be available here: Security:Cross-site request forgery.

Development:Security:Cross-site request forgery

From MoodleDocs
Revision as of 17:47, 5 November 2009 by Tim Hunt (talk | contribs) (New page: This page forms part of the Moodle security guidelines. ==What is the danger?== When you put a web application on the internet, you are making it available so th...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

This page forms part of the Moodle security guidelines.

What is the danger?

When you put a web application on the internet, you are making it available so that anyone can send requests to it, and any request can be simply encoded as a URL.

Suppose that in Moodle, the way for an Administrator to delete a user was to click a Delete button in their user profile, and then click Yes on an confirmation page. Suppose that as a result of that, the Administrator's web browser sends a POST request to http://example.com/moodle/user/delete.php, with post data ?id=123&confirm=1.

Now suppose that Evil Hacker knows this, and wants to trick the administrator into deleting another user. (If Evil Hacker makes this request himself, he will see a permission denied error.)

All the Hacker Needs to do is to put the link http://example.com/moodle/user/delete.php?id=123&confirm=1 somewhere where the administrator will click on it. For example, they could send the Administrator an email with a link saying "Look at this cool YouTube video" but where the link actually goes to the delete URL. The Administrator may click on the link without checking where it goes, and when the Administrator clicks that link, user 123 really will be deleted.

Or, more seriously, the student could put a post in a forum that Administrators will read, and in the forum post, put an <img src="http://example.com/moodle/user/delete.php?id=123&confirm=1" />. That way, the moment the Administrator reads the forum, user 123 will be deleted.

How Moodle avoids this problem

Session key

The most important protection of the concept of a sesskey, short for session key.

When you log in, Moodle adds a random string to your session. Whever it prints a link or a button to perform a significant action, it adds the sesskey value to the submitted data. Before performing the action, it checks the sesskey value in the request with the one in the session, and the action is only performed if the two match.

Therefore, the request to delete a user is actually something like http://example.com/moodle/user/delete.php?id=123&confirm=1&sesskey=E8i5BCxLJR, and there is no way for Evil Hacker to know what the sesskey is, so they cannot construct an URL that tricks the admin into deleting a user.

Use HTTP correctly

Web applications use HTTP to encode requests from the user. In HTTP, there are various types of request. The two most important are GET and POST.

GET requests should be used for getting information. So, for example, viewing a user's profile should be a GET request.

POST requests should be used for changing things in the application. For example deleting a user should be a POST request.

When you click a link or load an image, it is always a GET request. When you submit a form, it is either a POST or a GET request, depending on the form.

Moodle should only process changes in response to a POST request. If that is the case, then it does Evil Hacker no good to trick a user into clicking on a link or viewing an embedded image. They have to trick a user into clicking a form submit button, which is harder.

What you need to do

  • Use a moodleform whenever possible for handling HTML forms. This automatically checks the sesskey and request method for you.
  • Where you cannot use a moodleform, check that this is a POST request with a valid sesskey before your code lets the user make any significant changes.
    • In Moodle 2.0, use the is_post_with_sesskey() function.
    • Before Moodle 2.0, user the data_submitted() function to test whether this is a post request, and either confirm_sesskey() or require_sesskey() to check the sesskey.
  • When outputting user-interface to trigger actions, use buttons instead of links
    • In Moodle 2.0 that means $OUTPUT->button() specifying ->method = 'post', and include sesskey in the params.
    • Before Moodle 2.0, use print_single_button(...) specifying $method = 'post', and including sesskey in $options.
  • If you want the action triggered by an icon, rather than a button, use an simple form with <input type="image">, rather than an <img ...> in a link.

See also

Template:CategoryDeveloper