Note:

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

Hardening new Roles system: Difference between revisions

From MoodleDocs
No edit summary
m (Protected "Hardening new Roles system": Developer Docs Migration ([Edit=Allow only administrators] (indefinite)))
 
(30 intermediate revisions by 7 users not shown)
Line 1: Line 1:
New roles add great freedom when assigning rights to students. The problem might arise when students are assigned permission that allows adding of content that is not cleaned before display - such as editting Resources, adding activities, etc. They could then use any type of XSS attack to gain full administrative access without any restrictions.
{{Template:Migrated|newDocId=/docs/apis/subsystems/roles}}
Hardening a role, refers to limiting the ability of a role to assign or to aquire permissions.


==Proposed solution 1==
New roles add great freedom when assigning capabilities to students. The problem might arise when students are assigned permission that allows adding of content that is not cleaned before display - such as editting Resources, adding activities, etc. They could then use any type of XSS attack to gain full administrative access quite easily.
Assign trust level to each user and capability. Add trust level checks to has_capability() and require_capability().


===Implementation===
The solution has two parts: educate admins and teachers about the risks associated with each capability and optionally allow central management of risks.
* define basic trust levels (as integer constants)
** minimal - not logged-in, guests
** standard - students and non-editing teachers (must not be able to add HTML with javascript, can not upload files to coursefile area)
** high - teachers adding active content and handling sensitive information (backups, editing of activities and resources, uploading of course files, creating courses, etc.)
** absolute - usually administrators and trust level managers only
* add new column ''trustlevel'' to ''user'' table
* add new column ''requiredtrustlevel'' to table ''capabilities''
* fix role management GUI
** indicate required trust level next to each capability (different color and label or icon)
** allow filtering of capabilities based on trust level required
* add ''moodle/site:managetrustlevel'' with required absolute trust level
* add trust level management GUI
** predefined trust level for new users
** changing of trust level (also from user/edit page)
** request trust level change form (something like new course request)
* add trust level checks to has_capability() and require_capability() (veto when user does not have required trust level)
* assign levels based on legacy capabilities during upgrade
* do security audit of each capability in modules and core; set proper required levels (this is going to be the hardest part)


===Benefits===
==Risk bitmask in capabilities==
# Easy to implement, administer and explain to teachers compared to implementation based on capabilities.
Add risk bitmask field to each capability. Each bit indicates presence of different risk associated with given capability.
# Trust level manager has full control over potentially dangerous capabilities - it is necessary for large sites (or connected sites in the future).
# Trust level mechanism can be turned off by assigning high level to all users except admins - needed for small insecure ''workshop'' sites.
# Security audits could concentrate on standard and minimal capabilities.
# Module authors will be forced to think about security when defining capabilities.


== Proposed solution 1a ==
===Basic risks===
* '''RISK_SPAM''' - user can add visible content to site, send messages to other users; originally protected by !isguest()
* '''RISK_PERSONAL''' - access to private personal information - ex: backups with user details, non public information in profile (hidden email), etc.; originally protected by isteacher()
* '''RISK_XSS''' - user can submit content that is not cleaned (both HTML with active content and unprotected files); originally protected by isteacher()
* '''RISK_CONFIG''' - user can change global configuration, actions are missing sanity checks
* '''RISK_MANAGETRUST''' - manage trust bitmasks of other users
* '''RISK_DATALOSS''' - can destroy large amounts of information that cannot easily be recovered.


This proposal is pretty good, in that it is simple, and will work. I just worry that it is just tring to preseve the existing 7 roles:
In default configuration Guest role should have only capabilities without risks, Student roles also SPAM, Teacher roles PERSONAL and XSS too. Admins have all capabilitites by default.


;minimal
===Implementation===
:guest
* add new LONGINT column ''riskbitmask'' to table ''capabilities'' (DONE)
;standard
* define risks and assign them to capabilities in mod/xxx/db/access.php and lib/db/access.php (DONE)
:student, non-editing teacher
* link wiki pages with explanation to each risk from capabilities page
;high
* allow risk based filtering of capabilities admin/roles/manage.php (optional)
:editing teacher, course creator
;absolute
:admin, oringinal admin


