CVE-2023-26476 (published 2023-03-02T19:15Z)

XWiki Platform is a generic wiki platform. Starting in version 3.2-m3, users can deduce the content of the password fields by repeated call to `LiveTableResults` and `WikisLiveTableResultsMacros`. The issue can be fixed by upgrading to versions 14.7-rc-1, 13.4.4, or 13.10.9 and higher, or in version >= 3.2M3 by applying the patch manually on `LiveTableResults` and `WikisLiveTableResultsMacros`.

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

Weakness information:
cwe_id: CWE-307
cwe_name: Improper Restriction of Excessive Authentication Attempts
description: The product does not implement sufficient measures to prevent multiple failed authentication attempts within a short time frame, making it more susceptible to brute force attacks.
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: 2022-07-21 14:38:07+02:00
msg: XWIKI-19949: Livetable results allow reconstructing password hashes using 768 requests
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: @@ -73,7 +73,15 @@
   ##
   #set($tablelist = [])
   #foreach($colname in $collist)
-    #livetable_addColumnToQuery($colname)
+    ## If a classname is defined and the class field corresponding to the column name,
+    ## we check the type of the field and skip it if it's Password.
+    #if ($className != '' &amp;&amp; $class.get($colname))
+      #if ($class.get($colname).classType != 'Password')
+        #livetable_addColumnToQuery($colname)
+      #end
+    #else
+      #livetable_addColumnToQuery($colname)
+    #end
   #end
   ##
   ## Tag filtering

programming_language: PowerShell
filename: LiveTableResultsTest.java
change_type: ModificationType.MODIFY
diff: @@ -20,6 +20,7 @@
 package org.xwiki.livetable;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -44,6 +45,7 @@
 
 import com.xpn.xwiki.XWikiContext;
 import com.xpn.xwiki.doc.XWikiDocument;
+import com.xpn.xwiki.objects.classes.BaseClass;
 import com.xpn.xwiki.objects.classes.StaticListClass;
 import com.xpn.xwiki.plugin.tag.TagPluginApi;
 
@@ -500,6 +502,35 @@ void removeObfuscatedResultsWhenLimitIs0() throws Exception
         assertEquals(emptyList(), getRows());
     }
 
+    @Test
+    void cleanupAccessToPasswordFields() throws Exception
+    {
+        // Initialize an XClass with a password field.
+        DocumentReference documentReference = new DocumentReference("xwiki", "XWiki", "MyClass");
+        XWikiDocument xwikiDocument = this.xwiki.getDocument(documentReference, this.context);
+        BaseClass xClass = xwikiDocument.getXClass();
+        xClass.addPasswordField("password", "Password", 30);
+        this.xwiki.saveDocument(xwikiDocument, this.context);
+
+        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(0L);
+        when(this.query.execute()).thenReturn(Collections.emptyList());
+
+        this.request.put("classname", "XWiki.MyClass");
+        this.request.put("password", "abcd");
+        this.request.put("collist", "password");
+
+        renderPage();
+
+        verify(this.queryService).hql(", BaseObject as obj   "
+            + "where obj.name=doc.fullName "
+            + "and obj.className = :className "
+            + "and doc.fullName not in (:classTemplate1, :classTemplate2)  ");
+    }
+
     //
     // Helper methods
     //

programming_language: Java
filename: WikisLiveTableResultsMacros.xml
change_type: ModificationType.MODIFY
diff: @@ -57,7 +57,15 @@
   ##
   #set($tablelist = [])
   #foreach($colname in $collist)
-    #livetable_addColumnToQuery($colname)
+    ## If a classname is defined and the class field corresponding to the column name,
+    ## we check the type of the field and skip it if it's Password.
+    #if ($className != '' &amp;&amp; $class.get($colname))
+      #if ($class.get($colname).classType != 'Password')
+        #livetable_addColumnToQuery($colname)
+      #end
+    #else
+      #livetable_addColumnToQuery($colname)
+    #end
   #end
   ##
   ## Tag filtering

programming_language: PowerShell