CVE-2026-26045

Remote Code Execution
Affects
Moodle, IOMAD
in
Moodle
No items found.
Versions
<4.5.9, >=5.0.0 <5.0.5, >=5.1.0 <5.1.2

Patch Available.

Exclamation circle icon
Patch Available

This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.

Overview

Moodle is an open source learning management system written in PHP. Schools, universities, and companies use it to run online courses, and it can export a course, including its uploaded files, as a backup file that can be restored into the same site or a different one. IOMAD is a multi-tenant distribution of Moodle that lets one installation serve several companies or organizations; it is built on Moodle core and shares the affected code.

A Remote Code Execution (RCE) vulnerability (CVE-2026-26045) has been identified in the file restore handling of Moodle and IOMAD, which allows an authenticated user who can restore course content to plant serialized PHP objects in file records and have Moodle instantiate them, potentially leading to code execution on the server. Moodle tracks this issue as MSA-26-0001 (MDL-87612).

Per OWASP: Data which is untrusted cannot be trusted to be well formed. Malformed data or unexpected data could be used to abuse application logic, deny service, or execute arbitrary code, when deserialized.

This issue affects all versions of Moodle before 4.5.9, versions 5.0.0 through 5.0.4, and versions 5.1.0 through 5.1.1, including End-of-Life release lines such as Moodle 4.3 and 4.4. IOMAD releases built on these Moodle versions contain the same code and are affected as well.

Details

Module Info

Vulnerability Info

This High-severity vulnerability is found in the moodle/moodle package in all versions before 4.5.9, 5.0.0 through 5.0.4, and 5.1.0 through 5.1.1 of Moodle, and in IOMAD releases built on those versions.

Every stored file in Moodle has a source field. For files that came from a repository, Moodle stores a PHP-serialized stdClass there, and its original property records where a referenced file came from. Course backups carry each file's source value, and the restore process writes it back into the file record on the target site, so whoever builds the backup controls that string.

The draft-file helpers in repository/lib.php read the value back with PHP's native unserialize() and no class restriction. repository::overwrite_existing_draftfile() does it twice, and repository::update_draftfile() does it when a file is renamed or a folder is moved:

// repository::overwrite_existing_draftfile()
// Remember original file source field.
$source = @unserialize($file->get_source());
...
if (isset($source->original)) {
    if (!($newfilesource = @unserialize($newfile->get_source()))) {
        $newfilesource = new stdClass();
    }
    $newfilesource->original = $source->original;
    $newfile->set_source(serialize($newfilesource));
}

// repository::update_draftfile()
if (($filesource = @unserialize($file->get_source())) && isset($filesource->original)) {
    unset($filesource->original);
    $file->set_source(serialize($filesource));
}

Because unserialize() is called without an allowed_classes option, any class named in the string is instantiated, and that class's magic methods such as __wakeup() and __destruct() run when the object is created and discarded. The @ operator also hides any warning a malformed payload would produce. The legacy course files repository has the same pattern: repository_coursefiles::get_link() passes a base64-decoded parameter straight to unserialize().

A user who can restore content can build a backup whose file records carry a serialized object of an arbitrary class instead of a plain stdClass. When those restored files are later handled by the draft-file code, for example when a file is renamed, moved, or overwritten in the file picker, Moodle instantiates the attacker's object. Combined with a suitable gadget chain from classes available in Moodle core, its plugins, or its bundled libraries, this PHP object injection can lead to arbitrary code execution as the web server user and full compromise of the Moodle site.

Exploitation requires an authenticated account that can restore content. The moodle/restore:restorecourse and moodle/restore:restoreactivity capabilities are granted by default to the Manager and Teacher roles in their courses, so on a typical site any teacher can reach this code. A backup file from an untrusted source restored by an administrator can carry the same payload.

The fix replaces each of these calls with Moodle's safe helpers. unserialize_object() only allows stdClass and converts any other class into a plain stdClass, and unserialize_array() rejects any input that is not a serialized array of scalar values:

// repository::overwrite_existing_draftfile()
$source = unserialize_object($file->get_source());
...
if (isset($source->original)) {
    $newfilesource = unserialize_object($newfile->get_source());
    $newfilesource->original = $source->original;
    $newfile->set_source(serialize($newfilesource));
}

// repository_coursefiles::get_link()
$params = (array) unserialize_array(base64_decode($encoded));

This advisory follows CVE-2025-67847 (MSA-25-0051), which applied the same change to lib/filelib.php and repository/draftfiles_ajax.php. This fix covers the remaining call sites in the repository API.

Mitigation

Moodle publishes security fixes only for its supported release lines (4.5, 5.0, and 5.1 at the time of this advisory). Earlier release lines, including Moodle 4.3 and 4.4 and the IOMAD releases built on them, are End-of-Life and will not receive any public updates to address this issue.

Until an upgrade is possible, restrict the moodle/restore:restorecourse, moodle/restore:restoresection, and moodle/restore:restoreactivity capabilities to trusted roles, and do not restore backup files from untrusted sources.

Users of the affected components should apply one of the following mitigations:

  • Upgrade to Moodle 4.5.9, 5.0.5, 5.1.2, or later, or to an IOMAD release built on one of those versions.
  • Leverage a commercial support partner like HeroDevs for post-EOL security support.

Credits

  • Dinhnhi from VNPT-VCI (finder)
Vulnerability Details
Severity
Level
CVSS Assessment
Low
>=0 <4
Medium
>=4 <6
High
>=6 <8
Critical
>=8 <10
High
ID
CVE-2026-26045
PROJECT Affected
Moodle, IOMAD
Versions Affected
<4.5.9, >=5.0.0 <5.0.5, >=5.1.0 <5.1.2
NES Versions Affected
Published date
October 14, 2026
≈ Fix date
October 1, 2026
Category
Remote Code Execution
Vex Document
Download VEXHow do I use it?
Sign up for the latest vulnerability alerts fixed in
NES for Moodle
Rss feed icon
Subscribe via RSS
or

By submitting the form I acknowledge receipt of our Privacy Policy.

Thanks for signing up for our Newsletter! We look forward to connecting with you.
Oops! Something went wrong while submitting the form.