Headline
CVE-2023-37911: XWIKI-20685: Check access on the revision provider in the script API · xwiki/xwiki-platform@f471f2a
XWiki Platform is a generic wiki platform offering runtime services for applications built on top of it. Starting in version 9.4-rc-1 and prior to versions 14.10.8 and 15.3-rc-1, when a document has been deleted and re-created, it is possible for users with view right on the re-created document but not on the deleted document to view the contents of the deleted document. Such a situation might arise when rights were added to the deleted document. This can be exploited through the diff feature and, partially, through the REST API by using versions such as deleted:1
(where the number counts the deletions in the wiki and is thus guessable). Given sufficient rights, the attacker can also re-create the deleted document, thus extending the scope to any deleted document as long as the attacker has edit right in the location of the deleted document. This vulnerability has been patched in XWiki 14.10.8 and 15.3 RC1 by properly checking rights when deleted revisions of a document are accessed. The only workaround is to regularly clean deleted documents to minimize the potential exposure. Extra care should be taken when deleting sensitive documents that are protected individually (and not, e.g., by being placed in a protected space) or deleting a protected space as a whole.
Expand Up @@ -23,17 +23,23 @@
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.xwiki.model.reference.DocumentReference; import org.xwiki.observation.ObservationManager; import org.xwiki.rendering.renderer.PrintRendererFactory; import org.xwiki.rendering.syntax.Syntax; import org.xwiki.security.authorization.AuthorizationException; import org.xwiki.security.authorization.ContextualAuthorizationManager; import org.xwiki.security.authorization.Right; import org.xwiki.test.junit5.mockito.MockComponent; import org.xwiki.test.mockito.MockitoComponentManager; import org.xwiki.user.CurrentUserReference; import org.xwiki.user.UserReferenceResolver;
import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.XWikiException; import com.xpn.xwiki.doc.DocumentRevisionProvider; import com.xpn.xwiki.doc.XWikiDocument; import com.xpn.xwiki.doc.XWikiDocumentArchive; import com.xpn.xwiki.test.MockitoOldcore; Expand All @@ -45,6 +51,9 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when;
/** Expand All @@ -56,6 +65,8 @@ @ReferenceComponentList public class XWikiTest { private static final DocumentReference DOCUMENT_REFERENCE = new DocumentReference("xwiki", "MilkyWay", “Fidis”);
@MockComponent private UserReferenceResolver<CurrentUserReference> currentUserReferenceUserReferenceResolver;
Expand All @@ -78,8 +89,7 @@ public void setup(MockitoOldcore mockitoOldcore) throws XWikiException .thenReturn(new XWikiDocumentArchive());
xWikiContext.setUser(“Redtail”); this.apiDocument = new Document(new XWikiDocument(new DocumentReference("xwiki", "MilkyWay", “Fidis”)), xWikiContext); this.apiDocument = new Document(new XWikiDocument(DOCUMENT_REFERENCE), xWikiContext); this.apiDocument.getDocument().setCreator(“c” + xWikiContext.getUser()); this.apiDocument.getDocument().setAuthor(“a” + xWikiContext.getUser()); this.apiDocument.save(); Expand Down Expand Up @@ -134,4 +144,34 @@ public void getAvailableRendererSyntax(MockitoComponentManager componentManager) assertNull(this.apiXWiki.getAvailableRendererSyntax("plai", “1.0”)); assertNull(this.apiXWiki.getAvailableRendererSyntax("plai", null)); }
@ParameterizedTest @ValueSource(booleans = { false, true }) void getDocumentRevision(boolean allowAccess, MockitoOldcore mockitoOldcore) throws Exception { DocumentRevisionProvider revisionProvider = mockitoOldcore.getMocker().registerMockComponent(DocumentRevisionProvider.class); ContextualAuthorizationManager contextualAuthorizationManager = mockitoOldcore.getMockContextualAuthorizationManager();
XWikiDocument deletedDocument = new XWikiDocument(DOCUMENT_REFERENCE); deletedDocument.setContent(“Deleted”); String revision = "deleted:1"; when(revisionProvider.getRevision(DOCUMENT_REFERENCE, revision)).thenReturn(deletedDocument);
when(contextualAuthorizationManager.hasAccess(Right.VIEW, DOCUMENT_REFERENCE)).thenReturn(true);
if (!allowAccess) { doThrow(new AuthorizationException(“Denied”)).when(revisionProvider) .checkAccess(Right.VIEW, CurrentUserReference.INSTANCE, DOCUMENT_REFERENCE, revision); assertNull(this.apiXWiki.getDocument(DOCUMENT_REFERENCE, revision)); } else { assertEquals(new Document(deletedDocument, mockitoOldcore.getXWikiContext()), this.apiXWiki.getDocument(DOCUMENT_REFERENCE, revision)); }
verify(revisionProvider, times(allowAccess ? 1 : 0)).getRevision(DOCUMENT_REFERENCE, revision); verify(revisionProvider).checkAccess(Right.VIEW, CurrentUserReference.INSTANCE, DOCUMENT_REFERENCE, revision); verify(contextualAuthorizationManager).hasAccess(Right.VIEW, DOCUMENT_REFERENCE); } }
Related news
### Impact When a document has been deleted and re-created, it is possible for users with view right on the re-created document but not on the deleted document to view the contents of the deleted document. Such a situation might arise when rights were added to the deleted document. This can be exploited through the diff feature and, partially, through the REST API by using versions such as `deleted:1` (where the number counts the deletions in the wiki and is thus guessable). Given sufficient rights, the attacker can also re-create the deleted document, thus extending the scope to any deleted document as long as the attacker has edit right in the location of the deleted document. ### Patches This vulnerability has been patched in XWiki 14.10.8 and 15.3 RC1 by properly checking rights when deleted revisions of a document are accessed. ### Workarounds The only workaround is to regularly [clean deleted documents](https://extensions.xwiki.org/xwiki/bin/view/Extension/Index%20Application#...