CVE-2023-38509 (published 2023-11-07T04:17Z)

XWiki Platform is a generic wiki platform. In org.xwiki.platform:xwiki-platform-livetable-ui starting with version 3.5-milestone-1 and prior to versions 14.10.9 and 15.3-rc-1, the mail obfuscation configuration was not fully taken into account and is was still possible by obfuscated emails. This has been patched in XWiki 14.10.9 and XWiki 15.3-rc-1. A workaround is to modify the page `XWiki.LiveTableResultsMacros` following the patch.

CVSS v3 base score: 4.3, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N)

Weakness information:
cwe_id: CWE-402
cwe_name: Transmission of Private Resources into a New Sphere ('Resource Leak')
description: The product makes resources available to untrusted parties when those resources are only intended to be accessed by the product.
extended_description: 
            
         
         

Fix information:
repo_url: https://github.com/xwiki/xwiki-platform
commit_details: repo_url: https://github.com/xwiki/xwiki-platform
author: Manuel Leduc
author_date: 2023-04-06 17:33:48+02:00
msg: XWIKI-20601: Improved User Directory sorting
repository: repo_url: https://github.com/xwiki/xwiki-platform
repo_name: xwiki/xwiki-platform
description: The XWiki platform
repo_language: Java
owner: xwiki
file_changes: filename: LiveTableResultsMacros.xml
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,7 @@
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 -->
 
-<xwikidoc version="1.4" reference="XWiki.LiveTableResultsMacros" locale="">
+<xwikidoc version="1.5" reference="XWiki.LiveTableResultsMacros" locale="">
   <web>XWiki</web>
   <name>LiveTableResultsMacros</name>
   <language/>
@@ -138,6 +138,8 @@
   #set($order = "$!request.sort")
   #if ($order == 'doc.location')
     #set ($order = 'doc.fullName')
+  #elseif ($order == 'email' &amp;&amp; $services.mail.general.shouldObfuscate())
+    #set ($order = '')
   #end
   #set ($orderSql = '')
   #if($order != '')

programming_language: PowerShell
filename: LiveTableResultsTest.java
change_type: ModificationType.MODIFY
diff: @@ -643,6 +643,88 @@ void obfuscateEmails(boolean obfuscate, String expectedHql, Map<String, Object>
         verify(this.query).bindValues(expectedBindValues);
     }
 
+    public static Stream<Arguments> provideObfuscateEmailsSort()
+    {
+        return Stream.of(
+            Arguments.of(
+                true,
+                ", BaseObject as obj   "
+                    + "where obj.name=doc.fullName "
+                    + "and obj.className = :className "
+                    + "and doc.fullName not in (:classTemplate1, :classTemplate2)  ",
+                Map.of(
+                    "className", "Space.MyClass",
+                    "classTemplate1", "Space.MyClassTemplate",
+                    "classTemplate2", "Space.MyTemplate"
+                ),
+                "t...@mail.com",
+                "t...@mail.com"
+            ),
+            Arguments.of(
+                false,
+                ", BaseObject as obj , StringProperty prop_email  "
+                    + "where obj.name=doc.fullName "
+                    + "and obj.className = :className "
+                    + "and doc.fullName not in (:classTemplate1, :classTemplate2)  "
+                    + "and obj.id=prop_email.id.id "
+                    + "and prop_email.name = :prop_email_name   "
+                    + "order by lower(prop_email.value) asc, prop_email.value asc",
+                Map.of(
+                    "className", "Space.MyClass",
+                    "classTemplate1", "Space.MyClassTemplate",
+                    "classTemplate2", "Space.MyTemplate",
+                    "prop_email_name", "email"
+                ),
+                "<a href=\"mailto:test@mail.com\">test@mail.com</a>",
+                "test@mail.com"
+            )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("provideObfuscateEmailsSort")
+    void obfuscateEmailsSort(boolean obfuscate, String expectedHql, Map<String, Object> expectedBindValues,
+        String expectedMail, String expectedMailValue) throws Exception
+    {
+        // TODO: We mock the mail configuration as it relies on document that are loaded through xar files from external
+        //  modules, which is currently not possible (would it be loaded using a mandatory document initializer, it 
+        //  would work though).
+        when(this.generalMailConfiguration.shouldObfuscate()).thenReturn(obfuscate);
+
+        DocumentReference myClassReference = new DocumentReference("xwiki", "Space", "MyClass");
+        XWikiDocument xClassDocument = new XWikiDocument(myClassReference);
+        xClassDocument.getXClass().addEmailField("mail", "Email", 100);
+        xClassDocument.getXClass().addTextField("name", "Name", 100);
+        this.xwiki.saveDocument(xClassDocument, this.context);
+
+        XWikiDocument xObjectDocument = new XWikiDocument(new DocumentReference("xwiki", "Space", "MyObject"));
+        xObjectDocument.setSyntax(XWIKI_2_1);
+        BaseObject baseObject = xObjectDocument.newXObject(myClassReference, this.context);
+        baseObject.set("mail", "test@mail.com", this.context);
+        baseObject.set("name", "testName", this.context);
+        this.xwiki.saveDocument(xObjectDocument, this.context);
+
+        setColumns("mail,name");
+        setClassName("Space.MyClass");
+        setSort("email", true);
+
+        when(this.queryService.hql(anyString())).thenReturn(this.query);
+        when(this.query.setLimit(anyInt())).thenReturn(this.query);
+        when(this.query.setOffset(anyInt())).thenReturn(this.query);
+        when(this.query.bindValues(any(Map.class))).thenReturn(this.query);
+        when(this.query.count()).thenReturn(1L);
+        when(this.query.execute()).thenReturn(singletonList("Space.MyObject"));
+
+        renderPage();
+
+        List<Map<String, Object>> rows = getRows();
+        assertEquals(expectedMail, StringUtils.trim((String) rows.get(0).get("mail")));
+        assertEquals(expectedMailValue, rows.get(0).get("mail_value"));
+
+        verify(this.queryService).hql(expectedHql);
+        verify(this.query).bindValues(expectedBindValues);
+    }
+
     //
     // Helper methods
     //

programming_language: Java