CVE-2022-36092 (published 2022-09-08T18:15Z)

XWiki Platform Old Core is a core package for XWiki Platform, a generic wiki platform. Prior to versions 14.2 and 13.10.4, all rights checks that would normally prevent a user from viewing a document on a wiki can be bypassed using the login action and directly specified templates. This exposes title, content and comments of any document and properties of objects, though class and property name must be known. This is also exploitable on private wikis. This has been patched in versions 14.2 and 13.10.4 by properly checking view rights before loading documents and disallowing non-default templates in the login, registration and skin action. As a workaround, it would be possible to protect all templates individually by adding code to check access rights first.

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-287
cwe_name: Improper Authentication
description: When an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct.
extended_description: 
            
			
         
         

Fix information:
repo_url: https://github.com/xwiki/xwiki-platform
commit_details: repo_url: https://github.com/xwiki/xwiki-platform
author: Michael Hamann
author_date: 2022-03-24 16:35:08+01:00
msg: XWIKI-19549: Disallow template override for login, register and skin

* Also do not put a document without view rights into the context.
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: XWiki.java
change_type: ModificationType.MODIFY
diff: @@ -5917,31 +5917,41 @@ && getRightService().hasAccessLevel("view", XWikiRightService.GUEST_USER_FULLNAM
             }
         }
 
-        context.put("doc", doc);
-        context.put("cdoc", doc);
-        vcontext.put("doc", doc.newDocument(context));
-        vcontext.put("cdoc", vcontext.get("doc"));
-        XWikiDocument tdoc;
-
-        // If the parameter language exists and is empty, it means we want to force loading the regular document
-        // not a translation. This should be handled later by doing a better separation between locale used in the UI
-        // and for loading the documents.
-        if ("".equals(context.getRequest().getParameter("language"))) {
-            tdoc = doc;
+        if (!"skin".equals(context.getAction()) && !this.getRightService().hasAccessLevel("view",
+            user.getFullName(), doc.getFullName(), context)) {
+            // If for some reason (e.g., login action) the user has rights for the action but no view right on the
+            // document, do not load the document into the context.
+            setPhonyDocument(reference, context, vcontext);
+            doc = context.getDoc();
+            context.put("tdoc", doc);
+            context.put("cdoc", doc);
         } else {
-            tdoc = doc.getTranslatedDocument(context);
-        }
+            context.put("doc", doc);
+            context.put("cdoc", doc);
+            vcontext.put("doc", doc.newDocument(context));
+            vcontext.put("cdoc", vcontext.get("doc"));
+            XWikiDocument tdoc;
+
+            // If the parameter language exists and is empty, it means we want to force loading the regular document
+            // not a translation. This should be handled later by doing a better separation between locale used in the UI
+            // and for loading the documents.
+            if ("".equals(context.getRequest().getParameter("language"))) {
+                tdoc = doc;
+            } else {
+                tdoc = doc.getTranslatedDocument(context);
+            }
 
-        try {
-            String rev = (String) context.get("rev");
-            if (StringUtils.isNotEmpty(rev)) {
-                tdoc = getDocument(tdoc, rev, context);
+            try {
+                String rev = (String) context.get("rev");
+                if (StringUtils.isNotEmpty(rev)) {
+                    tdoc = getDocument(tdoc, rev, context);
+                }
+            } catch (Exception ex) {
+                // Invalid version, just use the most recent one
             }
-        } catch (Exception ex) {
-            // Invalid version, just use the most recent one
+            context.put("tdoc", tdoc);
+            vcontext.put("tdoc", tdoc.newDocument(context));
         }
-        context.put("tdoc", tdoc);
-        vcontext.put("tdoc", tdoc.newDocument(context));
 
         return true;
     }

programming_language: Java
filename: LoginAction.java
change_type: ModificationType.MODIFY
diff: @@ -37,6 +37,8 @@
 @Singleton
 public class LoginAction extends XWikiAction
 {
+    private static final String LOGIN = "login";
+
     /**
      * Default constructor.
      */
@@ -45,6 +47,18 @@ public LoginAction()
         this.waitForXWikiInitialization = false;
     }
 
+    @Override
+    public boolean action(XWikiContext context) throws XWikiException
+    {
+        // Disallow template override with xpage parameter.
+        if (!LOGIN.equals(Utils.getPage(context.getRequest(), LOGIN))) {
+            throw new XWikiException(XWikiException.MODULE_XWIKI, XWikiException.ERROR_XWIKI_ACCESS_DENIED,
+                String.format("Template may not be overriden with 'xpage' in [%s] action.", LOGIN));
+        }
+
+        return super.action(context);
+    }
+
     @Override
     public String render(XWikiContext context) throws XWikiException
     {
@@ -53,6 +67,6 @@ public String render(XWikiContext context) throws XWikiException
         if (!"1".equals(context.getRequest().getParameter("loginLink"))) {
             context.getResponse().setStatus(401);
         }
-        return "login";
+        return LOGIN;
     }
 }

programming_language: Java
filename: LoginErrorAction.java
change_type: ModificationType.MODIFY
diff: @@ -37,9 +37,23 @@
 @Singleton
 public class LoginErrorAction extends XWikiAction
 {
+    private static final String LOGIN = "login";
+
+    @Override
+    public boolean action(XWikiContext context) throws XWikiException
+    {
+        // Disallow template override with xpage parameter.
+        if (!LOGIN.equals(Utils.getPage(context.getRequest(), LOGIN))) {
+            throw new XWikiException(XWikiException.MODULE_XWIKI, XWikiException.ERROR_XWIKI_ACCESS_DENIED,
+                String.format("Template may not be overriden with 'xpage' in [%s] action.", LOGIN));
+        }
+
+        return super.action(context);
+    }
+
     @Override
     public String render(XWikiContext context) throws XWikiException
     {
-        return "login";
+        return LOGIN;
     }
 }

programming_language: Java
filename: LoginSubmitAction.java
change_type: ModificationType.MODIFY
diff: @@ -42,6 +42,20 @@
 @Singleton
 public class LoginSubmitAction extends XWikiAction
 {
+    private static final String LOGIN = "login";
+
+    @Override
+    public boolean action(XWikiContext context) throws XWikiException
+    {
+        // Disallow template override with xpage parameter.
+        if (!LOGIN.equals(Utils.getPage(context.getRequest(), LOGIN))) {
+            throw new XWikiException(XWikiException.MODULE_XWIKI, XWikiException.ERROR_XWIKI_ACCESS_DENIED,
+                String.format("Template may not be overriden with 'xpage' in [%s] action.", LOGIN));
+        }
+
+        return super.action(context);
+    }
+
     @Override
     public String render(XWikiContext context) throws XWikiException
     {
@@ -49,6 +63,6 @@ public String render(XWikiContext context) throws XWikiException
         if (StringUtils.isNotBlank(msg)) {
             context.getResponse().setStatus(HttpServletResponse.SC_FORBIDDEN);
         }
-        return "login";
+        return LOGIN;
     }
 }

programming_language: Java
filename: RegisterAction.java
change_type: ModificationType.MODIFY
diff: @@ -62,6 +62,12 @@ public boolean action(XWikiContext context) throws XWikiException
         XWikiRequest request = context.getRequest();
         XWikiResponse response = context.getResponse();
 
+        // Disallow template override with xpage parameter.
+        if (!REGISTER.equals(Utils.getPage(context.getRequest(), REGISTER))) {
+            throw new XWikiException(XWikiException.MODULE_XWIKI, XWikiException.ERROR_XWIKI_ACCESS_DENIED,
+                String.format("Template may not be overriden with 'xpage' in [%s] action.", REGISTER));
+        }
+
         String register = request.getParameter(REGISTER);
         if (register != null && register.equals("1")) {
             // CSRF prevention

programming_language: Java
filename: SkinAction.java
change_type: ModificationType.MODIFY
diff: @@ -66,6 +66,7 @@
 @Singleton
 public class SkinAction extends XWikiAction
 {
+
     /** Logging helper. */
     private static final Logger LOGGER = LoggerFactory.getLogger(SkinAction.class);
 
@@ -83,6 +84,20 @@ public class SkinAction extends XWikiAction
      */
     private static final String ENCODING = "UTF-8";
 
+    private static final String DOCDOESNOTEXIST = "docdoesnotexist";
+
+    @Override
+    public boolean action(XWikiContext context) throws XWikiException
+    {
+        // Disallow template override with xpage parameter.
+        if (!DOCDOESNOTEXIST.equals(Utils.getPage(context.getRequest(), DOCDOESNOTEXIST))) {
+            throw new XWikiException(XWikiException.MODULE_XWIKI, XWikiException.ERROR_XWIKI_ACCESS_DENIED,
+                "Template may not be overriden with 'xpage' in [skin] action.");
+        }
+
+        return super.action(context);
+    }
+
     @Override
     public String render(XWikiContext context) throws XWikiException
     {
@@ -90,7 +105,7 @@ public String render(XWikiContext context) throws XWikiException
             return render(context.getRequest().getPathInfo(), context);
         } catch (IOException e) {
             context.getResponse().setStatus(404);
-            return "docdoesnotexist";
+            return DOCDOESNOTEXIST;
         }
     }
 
@@ -177,7 +192,7 @@ public String render(String path, XWikiContext context) throws XWikiException, I
         }
         if (!found) {
             context.getResponse().setStatus(404);
-            return "docdoesnotexist";
+            return DOCDOESNOTEXIST;
         }
         return null;
     }

programming_language: Java
repo_url: https://github.com/xwiki/xwiki-platform
commit_details: repo_url: https://github.com/xwiki/xwiki-platform
author: Michael Hamann
author_date: 2022-03-25 11:14:51+01:00
msg: XWIKI-19549: Disallow template override for login, register and skin

* Also allow `registerinline` template for RegisterAction.
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: RegisterAction.java
change_type: ModificationType.MODIFY
diff: @@ -19,6 +19,9 @@
  */
 package com.xpn.xwiki.web;
 
+import java.util.Arrays;
+import java.util.List;
+
 import javax.inject.Named;
 import javax.inject.Singleton;
 import javax.script.ScriptContext;
@@ -55,6 +58,9 @@ public class RegisterAction extends XWikiAction
     /** Space where the registration config and class are stored. */
     private static final String WIKI_SPACE = "XWiki";
 
+    /** Allowed templates for this action. */
+    private static final List<String> ALLOWED_TEMPLATES = Arrays.asList(REGISTER, "registerinline");
+
     @Override
     public boolean action(XWikiContext context) throws XWikiException
     {
@@ -62,10 +68,10 @@ public boolean action(XWikiContext context) throws XWikiException
         XWikiRequest request = context.getRequest();
         XWikiResponse response = context.getResponse();
 
-        // Disallow template override with xpage parameter.
-        if (!REGISTER.equals(Utils.getPage(context.getRequest(), REGISTER))) {
+        // Limit template overrides with xpage to allowed templates.
+        if (!ALLOWED_TEMPLATES.contains(Utils.getPage(context.getRequest(), REGISTER))) {
             throw new XWikiException(XWikiException.MODULE_XWIKI, XWikiException.ERROR_XWIKI_ACCESS_DENIED,
-                String.format("Template may not be overriden with 'xpage' in [%s] action.", REGISTER));
+                String.format("Forbidden template override with 'xpage' in [%s] action.", REGISTER));
         }
 
         String register = request.getParameter(REGISTER);

programming_language: Java