Of course our current security model is build round these concepts, so changing it is a risk. Also, it is clearly not future proof to have 4 hard-coded levels.
The user interface will be minimal, icons and maybe colors indicating each risk together with description links which we need anyway.
Developers are deciding about the risks, the risk assignment is hardcoded in access.php description file, no GUI needed to change risks.


As I understand it: the new roles system is secure with the default settings, and it remains secure if the roles and permissions settings at a site are only editing by people who fully understand all the consequences of their actions. It is just the the new system is so powerful that it makes it too easy for people to screw up. Therefore, we need to protect them from themselves. Do I understand the problem correctly?
===Benefits===
# proper documentation of risks associated with capabilities, easy to explain
# solid foundation for regular code audits (mainly XSS prevention and personal information disclosure)


However, the new roles system is meant to make things more flexible, and at a large installation you might want to trust some people with some of the things you classify as high rist, but not others. For example, you might want to trust them to edit or upload uncleaned content, but not to handle backups nor create courses. Under your model, you would have to give these people high trust level, and then it would be possible give them capabilities that we would rather they did not have by mistake.
==User trust bitmask==
Indicate what kind of trust each user has. Match the risk bitmask of capability and user trust bitmask in both has_capability() and require_capability().


So can I suggest a slightly more flexible (and hence slightly more complicated solution). Instead of trust levels, have risks. For example:
===Implementation===
* Access to sensitive information
* add new LONGINT column ''trustbitmask'' to ''user'' table
* Add uncleaned content
* add capability ''moodle/site:managetrustbitmasks'' with RISK_MANAGETRUST risk
* Destroy the site
* add trust checks to has_capability() and require_capability()
Then for each user, list which risks you trust them not to exploit maliciously. For each cabability, list which risks it opens up.
* add GUI
** switch in global configuration to enable trust bitmask checking
** preseting of trust bitmask for new users
** changing of trust bitmasks
** add trust bitmask setting to user/edit.php
** request trust level change form - something like new course request (optional)
* fix upgrade to assign trust bitmaps based on original teacher or administrator rights
* patch user import script and synchronizations (optional)


All the checks you want to perform are still possible under my system. Explaining it is still easy, if not easier, because you can explain the possible consequences of trusting someone one risk at a time. Basically, instead of using integer trust levels and >= operator, we are using sets of risks and the superset operator. Very similar to implement, but much more flexible when we discover new classes of risk in the future.
===Benefits===
 
# This part is optional and can be implemented later.
 
# Trust manager or admin has full control over potentially dangerous capabilities - it is necessary for large sites (or connected sites in the future).  
== Proposed solution 1b ==
# Trust bitmask mechanism can be turned off by single configuration switch (both GUI and checks) - needed for small insecure workshop sites.
 
# General protection against future bugs in role and capability framework or user errors when configuring roles.
I like the idea of the risk system but I wonder if adding it right now will cause a new interface overload.  Assigning roles could also be a bit scary to think about.
 
As a first step, a simpler idea might be just be to add a column to the capabilities table called "risk" which defaults to "0" but could be set to higher numbers that are a mask (list of flags) with the kinds of risk this capability includes.
 
On the capability screens (eg role definition and override screens) any capabilities with a higher-than-zero entry could flags or colours or warnings next to it to help the user know that these capabilities had possible security or privacy issues that they should be aware of (linking off to the docs wiki for more details).
 
 
==Proposed solution 2 (independent of above)==
 
# Have one new capability called "moodle/site:trusttext".
# Certain roles who you trust to edit text and allow to have Javascript, EMBED etc can have permission for this capability set to "allow" (these people are generally teachers).
# When saving a text from a user, modules can call a function on the text and insert a special tag (eg ####TRUST#####) if the current user is trusted (and actively REMOVE all such tags if the user is NOT trusted).
# When displaying the text with format_text(), a new parameter needs to be passed to enable the trust system ($options->usetrust = true).
# If $options->usetrust is present, each text is checked for ####TRUST#### in the text and output is cleaned appropriately, depending on whether the tag was found.  If this new parameter is not present (eg in old modules or 3rd party modules) then all such tags are removed and the text is always fully cleaned.
# For caching, the text is stored in the final form as it is now.
 
