Background information

This was originally reported as a private security issue, but has been approved for handling in the public queue by the Drupal Security Team.

Problem/Motivation

This check in ajax.js can be bypassed if the URL corresponds to an existing property of the ajaxTrustedUrl object (for example .constructor) :

if (drupalSettings.ajaxTrustedUrl[originalUrl]) {

In order to exploit this an attacker would need the following permissions:

  • Create redirects
  • Upload files (any extension would work)
  • Insert HTML with data attributes (or be able to set the URL of some existing AJAX call)

Steps to reproduce

1. Upload a .txt file containing containing this:

[{"command":"insert","method":"html","data":"<img src=x onerror=alert(0)>", "selector": "body"}]

2. Create a new redirect from /constructor to the URL of the uploaded file (for example with the redirect module).
3. Insert this HTML into a page:

<a class="use-ajax" href="constructor" data-ajax-http-method="GET">Click me</a>

4. When the link is clicked, the uploaded JSON is used as a trusted response and the JS is executed.

Proposed resolution

I suppose the easiest fix would be for core to add something like this:

drupalSettings.ajaxTrustedUrl.hasOwnProperty(originalUrl)

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

Issue fork drupal-3600777

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

prudloff created an issue. See original summary.

kieran.cott made their first commit to this issue’s fork.

kieran.cott’s picture

I've opened an MR for this issue here - https://git.drupalcode.org/project/drupal/-/merge_requests/16061. It's similar in function to https://git.drupalcode.org/project/drupal/-/merge_requests/16060, but instead resolves the issue by use of a helper method and adds test coverage by:

  1. Adding an ajax_test regression page with a use-ajax link to constructor.
  2. Adding an untrusted JSON response route that returns an AJAX insert command without the verification header.
  3. Adding a functional JavaScript regression test asserting the untrusted response is rejected and not processed.

I had already started working on this when MR 16060 was opened, so I've committed the work separately and will leave it to the maintainers/community to choose their preferred path forward.

prudloff’s picture

Maybe wait a bit before jumping on new issues with your LLM...
Anyway, I finished adding test coverage to my MR so now the two are very similar and we need to decide which one to keep.

kieran.cott’s picture

Happy to keep yours - closing MR.

prudloff’s picture

Status: Active » Needs review