CVE-2023-30537 (XML, published 2023-04-16T08:15Z)
Description: value: XWiki Platform is a generic wiki platform offering runtime services for applications built on top of it. Any user with the right to add an object on a page can execute arbitrary Groovy, Python or Velocity code in XWiki leading to full access to the XWiki installation. The root cause is improper escaping of the styles properties `FlamingoThemesCode.WebHome`. This page is installed by default. The vulnerability has been patched in XWiki versions 13.10.11, 14.4.7 and 14.10.
Severity: nan (CVSS v3 base score: 8.8)
Weakness: CWE-94 \u2014 Improper Control of Generation of Code ('Code Injection')
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.
Repository: https://github.com/xwiki/xwiki-platform
Files changed:
xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-theme/xwiki-platform-flamingo-theme-ui/pom.xml
xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-theme/xwiki-platform-flamingo-theme-ui/src/main/resources/FlamingoThemesCode/WebHomeSheet.xml
xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-theme/xwiki-platform-flamingo-theme-ui/src/test/java/org/xwiki/flamingo/WebHomeSheetPageTest.java
xwiki-platform-core/xwiki-platform-wiki/xwiki-platform-wiki-script/pom.xml
xwiki-platform-core/xwiki-platform-wiki/xwiki-platform-wiki-script/src/test/java/org/xwiki/wiki/script/WikiManagerScriptServiceComponentList.java
Commit message: XWIKI-20280: Improved link display for FlamingoThemesCode.WebHomeSheet


Vulnerable code:
      === [[$themeDoc.displayTitle&gt;&gt;$fullName]] #if ($isSubWiki &amp;&amp; $scope == 'local') ($services.wiki.currentWikiId)#end===
        $services.icon.render('bullet_go') [[$services.localization.render('platform.flamingo.themes.home.useThisTheme')&gt;&gt;path:$doc.getURL('view', "action=setTheme&amp;theme=${fullName}&amp;form_token=$services.csrf.token")]]
    $value##
    RenderingConfigClassDocumentConfigurationSource.class
        Document document = this.renderHTMLPage(new DocumentReference("xwiki", "FlamingoThemesCode", "WebHomeSheet"));

Fixed code:
    <dependency>
      <groupId>org.xwiki.platform</groupId>
      <artifactId>xwiki-platform-wiki-script</artifactId>
      <version>${project.version}</version>
      <scope>runtime</scope>
    </dependency>
    <!-- Security Script Component List for the Page Tests. -->
    <dependency>
      <groupId>org.xwiki.platform</groupId>
      <artifactId>xwiki-platform-security-authorization-script</artifactId>
      <version>${project.version}</version>
      <scope>test</scope>
      <type>test-jar</type>
    </dependency>
    <!-- Wiki Manager Component List for the Page Tests. -->
    <dependency>
      <groupId>org.xwiki.platform</groupId>
      <artifactId>xwiki-platform-wiki-script</artifactId>
      <version>${project.version}</version>
      <scope>test</scope>
      <type>test-jar</type>
    </dependency>
      #set ($themeDocTitle = $services.rendering.escape($services.rendering.escape($themeDoc.displayTitle, 'xwiki/2.1'),
        'xwiki/2.1'))
      #set ($themeDocLink = $services.rendering.escape($fullName, 'xwiki/2.1'))
      === [[$themeDocTitle&gt;&gt;$themeDocLink]] #if ($isSubWiki &amp;&amp; $scope ==
        'local') ($services.rendering.escape($services.wiki.currentWikiId, 'xwiki/2.1'))#end===
        #set ($useThisThemeTitle = $services.rendering.escape($services.rendering.escape($services.localization.render(
          'platform.flamingo.themes.home.useThisTheme'), 'xwiki/2.1'), 'xwiki/2.1'))
        #set ($viewThemeUrl = $doc.getURL('view', $escapetool.url({
          'action': 'setTheme',
          'theme': $fullName,
          'form_token': $services.csrf.token
        })))
        #set ($useThisThemePath = "path:$viewThemeUrl")
        $services.icon.render('bullet_go') [[$useThisThemeTitle&gt;&gt;$useThisThemePath]]
    $escapetool.xml($value)##
import java.util.List;

import javax.script.ScriptContext;

import org.jsoup.nodes.Element;
import org.junit.jupiter.api.BeforeEach;
import org.xwiki.model.script.ModelScriptService;
import org.xwiki.query.Query;
import org.xwiki.query.script.QueryManagerScriptService;
import org.xwiki.script.ScriptContextManager;
import org.xwiki.script.service.ScriptService;
import org.xwiki.security.authorization.AuthorizationManager;
import org.xwiki.security.authorization.Right;
import org.xwiki.security.script.SecurityScriptServiceComponentList;
import org.xwiki.wiki.script.WikiManagerScriptServiceComponentList;

