Skip to content

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

Open
Patryk Mroczko (patmr7) wants to merge 1 commit into
MOODLE_501_STABLEfrom
wip-135837-m501
Open

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

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

Adds CSRF protection to the local_o365 admin AJAX endpoint to prevent cross-site request forgery from triggering state-changing administrative actions (including those that could expand web service permissions).

Changes:

  • Enforces require_sesskey() for all requests handled by local/o365/ajax.php.
  • Updates the three admin setting UIs that call ajax.php to include sesskey in the generated 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/ajax.php Adds require_sesskey() gate for all AJAX modes to block CSRF.
local/o365/classes/adminsetting/moodlesetup.php Appends sesskey to the AJAX URL passed into the JS widget.
local/o365/classes/adminsetting/verifysetup.php Appends sesskey to the AJAX URL passed into the JS widget.
local/o365/classes/adminsetting/serviceresource.php Appends sesskey to the AJAX URL passed into the JS widget.

💡 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