Skip to content

Fix CSRF in ajax.php enabling privilege escalation by requiring sessk… - #3389

Open
Patryk Mroczko (patmr7) wants to merge 1 commit into
MOODLE_500_STABLEfrom
wip-135837-m500
Open

Fix CSRF in ajax.php enabling privilege escalation by requiring sessk…#3389
Patryk Mroczko (patmr7) wants to merge 1 commit into
MOODLE_500_STABLEfrom
wip-135837-m500

Conversation

@patmr7

Copy link
Copy Markdown
Collaborator

…ey validation

local/o365/ajax.php required only require_login() and moodle/site:config, with no sesskey check on any of its state-changing modes. mode_checkteamsmoodlesetup in particular enables web services, the REST protocol, frame embedding, the bundled o365_webservices external service, and grants moodle/webservice:createtoken and webservice/rest:use to the default authenticated-user role - all unconditionally, on a simple GET request. A forged cross-site request against a logged-in administrator (e.g. via an tag) silently expands these permissions to every authenticated user, regardless of whether the site uses Teams SSO at all.

Add require_sesskey() to ajax.php, and append sesskey to the ajax.php URL built by the three admin_setting classes that call it (moodlesetup, verifysetup, serviceresource). These build their AJAX calls with plain jQuery rather than a sesskey-aware core JS module, so the sesskey is carried in the URL's query string instead, where jQuery's GET request serialization appends the remaining parameters.

…ey validation

local/o365/ajax.php required only require_login() and moodle/site:config, with no
sesskey check on any of its state-changing modes. mode_checkteamsmoodlesetup in
particular enables web services, the REST protocol, frame embedding, the bundled
o365_webservices external service, and grants moodle/webservice:createtoken and
webservice/rest:use to the default authenticated-user role - all unconditionally,
on a simple GET request. A forged cross-site request against a logged-in
administrator (e.g. via an <img> tag) silently expands these permissions to every
authenticated user, regardless of whether the site uses Teams SSO at all.

Add require_sesskey() to ajax.php, and append sesskey to the ajax.php URL built by
the three admin_setting classes that call it (moodlesetup, verifysetup,
serviceresource). These build their AJAX calls with plain jQuery rather than a
sesskey-aware core JS module, so the sesskey is carried in the URL's query string
instead, where jQuery's GET request serialization appends the remaining
parameters.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR closes a CSRF vulnerability in local/o365/ajax.php by requiring Moodle sesskey validation for all AJAX modes, preventing state-changing requests from being triggered cross-site against a logged-in administrator.

Changes:

  • Enforce require_sesskey() in local/o365/ajax.php before executing the requested mode.
  • Update the three admin setting UIs that call ajax.php to include sesskey in the constructed AJAX URL query string.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
local/o365/classes/adminsetting/verifysetup.php Adds sesskey to the AJAX endpoint URL used by the verify-setup UI.
local/o365/classes/adminsetting/serviceresource.php Adds sesskey to the AJAX endpoint URL used by the service-resource UI.
local/o365/classes/adminsetting/moodlesetup.php Adds sesskey to the AJAX endpoint URL used by the Moodle-setup UI.
local/o365/ajax.php Requires sesskey validation for all AJAX modes to prevent CSRF-triggered state changes.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants