Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Security: Difference between revisions

From MoodleDocs
(New page: This page describes how security best practices for Moodle developers, and how to use the Moodle API to achieve the best security for your scripts. ==General== # Always try to structure ...)
 
m (Update migration status and path)
 
(33 intermediate revisions by 14 users not shown)
Line 1: Line 1:
This page describes how security best practices for Moodle developers, and how to use the Moodle API to achieve the best security for your scripts.
{{Template:Migrated|newDocId=/general/development/policies/security}}
This page describes how to write secure Moodle code that is not vulnerable to anything that evil people may try to throw at it.


==General==
The page is organised around the common types of security vulnerability. For each one, it explains
# what the danger is,
# how Moodle is designed to avoid the problem,
# what you need to do as a Moodle developer to keep your code secure, and
# what you can do as an administrator, to make your Moodle more secure.
The explanation of each vulnerability is on a separate page, linked to in the list below.


# Always try to structure your code in classes and functions without using globals ... this will promote better checking and tracing of variables.
This page also summarises all the key guidelines.


==Security of web applications==


==Authentication==
===Secure web app requirements===
Some companies require maximum level of security for web applications. You can often see similar general recommendations:
* separate administration backend
* no sensitive information stored in web application
* communication has to be encrypted using SSL
* log all user actions
* server applications have to be completely separated
* no files uploaded by users on server
* no rich text entered by users on server (limited plain text only)
* validate user identity and actions via separate channel
* always keep every software up-to-date
* no 3rd party browser extensions recommended
* use only one web page, do not open multiple windows with different sites, close/open browser before and after using the secure app


# Each file should check that the user is authenticated correctly, using '''require_login()''' and '''has_capability()''' or '''require_capability()'''.
Web based banking systems are the best examples of these ''secure'' web applications. Security is the top most priority here, security incidents may cost money - either the customer, bank or insurance company, public image of the institution may be damaged too. Limiting factors may be cost of application development, maintenance, usability but also the cost of communication via the alternative channels.


==Handling input==
===Balanced security===
As you can see many web applications today violate the security design rules. For example web based mail system have to accept rich text messages with file attachments, mail massages often contain very sensitive information. In fact the Web 2.0 idea goes directly agains the security design rules, everybody is submitting content - only app designer/administrator should be adding trusted content.


# Do not rely on 'register_globals'. Every variable must be properly initialised in every code file. It must be obvious where the variable came from.
When designing web applications we have to find out what our users are supposed to be doing and then find some reasonable balance between features and security.
# Do not ever use $_GET, $_POST or $_REQUEST. Use the appropriate required_param() or optional_param() appropriate to your need.
# Do not use data from $_SERVER if you can avoid it. This has portability issues.  Instead, use Moodle functions to get what you want.
# Wherever possible group all your required_param(), optional_param() and other variables initialisation at the beginning of each file to make them easy to find.
# Initialise all arrays and objects, even if empty. $a = array() or $obj = new stdClass();.
# Use 'sesskey' mechanism to protect form handling routines from attack. Basic example of use: when form is generated, include <input type="hidden" name="sesskey" value="<?php echo sesskey(); ?>" />. When you process the form check with if (!confirm_sesskey()) { print_error('confirmsesskeybad');}.
# If you presenting a normal form and processing it, always use the [[lib/formslib.php|moodleforms library]] - it will take care of most details for you.
==Storing data==


# Try to always use the XMLDB library in Moodle for all database access.  Not only does this provide security but it ensures correct behaviour on different databases.
==Moodle security design==
# If you must write custom some SQL code, make very sure it is correct. In particular watch out for missing quotes around values to avoid possible SQL 'injection' exploits.
The security of web application depends on the intended use and features available for each type of user.
# Before Moodle 2.0, any data sourced from the database MUST have [[Developer:Slashes|addslashes()]] applied to it BEFORE it can be written back. A whole object of data can be processed at once with addslashes_object().
# In Moodle 2.0 and later the database layer has changed and you MUST NOT use addslashes() anywhere as this is now automated.  


==Output==
===Types of users===


#'''All texts should be printed using the format_text() function''', especially those that have come from users. This ensures that text is filtered and cleaned correctly. More information can be found on the page about [[Output_functions|output functions]].
====Administrators====
Administrators have following privileges:
* change all settings
* create courses
* access all courses
* modify language packs
* modify all users


==Logging==
Indirectly administrators are allowed to execute shell and PHP code. Moodle administrators may be partially restricted by hardcoding settings in config.php.
Low level server administrators can not be restricted because they can read content of PHP files and may modify them.


# User actions should be logged using the [[Logs|add_to_log()]] function. These logs are used for [[Settings#Show_activity_reports|activity reports]] and [[Logs]].
All administrators have to be fully trusted.


==Shell commands==
====Teachers====
# Avoid them!  However, if you must use shell_exec() (or any other shell invoking function), make sure you clean parameters first with escapeshellcmd()/escapeshellarg (to prevent shell injection attacks).
Teachers are usually creating course content, enrolling students and teaching. They usually need following privileges:
* upload files and submit html texts
* create and manage activities
* access student grades and other personal information


==Error handling==
Uploading of files with javascript, flash and other scripted is often considered to be a security risk. Unfortunately we can not remove these risks from teacher roles because even basic SCORM packages consist of html and javascript which needs to use user session.
 
Browser trusts everything coming from one server, it does not know anything about our courses or origin of data. Once the file is uploaded to server it becomes part of the server application. It is not possible to differentiate between wanted and unwanted code stored on the server.
 
All teachers with risky capabilities have to be trusted, it is not possible to give teacher access to students. In theory teachers may use XSS attacks to gain administrator access.
 
Technically it would be possible to create system where teachers can not attack other users but it would prevent all javascript, flash, SCORM, java, html forms, SVG, etc.
 
====Students====
Students are participating in courses, they are not trusted. Students need following privileges:
* post formatted text with inline images and attachments
* upload binary documents
 
Uploaded files must not be opened directly in browser from the same server. Instead the files need to be served from different domain, or server has to force download of all files to local hard drive before opening them.
 
All student submitted text has to be sanitised before printing the text on any page, this prevent XSS attacks on other users but at the same time prevents flash, javascript, SVG and all other HTML scripting. Moodle uses HTML Purifier library for this purpose.
 
====Guests====
For security reasons unregistered users can not be allowed to upload any files or submit any text that is stored in database. Guests could try to spam other users, exploit problems in html cleaning routines, abuse other vulnerabilities or try social engineering based attacks.
 
Sites with enabled user sign-up  via email have to take extra care in order to prevent spamming and other types of attacks.
 
===Capability risks===
 
Moodle is very flexible system, administrators may define multiple roles. Each role is a set of capabilities defined at system level, roles may be modified via overrides at lower context levels. [[Risks]] are part of description of each capability, administrators have to make sure only trusted users get potentially dangerous capabilities.
 
==Common types of security vulnerability==
 
* [[Security:Unauthenticated access|Unauthenticated access]]
* [[Security:Unauthorised access|Unauthorised access]]
* [[Security:Cross-site_request_forgery|Cross-site request forgery]] (XSRF)
* [[Security:Cross-site scripting|Cross-site scripting]] (XSS)
* [[Security:SQL injection|SQL injection]]
* [[Security:Command-line injection|Command-line injection]]
* [[Security:Data-loss|Data-loss]]
* [[Security:Confidential information leakage|Confidential information leakage]]
* [[Security:Configuration information leakage|Configuration information leakage]]
* [[Security:Session fixation|Session fixation]]
* [[Security:Denial of service|Denial of service]]
* [[Security:Brute-forcing login|Brute-forcing login]]
* [[Security:Insecure configuration management|Insecure configuration management]]
* [[Security:Buffer overruns, and other platform weaknesses|Buffer overruns, and other platform weaknesses]]
* [[Security:Social engineering|Social engineering]]
 
==Summary of the guidelines==
 
===Authenticate the user===
 
* With very few exceptions, every script should call '''[[Access_API#require_login.28.29|require_login]]''' or '''[[Access_API#require_course_login.28.29|require_course_login]]''' as near the start as possible.
 
===Verify course and module access===
* all course areas have to be protected by "require_login" or "require_course_login" with correct $course parameter
* all module areas have to be protected by "require_login" or "require_course_login" with correct $course and $cm parameter
 
===Check permissions===
 
* Before allowing the user to see anything or do anything, call to '''[[Access_API#has_capability.28.29|has_capability]]''' or '''[[Access_API#require_capability.28.29|require_capability]]'''.
* Capabilities should be annotated with the appropriate '''[[Hardening_new_Roles_system#Basic_risks|risks]]'''.
* If appropriate, restrict what people can see according to '''groups'''.
 
===Don't trust any input from users===
 
* Use '''[[lib/formslib.php|moodleforms]]''' whenever possible, with an appropriate '''setType''' method call for each field.
* Before performing actions, use '''data_submitted() && confirm_sesskey()''' to check sesskey and that you are handling a POST request.
* Before destroying large amounts of data, add a confirmation step.
* If not using a moodleform, clean input using '''optional_param''' or '''required_param''' with an appropriate '''PARAM_...''' type.
** Do not access $_GET, $_POST or $_REQUEST directly.
** Group optional_param and required_param calls together at the top of the script, to make them easy to find.
 
Similarly, clean data from other external resources like RSS feeds before use.
 
===Clean and escape data before output===
 
* Use '''s''' or '''p''' to output plain text content.
* use '''format_string''' to output content with minimal HTML like multi-lang spans (for example, course and activity names).
* Use '''format_text''' to output all other content.
** Only use $options->noclean if it requires a capability with RISK_XSS to input that content (for example web page resources).
* Before Moodle 2.0, input from optional_param or required_param must have [[Developer:Slashes|'''stripslashes''' or '''stripslashes_recursive''']] applied if it is being output directly, rather than being stored in the database.
* Data destined for JavaScript should be escaped using '''$PAGE->requires->data_for_js''' (Moodle 2.0) or '''addslashes_js''' (Moodle 1.9).
 
See [[Output functions]] for more details.
 
===Escape data before storing it in the database===
 
* Use the XMLDB library. This takes care of most escaping issues for you.
* When you must use custom SQL code, '''use place-holders''' to insert values into the queries.
** Before Moodle 2.0, you have to build SQL by concatenating strings. Take particular care, especially with quoting values, to avoid SQL injection vulnerabilities.
* Before Moodle 2.0, data loaded from the database must have [[Developer:Slashes|'''addslashes''' or '''addslashes_object''']] applied to it before it can be written back to the database. (addslashes should no longer be use anywhere in Moodle 2.0 code.)
* In Moodle 2.0 variables must be passed to database queries through bound parameters
 
===Escape data before using it in shell commands===
 
* Avoid shell commands if at all possible.
** Look to see if there is a PHP library instead.
* If you can't avoid shell commands, use '''escapeshellcmd''' and '''escapeshellarg'''.
 
 
===Log every request===
 
* Every script should call '''add_to_log'''.
 
 
===Other good practice===
 
... that helps with security.
 
* Structure your code nicely, minimising the use of global variables. This makes the flow of data, and hence security, easier to verify.
* Initialise objects ($x = new stdClass;) and arrays ($x = array()) before you first use them.
* Test every input field with tricky input to ensure that it is escaped and un-escaped the right number of times everywhere, and that Unicode characters are not corrupted. My standard test input is:
<nowiki>< > & &amp;lt; &amp;gt; &amp;amp; ' \' 碁 \ \\</nowiki>
 
==See also==
 
* [[Process#Security_issues|Security issue process]]
* [[Coding]]
* The [http://cwe.mitre.org/top25/ 2010 CWE/SANS Top 25 Most Dangerous Programming Errors] - this is a generic list of common security mistakes, produced by a group of security experts. The above Moodle-specific guidelines cover most of these general points.
* [https://www.owasp.org/index.php/PHP_Security_Cheat_Sheet PHP Security Cheat Sheet]
* [https://www.owasp.org/index.php/Main_Page The Open Web Application Security Project (OWASP)] - Large collection of documentation and code samples about preventing security issues while using web technologies.
 
[[Category:Security]]
[[Category:Coding guidelines|Security]]

Latest revision as of 13:20, 31 May 2022

Important:

This content of this page has been updated and migrated to the new Moodle Developer Resources. The information contained on the page should no longer be seen up-to-date.

Why not view this page on the new site and help us to migrate more content to the new site!

This page describes how to write secure Moodle code that is not vulnerable to anything that evil people may try to throw at it.

The page is organised around the common types of security vulnerability. For each one, it explains

  1. what the danger is,
  2. how Moodle is designed to avoid the problem,
  3. what you need to do as a Moodle developer to keep your code secure, and
  4. what you can do as an administrator, to make your Moodle more secure.

The explanation of each vulnerability is on a separate page, linked to in the list below.

This page also summarises all the key guidelines.

Security of web applications

Secure web app requirements

Some companies require maximum level of security for web applications. You can often see similar general recommendations:

  • separate administration backend
  • no sensitive information stored in web application
  • communication has to be encrypted using SSL
  • log all user actions
  • server applications have to be completely separated
  • no files uploaded by users on server
  • no rich text entered by users on server (limited plain text only)
  • validate user identity and actions via separate channel
  • always keep every software up-to-date
  • no 3rd party browser extensions recommended
  • use only one web page, do not open multiple windows with different sites, close/open browser before and after using the secure app

Web based banking systems are the best examples of these secure web applications. Security is the top most priority here, security incidents may cost money - either the customer, bank or insurance company, public image of the institution may be damaged too. Limiting factors may be cost of application development, maintenance, usability but also the cost of communication via the alternative channels.

Balanced security

As you can see many web applications today violate the security design rules. For example web based mail system have to accept rich text messages with file attachments, mail massages often contain very sensitive information. In fact the Web 2.0 idea goes directly agains the security design rules, everybody is submitting content - only app designer/administrator should be adding trusted content.

When designing web applications we have to find out what our users are supposed to be doing and then find some reasonable balance between features and security.

Moodle security design

The security of web application depends on the intended use and features available for each type of user.

Types of users

Administrators

Administrators have following privileges:

  • change all settings
  • create courses
  • access all courses
  • modify language packs
  • modify all users

Indirectly administrators are allowed to execute shell and PHP code. Moodle administrators may be partially restricted by hardcoding settings in config.php. Low level server administrators can not be restricted because they can read content of PHP files and may modify them.

All administrators have to be fully trusted.

Teachers

Teachers are usually creating course content, enrolling students and teaching. They usually need following privileges:

  • upload files and submit html texts
  • create and manage activities
  • access student grades and other personal information

Uploading of files with javascript, flash and other scripted is often considered to be a security risk. Unfortunately we can not remove these risks from teacher roles because even basic SCORM packages consist of html and javascript which needs to use user session.

Browser trusts everything coming from one server, it does not know anything about our courses or origin of data. Once the file is uploaded to server it becomes part of the server application. It is not possible to differentiate between wanted and unwanted code stored on the server.

All teachers with risky capabilities have to be trusted, it is not possible to give teacher access to students. In theory teachers may use XSS attacks to gain administrator access.

Technically it would be possible to create system where teachers can not attack other users but it would prevent all javascript, flash, SCORM, java, html forms, SVG, etc.

Students

Students are participating in courses, they are not trusted. Students need following privileges:

  • post formatted text with inline images and attachments
  • upload binary documents

Uploaded files must not be opened directly in browser from the same server. Instead the files need to be served from different domain, or server has to force download of all files to local hard drive before opening them.

All student submitted text has to be sanitised before printing the text on any page, this prevent XSS attacks on other users but at the same time prevents flash, javascript, SVG and all other HTML scripting. Moodle uses HTML Purifier library for this purpose.

Guests

For security reasons unregistered users can not be allowed to upload any files or submit any text that is stored in database. Guests could try to spam other users, exploit problems in html cleaning routines, abuse other vulnerabilities or try social engineering based attacks.

Sites with enabled user sign-up via email have to take extra care in order to prevent spamming and other types of attacks.

Capability risks

Moodle is very flexible system, administrators may define multiple roles. Each role is a set of capabilities defined at system level, roles may be modified via overrides at lower context levels. Risks are part of description of each capability, administrators have to make sure only trusted users get potentially dangerous capabilities.

Common types of security vulnerability

Summary of the guidelines

Authenticate the user

Verify course and module access

  • all course areas have to be protected by "require_login" or "require_course_login" with correct $course parameter
  • all module areas have to be protected by "require_login" or "require_course_login" with correct $course and $cm parameter

Check permissions

  • Before allowing the user to see anything or do anything, call to has_capability or require_capability.
  • Capabilities should be annotated with the appropriate risks.
  • If appropriate, restrict what people can see according to groups.

Don't trust any input from users

  • Use moodleforms whenever possible, with an appropriate setType method call for each field.
  • Before performing actions, use data_submitted() && confirm_sesskey() to check sesskey and that you are handling a POST request.
  • Before destroying large amounts of data, add a confirmation step.
  • If not using a moodleform, clean input using optional_param or required_param with an appropriate PARAM_... type.
    • Do not access $_GET, $_POST or $_REQUEST directly.
    • Group optional_param and required_param calls together at the top of the script, to make them easy to find.

Similarly, clean data from other external resources like RSS feeds before use.

Clean and escape data before output

  • Use s or p to output plain text content.
  • use format_string to output content with minimal HTML like multi-lang spans (for example, course and activity names).
  • Use format_text to output all other content.
    • Only use $options->noclean if it requires a capability with RISK_XSS to input that content (for example web page resources).
  • Before Moodle 2.0, input from optional_param or required_param must have stripslashes or stripslashes_recursive applied if it is being output directly, rather than being stored in the database.
  • Data destined for JavaScript should be escaped using $PAGE->requires->data_for_js (Moodle 2.0) or addslashes_js (Moodle 1.9).

See Output functions for more details.

Escape data before storing it in the database

  • Use the XMLDB library. This takes care of most escaping issues for you.
  • When you must use custom SQL code, use place-holders to insert values into the queries.
    • Before Moodle 2.0, you have to build SQL by concatenating strings. Take particular care, especially with quoting values, to avoid SQL injection vulnerabilities.
  • Before Moodle 2.0, data loaded from the database must have addslashes or addslashes_object applied to it before it can be written back to the database. (addslashes should no longer be use anywhere in Moodle 2.0 code.)
  • In Moodle 2.0 variables must be passed to database queries through bound parameters

Escape data before using it in shell commands

  • Avoid shell commands if at all possible.
    • Look to see if there is a PHP library instead.
  • If you can't avoid shell commands, use escapeshellcmd and escapeshellarg.


Log every request

  • Every script should call add_to_log.


Other good practice

... that helps with security.

  • Structure your code nicely, minimising the use of global variables. This makes the flow of data, and hence security, easier to verify.
  • Initialise objects ($x = new stdClass;) and arrays ($x = array()) before you first use them.
  • Test every input field with tricky input to ensure that it is escaped and un-escaped the right number of times everywhere, and that Unicode characters are not corrupted. My standard test input is:
< > & &lt; &gt; &amp; ' \' 碁 \ \\

See also