Development:Security:Cross-site request forgery: Difference between revisions
Line 47: | Line 47: | ||
* Use a [[Development:lib/formslib.php|moodleform]] whenever possible for handling HTML forms. This automatically checks the sesskey and request method for you. | * Use a [[Development:lib/formslib.php|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 | * 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: | ||
<code php> | |||
$delete = optional_param('delete', null, PARAM_INT); | |||
if ($delete && confirm_sesskey() && data_submitted()) { | |||
$DB->delete_records(...); | |||
redirect(...); | |||
} | |||
</code> | |||
* When outputting user-interface to trigger actions, use buttons instead of links | * 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. | ** In Moodle 2.0 that means $OUTPUT->button() specifying ->method = 'post', and include sesskey in the params. |
Latest revision as of 15:33, 4 March 2011
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.
It is also possible to fake POST requests, you can simple put the form on external site and post a link pointing to that site on your Moodle server, it is also possible to use external flash instead of forms.
It may be a bit surprising, but this type of attack may be used against servers behind firewall on private network. It is not important where is the exploiting code, you can attack any server users may access from their browsers.
How Moodle avoids this problem
Session key
The most important protection is 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 in your code
Note, some of the Moodle 2.0 ideas mentioned here are still under discussion. That is what you get for writing coding guidelines at the same time as you are having design discussions.--Tim Hunt 10:48, 23 November 2009 (UTC)
- 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:
$delete = optional_param('delete', null, PARAM_INT);
if ($delete && confirm_sesskey() && data_submitted()) {
$DB->delete_records(...);
redirect(...);
}
- 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.
What you need to do as an administrator
- This is really only a code issue, but try not to fall for Evil Hacker's tricks ;-).