CVE-2025-49514

Server-Side Request Forgery
Affects
Moodle, IOMAD
in
Moodle
No items found.
Versions
<4.1.19, >=4.2.0 <4.4.9, >=4.5.0 <4.5.5, >=5.0.0 <5.0.1

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. 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 makes outgoing HTTP requests through its curl wrapper class in lib/filelib.php. Before each request, the wrapper checks the target against the cURL blocked hosts list and cURL allowed ports list settings, which by default block loopback, private network, and cloud metadata addresses.

A Server-Side Request Forgery (SSRF) vulnerability (CVE-2025-49514) has been identified in the outgoing request handling of Moodle and IOMAD, which allows an attacker who controls the DNS records of a domain to get past the cURL blocked hosts and allowed ports settings and make Moodle send requests to internal addresses. Moodle tracks this issue as MSA-25-0032 (MDL-83762).

Per OWASP: The target application may have functionality for importing data from a URL, publishing data to a URL or otherwise reading data from a URL that can be tampered with. The attacker modifies the calls to this functionality by supplying a completely different URL or by manipulating how URLs are built (path traversal etc.). When the manipulated request goes to the server, the server-side code picks up the manipulated URL and tries to read data to the manipulated URL.

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

Vulnerability Info

This High-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 Serious.

The curl class asks \core\files\curl_security_helper::url_is_blocked() whether a URL may be fetched. When the host is a domain name and the blocked hosts list contains IP rules, host_is_blocked() resolves the name with gethostbynamel() and checks each returned address against the list. The addresses it checked were then thrown away:

// If any of the returned IPs are in the blocklist, block the request.
foreach ($hostips as $hostip) {
    if ($this->address_explicitly_blocked($hostip)) {
        return true;
    }
}

After the check passed, curl::request() handed only the URL to cURL, and cURL did its own DNS lookup when it connected. The name was resolved twice, and nothing tied the second answer to the first. An attacker who controls a domain's DNS server can answer the first lookup with a public address that passes the check and the second with an address on the blocked list, such as 127.0.0.1 or the cloud metadata address 169.254.169.254. This is DNS rebinding, and it lets the request reach a host the site administrator meant to block.

Moodle fetches remote URLs in many places, and some of them take the URL from a user, so a user who can submit such a URL may be able to make the server send requests into its internal network or to a cloud metadata service. The result can be returned to the attacker or only observed indirectly, depending on the feature used. URLs that name an IP address directly were already checked correctly, because cURL does no lookup for them; the gap affects only URLs that use a domain name.

The fix makes the security helper remember the addresses and port that passed the check, and get_resolve_info() returns them in the host:port:address format that cURL's CURLOPT_RESOLVE option expects. curl::request() now passes that list to cURL through CURLOPT_RESOLVE, so cURL connects only to the addresses that were validated instead of looking the name up again:

// Force cURL to only resolve the URL from IP/port combinations that were validated by the security helper.
// This prevents re-fetching DNS data on subsequent requests, which could return un-validated hosts/ports.
$this->setopt(['CURLOPT_RESOLVE' => $this->curlresolveinfo]);

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.

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

  • Rekter0 (finder)
  • Holme (finder)
  • 0x123456789 (finder)
  • TaiYou (finder)
  • Vladislav Gladkiy of Positive Technologies (finder)
Vulnerability Details
Severity
Level
CVSS Assessment
Low
>=0 <4
Medium
>=4 <6
High
>=6 <8
Critical
>=8 <10
High
ID
CVE-2025-49514
PROJECT Affected
Moodle, IOMAD
Versions Affected
<4.1.19, >=4.2.0 <4.4.9, >=4.5.0 <4.5.5, >=5.0.0 <5.0.1
NES Versions Affected
Published date
October 14, 2026
≈ Fix date
October 1, 2026
Category
Server-Side Request Forgery
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.