CVE-2025-49516
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. 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. Moodle can send the badges that users earn to external backpacks, which are Open Badges services that collect a person's badges in one place. Administrators manage the list of site backpacks on the Manage backpacks page, and the backpack at the top of that list is the site's primary backpack.
A Cross-Site Request Forgery (CSRF) vulnerability (CVE-2025-49516) has been identified in the backpack management page of Moodle and IOMAD, which allows an attacker to change the order of the site's external backpacks by getting a logged-in administrator to open a crafted link. Moodle tracks this issue as MSA-25-0034 (MDL-84497).
Per OWASP: Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they're currently authenticated. With a little help of social engineering (such as sending a link via email or chat), an attacker may trick the users of a web application into executing actions of the attacker's choosing.
This issue affects all versions of Moodle before 4.1.19, versions 4.2.0 through 4.4.8, versions 4.5.0 through 4.5.4, and version 5.0.0, including End-of-Life release lines such as Moodle 4.3. IOMAD releases built on these Moodle versions contain the same code and are affected as well.
Details
Module Info
- Product: Moodle, IOMAD
- Affected packages:
moodle/moodle(badges/backpacks.php) - Affected versions: <4.1.19, >=4.2.0 <4.4.9, >=4.5.0 <4.5.5, >=5.0.0 <5.0.1
- GitHub repository: https://github.com/moodle/moodle (Moodle), https://github.com/iomad/iomad (IOMAD)
- Published packages: https://packagist.org/packages/moodle/moodle
- Package manager: Composer
- Fixed in:
- OSS Moodle 4.1.19, 4.4.9, 4.5.5, 5.0.1
- NES for Moodle v4.3.13
- NES for IOMAD v4.3.4
Vulnerability Info
This Low-severity vulnerability is found in the moodle/moodle package in all versions before 4.1.19, 4.2.0 through 4.4.8, 4.5.0 through 4.5.4, and 5.0.0 of Moodle, and in IOMAD releases built on those versions. Moodle rates it Minor.
Moodle protects state-changing requests with a per-session token, the sesskey, and checks it with require_sesskey() or confirm_sesskey(). badges/backpacks.php checked the token for deleting a backpack, but the moveup and movedown actions ran on the action and id URL parameters alone:
} else if ($action == 'moveup' || $action == 'movedown') {
// If no backpack has been selected, there isn't anything to move.
if (empty($id)) {
redirect($url);
}
$direction = BACKPACK_MOVE_DOWN;
if ($action == 'moveup') {
$direction = BACKPACK_MOVE_UP;
}
badges_change_sortorder_backpacks($id, $direction);
}The up and down arrows in the backpack list were plain links of the form backpacks.php?id=<id>&action=moveup, with no token. Because the request needed nothing the attacker could not guess, any page or message could send it on an administrator's behalf. badges_change_sortorder_backpacks() then swaps the backpack with its neighbour, and since badges_get_site_primary_backpack() returns the backpack with the lowest sort order, moving a backpack to the top changes which backpack Moodle treats as the site's primary backpack.
The page requires the moodle/badges:manageglobalsettings capability, which only the manager archetype has by default, and it redirects away unless external backpack connections are enabled. The victim must be logged in with that capability. The impact is limited to the order of configured backpacks: the request cannot add, edit, or delete a backpack, and it does not expose data.
The fix requires a valid session token before either move action runs, and adds the token to the up and down links in the external_backpacks_page template:
} else if (($action == 'moveup' || $action == 'movedown') && confirm_sesskey()) {
// If no backpack has been selected, there isn't anything to move.
if (empty($id)) {
redirect($url);
}{{#canmoveup}}
<a href="{{baseurl}}?id={{id}}&sesskey={{sesskey}}&action=moveup">{{#pix}}t/up, core,{{#str}}moveup{{/str}}{{/pix}}</a>
{{/canmoveup}}Mitigation
Moodle publishes security fixes only for its supported release lines. Earlier release lines, including Moodle 4.3 and the IOMAD releases built on it, are End-of-Life and will not receive any public updates to address this issue.
Until an upgrade is possible, sites that do not use external backpacks can turn off Enable connection to external backpacks (badges_allowexternalbackpack). The backpack management page then redirects before it handles any action.
Users of the affected components should apply one of the following mitigations:
- Upgrade to Moodle 4.1.19, 4.4.9, 4.5.5, 5.0.1, 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
- Vincent Schneider (finder)