Advisory: 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 - Product: Moodle - Affected Versions: 4.4 to 4.4.1, 4.3 to 4.3.5, 4.2 to 4.2.8, 4.1 to 4.1.11 and earlier unsupported versions - Fixed Versions: 4.1.12, 4.2.9, 4.3.6, 4.4.2 - Vulnerability Type: Remote Code Execution - Security Risk: high - Vendor URL: https://moodle.org/ - Vendor Status: fixed version released - Advisory URL: https://www.redteam-pentesting.de/advisories/rt-sa-2024-009 - Advisory Status: published - CVE: CVE-2024-43425 - CVE URL: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-43425 ### 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](https://docs.moodle.org/404/en/About_Moodle)) ### 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: ### Working at RedTeam Pentesting RedTeam Pentesting is looking for penetration testers to join our team in Aachen, Germany. If you are interested please visit: