CVE-2023-26471: Insufficient Information (NVD-CWE-noinfo)
value: XWiki Platform is a generic wiki platform. Starting in version 11.6-rc-1, comments are supposed to be executed with the right of superadmin but in restricted mode (anything dangerous is disabled), but the async macro does not take into account the restricted mode. This means that any user with comment right can use the async macro to make it execute any wiki content with the right of superadmin. This has been patched in XWiki 14.9, 14.4.6, and 13.10.10. The only known workaround consists of applying a patch and rebuilding and redeploying `org.xwiki.platform:xwiki-platform-rendering-async-macro`.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 8.8
Published: 2023-03-02T19:15Z
Repository: https://github.com/xwiki/xwiki-platform
Language: Java
Files changed: xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-api/src/main/java/org/xwiki/rendering/async/internal/block/BlockAsyncRendererConfiguration.java, xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-api/src/main/java/org/xwiki/rendering/async/internal/block/DefaultBlockAsyncRenderer.java, xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/main/java/org/xwiki/rendering/async/internal/AbstractExecutedContentMacro.java, xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/test/java/org/xwiki/rendering/async/AsyncMacroTest.java, xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/test/java/org/xwiki/rendering/async/IntegrationTests.java, xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-context/src/test/java/org/xwiki/rendering/internal/macro/context/ContextMacroTest.java
Commit date: 2022-10-18 11:33:50 +0200
Commit message: XWIKI-20234: It's possible to execute anything with superadmin right through comments and async macro

Diff: diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-api/src/main/java/org/xwiki/rendering/async/internal/block/BlockAsyncRendererConfiguration.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-api/src/main/java/org/xwiki/rendering/async/internal/block/BlockAsyncRendererConfiguration.java
index 3edb17a2ffe7..82a33c07978a 100644
--- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-api/src/main/java/org/xwiki/rendering/async/internal/block/BlockAsyncRendererConfiguration.java
+++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-api/src/main/java/org/xwiki/rendering/async/internal/block/BlockAsyncRendererConfiguration.java
@@ -59,10 +59,12 @@ public class BlockAsyncRendererConfiguration extends AsyncRendererConfiguration
 
     private Syntax targetSyntax;
 
     private boolean inline;
 
+    private boolean resricted;
+
     private BlockAsyncRendererDecorator decorator;
 
     private Set<EntityReference> references;
 
     private Set<ComponentRole<?>> roles;
@@ -236,10 +238,32 @@ public boolean isInline()
     public void setInline(boolean inline)
     {
         this.inline = inline;
     }
 
+    /**
+     * @return indicator of whether the transformation context is restricted or not
+     * @since 14.9
+     * @since 14.4.6
+     * @since 13.10.10
+     */
+    public boolean isResricted()
+    {
+        return this.resricted;
+    }
+
+    /**
+     * @param resricted indicator of whether the transformation context is restricted or not
+     * @since 14.9
+     * @since 14.4.6
+     * @since 13.10.10
+     */
+    public void setResricted(boolean resricted)
+    {
+        this.resricted = resricted;
+    }
+
     /**
      * @return the decorator
      */
     public BlockAsyncRendererDecorator getDecorator()
     {
diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-api/src/main/java/org/xwiki/rendering/async/internal/block/DefaultBlockAsyncRenderer.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-api/src/main/java/org/xwiki/rendering/async/internal/block/DefaultBlockAsyncRenderer.java
index d9e1328a2685..8e6a0d9917c9 100644
--- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-api/src/main/java/org/xwiki/rendering/async/internal/block/DefaultBlockAsyncRenderer.java
+++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-api/src/main/java/org/xwiki/rendering/async/internal/block/DefaultBlockAsyncRenderer.java
@@ -145,11 +145,11 @@ public Block execute(boolean async, boolean cached) throws RenderingException
     }
 
     private Block tranform(XDOM xdom, Block block) throws RenderingException
     {
         TransformationContext transformationContext =
-            new TransformationContext(xdom, this.configuration.getDefaultSyntax(), false);
+            new TransformationContext(xdom, this.configuration.getDefaultSyntax(), this.configuration.isResricted());
         transformationContext.setTargetSyntax(this.configuration.getTargetSyntax());
         transformationContext.setId(this.configuration.getTransformationId());
 
         transform(block, transformationContext);
 
diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/main/java/org/xwiki/rendering/async/internal/AbstractExecutedContentMacro.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/main/java/org/xwiki/rendering/async/internal/AbstractExecutedContentMacro.java
index 8a40f51ca5eb..57c6a0768304 100644
--- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/main/java/org/xwiki/rendering/async/internal/AbstractExecutedContentMacro.java
+++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/main/java/org/xwiki/rendering/async/internal/AbstractExecutedContentMacro.java
@@ -140,8 +140,11 @@ protected BlockAsyncRendererConfiguration createBlockAsyncRendererConfiguration(
         configuration.setTargetSyntax(this.renderingContext.getTargetSyntax());
 
         // Set the transformation id
         configuration.setTransformationId(context.getTransformationContext().getId());
 
+        // Indicate if we are in a restricted mode
+        configuration.setResricted(context.getTransformationContext().isRestricted());
+
         return configuration;
     }
 }
diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/test/java/org/xwiki/rendering/async/AsyncMacroTest.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/test/java/org/xwiki/rendering/async/AsyncMacroTest.java
new file mode 100644
index 000000000000..d9a567666c57
--- /dev/null
+++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/test/java/org/xwiki/rendering/async/AsyncMacroTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.rendering.async;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.xwiki.rendering.async.internal.AsyncMacro;
+import org.xwiki.rendering.async.internal.block.BlockAsyncRendererConfiguration;
+import org.xwiki.rendering.async.internal.block.BlockAsyncRendererExecutor;
+import org.xwiki.rendering.block.MacroBlock;
+import org.xwiki.rendering.block.WordBlock;
+import org.xwiki.rendering.block.XDOM;
+import org.xwiki.rendering.listener.MetaData;
+import org.xwiki.rendering.macro.MacroContentParser;
+import org.xwiki.rendering.syntax.Syntax;
+import org.xwiki.rendering.transformation.MacroTransformationContext;
+import org.xwiki.test.TestEnvironment;
+import org.xwiki.test.annotation.ComponentList;
+import org.xwiki.test.junit5.mockito.ComponentTest;
+import org.xwiki.test.junit5.mockito.InjectComponentManager;
+import org.xwiki.test.junit5.mockito.InjectMockComponents;
+import org.xwiki.test.junit5.mockito.MockComponent;
+import org.xwiki.test.mockito.MockitoComponentManager;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Unit tests for {@link AsyncMacro}.
+ *
+ * @version $Id$
+ * @since 8.3RC1
+ */
+@ComponentTest
+@ComponentList(TestEnvironment.class)
+class AsyncMacroTest
+{
+    @InjectMockComponents
+    private AsyncMacro macro;
+
+    @InjectComponentManager
+    private MockitoComponentManager componentManager;
+
+    @MockComponent
+    private MacroContentParser parser;
+
+    private BlockAsyncRendererExecutor executor;
+
+    @BeforeEach
+    public void beforeEach() throws Exception
+    {
+        this.executor = this.componentManager.getInstance(BlockAsyncRendererExecutor.class);
+    }
+
+    @Test
+    void executeInRestrictedMode() throws Exception
+    {
+        MacroBlock macroBlock = new MacroBlock("async", Collections.<String, String>emptyMap(), false);
+        MetaData metadata = new MetaData();
+        metadata.addMetaData(MetaData.SOURCE, "source");
+        XDOM pageXDOM = new XDOM(Arrays.asList(macroBlock), metadata);
+        MacroTransformationContext macroContext = new MacroTransformationContext();
+        macroContext.setSyntax(Syntax.XWIKI_2_0);
+        macroContext.setCurrentMacroBlock(macroBlock);
+        macroContext.setXDOM(pageXDOM);
+        macroContext.getTransformationContext().setRestricted(true);
+
+        XDOM contentXDOM = new XDOM(Arrays.asList(new WordBlock("test")), metadata);
+        when(this.parser.parse(eq(""), same(macroContext), eq(false), eq(false))).thenReturn(contentXDOM);
+
+        when(this.executor.execute(any())).thenReturn(new WordBlock("result"));
+
+        this.macro.execute(new AsyncMacroParameters(), "", macroContext);
+
+        ArgumentCaptor<BlockAsyncRendererConfiguration> configurationCaptor =
+            ArgumentCaptor.forClass(BlockAsyncRendererConfiguration.class);
+        verify(this.executor).execute(configurationCaptor.capture());
+
+        BlockAsyncRendererConfiguration configuration = configurationCaptor.getValue();
+        assertTrue(configuration.isResricted());
+    }
+}
diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/test/java/org/xwiki/rendering/macro/box/IntegrationTests.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/test/java/org/xwiki/rendering/async/IntegrationTests.java
similarity index 98%
rename from xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/test/java/org/xwiki/rendering/macro/box/IntegrationTests.java
rename to xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/test/java/org/xwiki/rendering/async/IntegrationTests.java
index 9c53df163b19..5db46cbc3b2e 100644
--- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/test/java/org/xwiki/rendering/macro/box/IntegrationTests.java
+++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/test/java/org/xwiki/rendering/async/IntegrationTests.java
@@ -15,11 +15,11 @@
  * 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.rendering.macro.box;
+package org.xwiki.rendering.async;
 
 import java.util.List;
 
 import org.jmock.Expectations;
 import org.jmock.Mockery;
@@ -31,11 +31,10 @@
 import org.xwiki.job.Request;
 import org.xwiki.model.reference.DocumentReference;
 import org.xwiki.model.reference.EntityReference;
 import org.xwiki.observation.ObservationManager;
 import org.xwiki.observation.event.Event;
-import org.xwiki.rendering.async.AsyncContext;
 import org.xwiki.rendering.async.internal.AsyncRendererJobRequest;
 import org.xwiki.rendering.async.internal.AsyncRendererJobStatus;
 import org.xwiki.rendering.test.integration.RenderingTestSuite;
 import org.xwiki.security.authorization.AuthorizationManager;
 import org.xwiki.security.authorization.Right;
diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-context/src/test/java/org/xwiki/rendering/internal/macro/context/ContextMacroTest.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-context/src/test/java/org/xwiki/rendering/internal/macro/context/ContextMacroTest.java
index 0dbb2f879101..bdfef96a71f7 100644
--- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-context/src/test/java/org/xwiki/rendering/internal/macro/context/ContextMacroTest.java
+++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-context/src/test/java/org/xwiki/rendering/internal/macro/context/ContextMacroTest.java
@@ -160,25 +160,38 @@ void executeWithReferencedDocumentNotViewableByTheAuthor() throws Exception
         }
     }
 
     @Test
     void executeOk() throws Exception
+    {
+        execute(false);
+    }
+
+    @Test
+    void executeInRestrictedMode() throws Exception
+    {
+        execute(true);
+    }
+
+    private void execute(boolean restricted) throws Exception
     {
         MacroBlock macroBlock = new MacroBlock("context", Collections.<String, String>emptyMap(), false);
         MetaData metadata = new MetaData();
         metadata.addMetaData(MetaData.SOURCE, "source");
         XDOM pageXDOM = new XDOM(Arrays.asList(macroBlock), metadata);
         MacroTransformationContext macroContext = new MacroTransformationContext();
         macroContext.setSyntax(Syntax.XWIKI_2_0);
         macroContext.setCurrentMacroBlock(macroBlock);
         macroContext.setXDOM(pageXDOM);
+        macroContext.getTransformationContext().setRestricted(restricted);
 
         DocumentModelBridge dmb = mock(DocumentModelBridge.class);
         when(this.dab.getTranslatedDocumentInstance(TARGET_REFERENCE)).thenReturn(dmb);
 
         XDOM contentXDOM = new XDOM(Arrays.asList(new WordBlock("test")), metadata);
-        when(this.parser.parse(eq(""), same(macroContext), eq(false), any(MetaData.class), eq(false))).thenReturn(contentXDOM);
+        when(this.parser.parse(eq(""), same(macroContext), eq(false), any(MetaData.class), eq(false)))
+            .thenReturn(contentXDOM);
 
         ContextMacroParameters parameters = new ContextMacroParameters();
         parameters.setDocument("target");
 
         when(this.executor.execute(any())).thenReturn(new WordBlock("result"));
@@ -191,7 +204,8 @@ void executeOk() throws Exception
 
         BlockAsyncRendererConfiguration configuration = configurationCaptor.getValue();
         assertEquals(AUTHOR, configuration.getSecureAuthorReference());
         assertEquals(SOURCE_REFERENCE, configuration.getSecureDocumentReference());
         assertSame(pageXDOM, configuration.getXDOM());
+        assertEquals(restricted, configuration.isResricted());
     }
 }

Vulnerable code:             new TransformationContext(xdom, this.configuration.getDefaultSyntax(), false);
package org.xwiki.rendering.macro.box;
import org.xwiki.rendering.async.AsyncContext;
        when(this.parser.parse(eq(""), same(macroContext), eq(false), any(MetaData.class), eq(false))).thenReturn(contentXDOM);
Fixed code:     private boolean resricted;

    /**
     * @return indicator of whether the transformation context is restricted or not
     * @since 14.9
     * @since 14.4.6
     * @since 13.10.10
     */
    public boolean isResricted()
    {
        return this.resricted;
    }

    /**
     * @param resricted indicator of whether the transformation context is restricted or not
     * @since 14.9
     * @since 14.4.6
     * @since 13.10.10
     */
    public void setResricted(boolean resricted)
    {
        this.resricted = resricted;
    }

            new TransformationContext(xdom, this.configuration.getDefaultSyntax(), this.configuration.isResricted());
        // Indicate if we are in a restricted mode
        configuration.setResricted(context.getTransformationContext().isRestricted());

/*
 * 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.rendering.async;

import java.util.Arrays;
import java.util.Collections;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.xwiki.rendering.async.internal.AsyncMacro;
import org.xwiki.rendering.async.internal.block.BlockAsyncRendererConfiguration;
import org.xwiki.rendering.async.internal.block.BlockAsyncRendererExecutor;
import org.xwiki.rendering.block.MacroBlock;
import org.xwiki.rendering.block.WordBlock;
import org.xwiki.rendering.block.XDOM;
import org.xwiki.rendering.listener.MetaData;
import org.xwiki.rendering.macro.MacroContentParser;
import org.xwiki.rendering.syntax.Syntax;
import org.xwiki.rendering.transformation.MacroTransformationContext;
import org.xwiki.test.TestEnvironment;
import org.xwiki.test.annotation.ComponentList;
import org.xwiki.test.junit5.mockito.ComponentTest;
import org.xwiki.test.junit5.mockito.InjectComponentManager;
import org.xwiki.test.junit5.mockito.InjectMockComponents;
import org.xwiki.test.junit5.mockito.MockComponent;
import org.xwiki.test.mockito.MockitoComponentManager;

import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

/**
 * Unit tests for {@link AsyncMacro}.
 *
 * @version $Id$
 * @since 8.3RC1
 */
@ComponentTest
@ComponentList(TestEnvironment.class)
class AsyncMacroTest
{
    @InjectMockComponents
    private AsyncMacro macro;

    @InjectComponentManager
    private MockitoComponentManager componentManager;

    @MockComponent
    private MacroContentParser parser;

    private BlockAsyncRendererExecutor executor;

    @BeforeEach
    public void beforeEach() throws Exception
    {
        this.executor = this.componentManager.getInstance(BlockAsyncRendererExecutor.class);
    }

    @Test
    void executeInRestrictedMode() throws Exception
    {
        MacroBlock macroBlock = new MacroBlock("async", Collections.<String, String>emptyMap(), false);
        MetaData metadata = new MetaData();
        metadata.addMetaData(MetaData.SOURCE, "source");
        XDOM pageXDOM = new XDOM(Arrays.asList(macroBlock), metadata);
        MacroTransformationContext macroContext = new MacroTransformationContext();
        macroContext.setSyntax(Syntax.XWIKI_2_0);
        macroContext.setCurrentMacroBlock(macroBlock);
        macroContext.setXDOM(pageXDOM);
        macroContext.getTransformationContext().setRestricted(true);

        XDOM contentXDOM = new XDOM(Arrays.asList(new WordBlock("test")), metadata);
        when(this.parser.parse(eq(""), same(macroContext), eq(false), eq(false))).thenReturn(contentXDOM);

        when(this.executor.execute(any())).thenReturn(new WordBlock("result"));

        this.macro.execute(new AsyncMacroParameters(), "", macroContext);

        ArgumentCaptor<BlockAsyncRendererConfiguration> configurationCaptor =
            ArgumentCaptor.forClass(BlockAsyncRendererConfiguration.class);
        verify(this.executor).execute(configurationCaptor.capture());

        BlockAsyncRendererConfiguration configuration = configurationCaptor.getValue();
        assertTrue(configuration.isResricted());
    }
}
package org.xwiki.rendering.async;
    {
        execute(false);
    }

    @Test
    void executeInRestrictedMode() throws Exception
    {
        execute(true);
    }

    private void execute(boolean restricted) throws Exception
        macroContext.getTransformationContext().setRestricted(restricted);
        when(this.parser.parse(eq(""), same(macroContext), eq(false), any(MetaData.class), eq(false)))
            .thenReturn(contentXDOM);
        assertEquals(restricted, configuration.isResricted());