===Example===
====Storing the text====
Here is the original text from the user:
  Elephant says <script>alert('hello')</script>
 
Here it's converted before storage:
  $text = apply_trust_to_text($text);
 
For a trusted user, this will return this text for storage:
  ####TRUST####Elephant says <script>alert('hello')</script>


For an untrusted user, this will return:
  Elephant says <script>alert('hello')</script>


====Showing the text====
''Note: trusttext moved to its own page at [[Trusttext cleaning bypass]]''
If the tag is found AND the code is trust-enabled then cleaning is NOT done, and only that special tag is removed before output.
  Elephant says <script>alert('hello')</script>


If not found then cleaning is done fully (as it is now in Moodle):
[[Category:Roles]]
  Elephant says

Latest revision as of 05:48, 17 June 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!

Hardening a role, refers to limiting the ability of a role to assign or to aquire permissions.

New roles add great freedom when assigning capabilities to students. The problem might arise when students are assigned permission that allows adding of content that is not cleaned before display - such as editting Resources, adding activities, etc. They could then use any type of XSS attack to gain full administrative access quite easily.

The solution has two parts: educate admins and teachers about the risks associated with each capability and optionally allow central management of risks.

Risk bitmask in capabilities

Add risk bitmask field to each capability. Each bit indicates presence of different risk associated with given capability.

Basic risks

  • RISK_SPAM - user can add visible content to site, send messages to other users; originally protected by !isguest()
  • RISK_PERSONAL - access to private personal information - ex: backups with user details, non public information in profile (hidden email), etc.; originally protected by isteacher()
  • RISK_XSS - user can submit content that is not cleaned (both HTML with active content and unprotected files); originally protected by isteacher()
  • RISK_CONFIG - user can change global configuration, actions are missing sanity checks
  • RISK_MANAGETRUST - manage trust bitmasks of other users
  • RISK_DATALOSS - can destroy large amounts of information that cannot easily be recovered.

In default configuration Guest role should have only capabilities without risks, Student roles also SPAM, Teacher roles PERSONAL and XSS too. Admins have all capabilitites by default.

Implementation

  • add new LONGINT column riskbitmask to table capabilities (DONE)
  • define risks and assign them to capabilities in mod/xxx/db/access.php and lib/db/access.php (DONE)
  • link wiki pages with explanation to each risk from capabilities page
  • allow risk based filtering of capabilities admin/roles/manage.php (optional)

The user interface will be minimal, icons and maybe colors indicating each risk together with description links which we need anyway. Developers are deciding about the risks, the risk assignment is hardcoded in access.php description file, no GUI needed to change risks.

Benefits

  1. proper documentation of risks associated with capabilities, easy to explain
  2. solid foundation for regular code audits (mainly XSS prevention and personal information disclosure)

User trust bitmask

Indicate what kind of trust each user has. Match the risk bitmask of capability and user trust bitmask in both has_capability() and require_capability().

Implementation

  • add new LONGINT column trustbitmask to user table
  • add capability moodle/site:managetrustbitmasks with RISK_MANAGETRUST risk
  • add trust checks to has_capability() and require_capability()
  • add GUI
    • switch in global configuration to enable trust bitmask checking
    • preseting of trust bitmask for new users
    • changing of trust bitmasks
    • add trust bitmask setting to user/edit.php
    • request trust level change form - something like new course request (optional)
  • fix upgrade to assign trust bitmaps based on original teacher or administrator rights
  • patch user import script and synchronizations (optional)

Benefits

  1. This part is optional and can be implemented later.
  2. Trust manager or admin has full control over potentially dangerous capabilities - it is necessary for large sites (or connected sites in the future).
  3. Trust bitmask mechanism can be turned off by single configuration switch (both GUI and checks) - needed for small insecure workshop sites.
  4. General protection against future bugs in role and capability framework or user errors when configuring roles.


Note: trusttext moved to its own page at Trusttext cleaning bypass