CVE-2023-50723: Improper Control of Generation of Code ('Code Injection') (CWE-94)
value: XWiki Platform is a generic wiki platform. Starting in 2.3 and prior to versions 14.10.15, 15.5.2, and 15.7-rc-1, anyone who can edit an arbitrary wiki page in an XWiki installation can gain programming right through several cases of missing escaping in the code for displaying sections in the administration interface. This impacts the confidentiality, integrity and availability of the whole XWiki installation. Normally, all users are allowed to edit their own user profile so this should be exploitable by all users of the XWiki instance. This has been fixed in XWiki 14.10.15, 15.5.2 and 15.7RC1. The patches can be manually applied to the `XWiki.ConfigurableClassMacros` and `XWiki.ConfigurableClass` pages.
CWE description: The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.
CVSS v3 base score: 8.8
Published: 2023-12-15T19:15Z
Repository: https://github.com/xwiki/xwiki-platform
Language: XML
Files changed: xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-ui/src/main/resources/XWiki/ConfigurableClass.xml, xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-ui/src/test/java/org/xwiki/administration/ConfigurableClassPageTest.java
Commit date: 2023-08-02 15:36:27 +0200
Commit message: XWIKI-21122: Improve escaping of configuration section headings

* Also improve escaping of the document reference in other places.

Diff: diff --git a/xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-ui/src/main/resources/XWiki/ConfigurableClass.xml b/xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-ui/src/main/resources/XWiki/ConfigurableClass.xml
index c87781046bbaf..83d02641e8456 100644
--- a/xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-ui/src/main/resources/XWiki/ConfigurableClass.xml
+++ b/xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-ui/src/main/resources/XWiki/ConfigurableClass.xml
@@ -159,10 +159,13 @@
           &lt;noscript&gt;
 
             {{warning}}{{translation key="xe.admin.configurable.cannotLockNoJavascript"/}}{{/warning}}
 
           &lt;/noscript&gt;
+        {{/html}}
+
+        {{html clean=false}}
           &lt;script&gt;
             document.observe("xwiki:dom:loaded", function() {
               XWiki.DocumentLock &amp;&amp; new XWiki.DocumentLock('$escapetool.javascript($app.prefixedFullName)').lock();
             });
           &lt;/script&gt;
@@ -444,12 +447,12 @@
   #end
   {{/html}}
 
   ## Finally we display an error message if there are any applications which we were unable to view.
   #if($appsUserCannotView.size() &gt; 0)
-
-    {{error}}$services.localization.render('xe.admin.configurable.noViewAccessSomeApplications', [$appsUserCannotView]){{/error}}
+    {{error}}$services.localization.render('xe.admin.configurable.noViewAccessSomeApplications',
+      'xwiki/2.1', [$appsUserCannotView]){{/error}}
 
   #end
 #end## If we should be looking at the main administration page.
 {{/velocity}}</content>
   <attachment>
diff --git a/xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-ui/src/test/java/org/xwiki/administration/ConfigurableClassPageTest.java b/xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-ui/src/test/java/org/xwiki/administration/ConfigurableClassPageTest.java
index 399d4b3c91a49..f79fc8637db72 100644
--- a/xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-ui/src/test/java/org/xwiki/administration/ConfigurableClassPageTest.java
+++ b/xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-ui/src/test/java/org/xwiki/administration/ConfigurableClassPageTest.java
@@ -19,10 +19,11 @@
  */
 package org.xwiki.administration;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 import org.jsoup.nodes.Document;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -180,6 +181,31 @@ void checkScriptRight(boolean hasScript) throws Exception
         } else {
             expected = originalHeading;
         }
         assertEquals(expected, htmlPage.selectFirst("h2").text());
     }
+
+    @Test
+    void escapeNonViewableSections() throws Exception
+    {
+        // Create a new section document.
+        XWikiDocument mySectionDoc = new XWikiDocument(MY_SECTION);
+        this.xwiki.saveDocument(mySectionDoc, this.context);
+
+        when(this.oldcore.getMockRightService()
+            .hasAccessLevel(eq("view"), any(), eq("xwiki:" + MY_SECTION_SERIALIZED), any())).thenReturn(false);
+
+        // Make sure the section document is returned by the query.
+        when(this.query.execute()).thenReturn(List.of(MY_SECTION_SERIALIZED)).thenReturn(List.of());
+
+        DocumentReference docRef = new DocumentReference(WIKI_NAME, "\">{{/html}}{{noscript /}}", "WebHome");
+        XWikiDocument contextDoc = new XWikiDocument(docRef);
+        this.xwiki.saveDocument(contextDoc, this.context);
+        this.context.setDoc(contextDoc);
+
+        XWikiDocument doc = loadPage(CONFIGURABLE_CLASS);
+        Document htmlPage = renderHTMLPage(doc);
+        String errorMessage = Objects.requireNonNull(htmlPage.selectFirst("div.errormessage p")).text();
+        assertEquals(String.format("xe.admin.configurable.noViewAccessSomeApplications [[%s]]", MY_SECTION_SERIALIZED),
+            errorMessage);
+    }
 }

Vulnerable code: 
    {{error}}$services.localization.render('xe.admin.configurable.noViewAccessSomeApplications', [$appsUserCannotView]){{/error}}
Fixed code:         {{/html}}

        {{html clean=false}}
    {{error}}$services.localization.render('xe.admin.configurable.noViewAccessSomeApplications',
      'xwiki/2.1', [$appsUserCannotView]){{/error}}
import java.util.Objects;

    @Test
    void escapeNonViewableSections() throws Exception
    {
        // Create a new section document.
        XWikiDocument mySectionDoc = new XWikiDocument(MY_SECTION);
        this.xwiki.saveDocument(mySectionDoc, this.context);

        when(this.oldcore.getMockRightService()
            .hasAccessLevel(eq("view"), any(), eq("xwiki:" + MY_SECTION_SERIALIZED), any())).thenReturn(false);

        // Make sure the section document is returned by the query.
        when(this.query.execute()).thenReturn(List.of(MY_SECTION_SERIALIZED)).thenReturn(List.of());

        DocumentReference docRef = new DocumentReference(WIKI_NAME, "\">{{/html}}{{noscript /}}", "WebHome");
        XWikiDocument contextDoc = new XWikiDocument(docRef);
        this.xwiki.saveDocument(contextDoc, this.context);
        this.context.setDoc(contextDoc);

        XWikiDocument doc = loadPage(CONFIGURABLE_CLASS);
        Document htmlPage = renderHTMLPage(doc);
        String errorMessage = Objects.requireNonNull(htmlPage.selectFirst("div.errormessage p")).text();
        assertEquals(String.format("xe.admin.configurable.noViewAccessSomeApplications [[%s]]", MY_SECTION_SERIALIZED),
            errorMessage);
    }