import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.objects.BaseObject;
import static javax.script.ScriptContext.GLOBAL_SCOPE;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@SecurityScriptServiceComponentList
@WikiManagerScriptServiceComponentList
    RenderingConfigClassDocumentConfigurationSource.class,
    ModelScriptService.class
    private static final DocumentReference WEBHOME_SHEET =
        new DocumentReference("xwiki", "FlamingoThemesCode", "WebHomeSheet");

    private static final DocumentReference NEW_THEME_DOCUMENT_REFERENCE =
        new DocumentReference("xwiki", "Space", "NewTheme");

    private QueryManagerScriptService queryManagerScriptService;

    private AuthorizationManager authorizationManager;

    private ScriptContext scriptContext;

    @BeforeEach
    void setUp() throws Exception
    {
        this.queryManagerScriptService =
            this.componentManager.registerMockComponent(ScriptService.class, "query", QueryManagerScriptService.class,
                false);
        this.authorizationManager = this.componentManager.getInstance(AuthorizationManager.class);
        this.scriptContext = this.oldcore.getMocker().<ScriptContextManager>getInstance(ScriptContextManager.class)
            .getCurrentScriptContext();
    }

        Document document = renderHTMLPage(WEBHOME_SHEET);

    @Test
    void listAvailableThemes() throws Exception
    {
        loadPage(new DocumentReference("xwiki", "FlamingoThemes", "Charcoal"));
        initNewTheme();
        
        // Mock the database.
        Query query = mock(Query.class);
        when(this.queryManagerScriptService.xwql("from doc.object(FlamingoThemesCode.ThemeClass) obj WHERE doc"
            + ".fullName <> 'FlamingoThemesCode.ThemeTemplate' ORDER BY doc.name")).thenReturn(query);
        when(query.setWiki(anyString())).thenReturn(query);
        when(query.execute()).thenReturn(List.of("Space.NewTheme"));
        
        // Allow the current user to have access to the resources.
        when(this.authorizationManager.hasAccess(eq(Right.VIEW), any(), eq(NEW_THEME_DOCUMENT_REFERENCE)))
            .thenReturn(true);
        this.scriptContext.setAttribute("hasAdmin", true, GLOBAL_SCOPE);

        Document document = renderHTMLPage(WEBHOME_SHEET);
        
        // Validate the links and styles.
        Element newThemeHeader = document.select("h3").get(1);
        String newThemeHeaderText = newThemeHeader.text();
        String newThemeHeaderLinkHref = newThemeHeader.selectFirst("a").attr("href");
        assertEquals("]] &#123;&#123;noscript}}println(\"Hello from title!\")&#123;&#123;/noscript}}",
            newThemeHeaderText);
        assertEquals("Space.NewTheme", newThemeHeaderLinkHref);

        String newThemeMockupPageStyle = document.select(".mockup-page").get(1).attr("style");
        assertEquals("background-color: {{/html}} {{noscript}}println(\"Hello from body-bg!\"){{/noscript}} \"/>"
                + "<script>...</script/>",
            newThemeMockupPageStyle);
    }

    /**
     * Creates a new page describing a theme.
     *
     * @throws XWikiException in case of error
     */
    private void initNewTheme() throws XWikiException
    {
        XWikiDocument newTheme = this.xwiki.getDocument(NEW_THEME_DOCUMENT_REFERENCE, this.context);
        newTheme.setTitle("]] {{noscript}}println(\"Hello from title!\"){{/noscript}}");
        BaseObject baseObject =
            newTheme.newXObject(new DocumentReference("xwiki", "FlamingoThemesCode", "ThemeClass"), this.context);
        baseObject.setStringValue("body-bg",
            "{{/html}} {{noscript}}println(\"Hello from body-bg!\"){{/noscript}} \"/><script>...</script/>");
        this.xwiki.saveDocument(newTheme, this.context);
    }
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <executions>
          <execution>
            <id>test-jar</id>
            <goals>
              <goal>test-jar</goal>
            </goals>
            <configuration>
              <includes>
                <include>**/WikiManagerScriptServiceComponentList.class</include>
              </includes>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.wiki.script;

import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import org.xwiki.test.annotation.ComponentList;
import org.xwiki.url.internal.standard.DefaultStandardURLConfiguration;
import org.xwiki.wiki.internal.configuration.DefaultWikiConfiguration;
import org.xwiki.wiki.internal.descriptor.builder.DefaultWikiDescriptorBuilder;
import org.xwiki.wiki.internal.descriptor.document.DefaultWikiDescriptorDocumentHelper;
import org.xwiki.wiki.internal.manager.DefaultWikiCreator;
import org.xwiki.wiki.internal.manager.DefaultWikiDeleter;
import org.xwiki.wiki.internal.manager.DefaultWikiManager;
import org.xwiki.wiki.internal.provisioning.DefaultWikiCopier;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Pack of default Components that are needed for the wiki manager script service.
 *
 * @version $Id$
 * @since 14.10RC1
 */
@Documented
@Retention(RUNTIME)
@Target({ TYPE, METHOD, ANNOTATION_TYPE })
@ComponentList({
    WikiManagerScriptService.class,
    DefaultWikiManager.class,
    DefaultWikiCreator.class,
    DefaultWikiDescriptorBuilder.class,
    DefaultWikiDescriptorDocumentHelper.class,
    DefaultWikiConfiguration.class,
    DefaultWikiCopier.class,
    DefaultWikiDeleter.class,
    DefaultStandardURLConfiguration.class
})
@Inherited
public @interface WikiManagerScriptServiceComponentList
{
}