alphaspirit - Fotolia

How did a Moodle security vulnerability enable remote code execution?

A series of logic flaws in Moodle enabled attackers to remotely execute code on servers. Expert Michael Cobb explains how the Moodle security vulnerability can be exploited.

A vulnerability found in Moodle, an open source, PHP-based learning management system used by tens of thousands of universities internationally, left servers and their data open to compromise. According to the researcher that discovered the issue, the Moodle security vulnerability is actually made up of several small flaws, and it can enable attackers to execute PHP code on related servers. What does this vulnerability entail, and what can be done about it?

Netanel Rubin, security researcher and CEO of Vaultra, found that by exploiting a series of minor vulnerabilities, he could chain them together to remotely execute code on a server running Moodle.

Moodle is an open source learning management system that stores a lot of sensitive information, like students' grades, tests and private data, making it an attractive target for hackers. The Moodle security vulnerability is tracked as CVE-2017-2641 and Moodle Tracker issue MDL-58010.

The attack works on almost all Moodle versions, so administrators should move to the latest version, version 3.2.2, to fix the problem as soon as possible. Besides updating to the latest version, administrators should also check for any new administrators, plug-ins or templates within Moodle, and search for any new files in the file system in case the server has been compromised.

The coding and logic flaws that contributed to this Moodle security vulnerability are a consequence of the size and complexity of the Moodle system; it contains thousands of files, hundreds of different components and around two million lines of PHP code, written and updated by various different developers at different times.

A new function, update_user_preferences, was added to Moodle to replace the update_users function. It implemented a privilege check, so even if an attacker could change settings using user preferences, it would only work on their own privileges.

While the new function removed the possibility of changing every user attribute, the code failed to check which preference was being changed. The previous function used the setuserpref.php file to check that the preference that needed to be updated was listed in the ajax_updatable_user_prefs array, which defines the preferences that can be changed via Ajax to ensure no critical values can be altered.

Ironically, in an attempt to reduce any potential abuse of the user attribute update function, the new privilege check actually introduced this Moodle security vulnerability. It's possible the developer thought that user preferences could not be exploited to mount a full-scale attack, as they only affect the graphical user interface part of the system.

However, the lack of containment enables an object injection attack to update any row in the entire database, such as administrator accounts, passwords and site configuration. Rubin discovered that this and other false assumptions made during code development could be leveraged to eventually execute PHP code on the server.

Logic flaws can and will occur in any system featuring a large code base, particularly when it's developed over a long period of time by a changing team of developers.

According to Steve McConnell, author of Code Complete, software projects that reach 512,000 lines of code or more can see four to 100 coding errors per thousand lines of code. A typical web application utilizes multiple languages, such as Java, HTML, PHP, Python, CSS, third-party libraries and components, and so on, and there are very few developers that know or understand how to use and integrate each of them without introducing any security vulnerabilities.

To reduce the chances of developers introducing logic flaws or omitting security and validation checks, it should be a requirement that they add a minimum level of in-code comments using an agreed-upon comment style, along with more verbose supporting documentation. Wikipedia has a comprehensive list of comment styles.

Although time spent on commenting and documenting code will slow down development, it will ensure developers making changes in the future can fully understand what a function does, how it does it and what checks are required on the data it handles. It is important that functions receiving data passed by other functions don't carry the assumption that the data has already been validated, as the previous function may have validated it against a different set of requirements or rules.

A good example is a telephone number. A function to retrieve and display a user's telephone number from a database may well accept + and () symbols, but if that function then passes the data to a function that actually calls the number, these characters could cause the function to fail if they are not removed before being processed.

Ask the expert:
Want to ask Michael Cobb a question about application security? Submit your questions now via email. (All questions are anonymous.)

Next Steps

Find out how a flaw in open source graphics library libpng enabled denial-of-service attacks

Learn why a remote code execution flaw in PHPMailer had to be repatched

Discover how thousands of MongoDB configurations were hijacked

Dig Deeper on Application and platform security

Enterprise Desktop
Cloud Computing