CVE-2023-29210: Improper Control of Generation of Code ('Code Injection') (CWE-94)
value: XWiki Commons are technical libraries common to several other top level XWiki projects. Any user with view rights on commonly accessible documents including the notification preferences macros can execute arbitrary Groovy, Python or Velocity code in XWiki leading to full access to the XWiki installation. The root cause is improper escaping of the user parameter of the macro that provide the notification filters. These macros are used in the user profiles and thus installed by default in XWiki. The vulnerability has been patched in XWiki 13.10.11, 14.4.7 and 14.10.
CWE description: The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.
CVSS v3 base score: 8.8
Published: 2023-04-15T17:15Z
Repository: https://github.com/xwiki/xwiki-platform
Language: XML
Files changed: xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsApplicationsPreferencesMacro.xml, xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsAutoWatchPreferencesMacro.xml, xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsCustomFiltersPreferencesMacro.xml, xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsEmailPreferencesMacro.xml, xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsFiltersPreferencesMacro.xml, xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsSystemFiltersPreferencesMacro.xml
Commit date: 2022-10-26 18:28:18 +0200
Commit message: XWIKI-20259: Improve escaping in Notification Preferences Macros

Diff: diff --git a/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsApplicationsPreferencesMacro.xml b/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsApplicationsPreferencesMacro.xml
index 3c97578f07499..ec1720cddf033 100644
--- a/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsApplicationsPreferencesMacro.xml
+++ b/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsApplicationsPreferencesMacro.xml
@@ -980,11 +980,11 @@
     #set ($targetUserReference = $wikimacro.parameters.user)
   #else
     #set ($targetUser = $xcontext.userReference)
     #set ($targetUserReference = $services.user.currentUserReference)
   #end
-  #set ($divData = "data-user=""$services.model.serialize($targetUser)""")
+  #set ($divData = "data-user=""$escapetool.xml($services.model.serialize($targetUser))""")
 #end
 #set ($userDoc = $xwiki.getDocument($targetUser))
 ######################################################
 ### MACRO CONTENT
 ######################################################
diff --git a/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsAutoWatchPreferencesMacro.xml b/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsAutoWatchPreferencesMacro.xml
index 38429f5b9d96c..6f718068eed88 100644
--- a/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsAutoWatchPreferencesMacro.xml
+++ b/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsAutoWatchPreferencesMacro.xml
@@ -389,11 +389,11 @@
   {{error}}
     {{translation key="notifications.settings.error.userReferenceNotSupported" /}}
   {{/error}}
 #elseif ($wikimacro.parameters.target == 'user' &amp;&amp; "$!wikimacro.parameters.user" != "" &amp;&amp; !$services.security.authorization.hasAccess('admin', $wikimacro.parameters.user.reference) &amp;&amp; !$xcontext.userReference.equals($wikimacro.parameters.user.reference))
   {{error}}
-    {{translation key="notifications.settings.error.userReferenceAdminForbidden" parameters="$wikimacro.parameters.user" /}}
+    {{translation key="notifications.settings.error.userReferenceAdminForbidden" parameters="~"${services.rendering.escape($escapetool.java($wikimacro.parameters.user), 'xwiki/2.1')}~"" /}}
   {{/error}}
 #else
 #set ($discard = $xwiki.jsx.use('XWiki.Notifications.Code.NotificationsAutoWatchPreferencesMacro'))
 #if ("$!wikimacro.parameters.user" != "")
     #set ($targetUser = $wikimacro.parameters.user.reference)
@@ -401,11 +401,11 @@
     #set ($targetUser = $xcontext.userReference)
 #end
 #set ($dataUser = "")
 #if ($wikimacro.parameters.target == 'user')
   #set ($mode = $services.notification.watch.getAutomaticWatchMode($targetUser))
-  #set ($dataUser = "data-user=""$services.model.serialize($targetUser)""")
+  #set ($dataUser = "data-user=""$escapetool.xml($services.model.serialize($targetUser))""")
 #else
   #set ($mode = $services.notification.watch.defaultAutomaticWatchMode)
 #end
 {{html clean="false"}}
   &lt;div class="xform"&gt;
diff --git a/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsCustomFiltersPreferencesMacro.xml b/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsCustomFiltersPreferencesMacro.xml
index 243c3f993d441..ea89fe557cb7b 100644
--- a/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsCustomFiltersPreferencesMacro.xml
+++ b/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsCustomFiltersPreferencesMacro.xml
@@ -1081,11 +1081,11 @@
   #if ("$!wikimacro.parameters.user" != "")
     #set ($targetUser = $wikimacro.parameters.user.reference)
   #else
     #set ($targetUser = $xcontext.userReference)
   #end
-  #set ($divData = "data-doc-url=""$escapetool.xml($services.rest.url($targetUser))"" data-user=""$services.model.serialize($targetUser)""")
+  #set ($divData = "data-doc-url=""$escapetool.xml($services.rest.url($targetUser))"" data-user=""$escapetool.xml($services.model.serialize($targetUser))""")
 #end
 ######################################################
 ### CSS and JAVASCRIPTS
 ######################################################
 #set ($discard = $xwiki.jsx.use('XWiki.Notifications.Code.NotificationsCustomFiltersPreferencesMacro'))
diff --git a/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsEmailPreferencesMacro.xml b/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsEmailPreferencesMacro.xml
index 12be2660fa6d5..247f0264cab8d 100644
--- a/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsEmailPreferencesMacro.xml
+++ b/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsEmailPreferencesMacro.xml
@@ -421,22 +421,22 @@
   {{error}}
     {{translation key="notifications.settings.error.userReferenceNotSupported" /}}
   {{/error}}
 #elseif ($wikimacro.parameters.target == 'user' &amp;&amp; "$!wikimacro.parameters.user" != "" &amp;&amp; !$services.security.authorization.hasAccess('admin', $wikimacro.parameters.user.reference) &amp;&amp; !$xcontext.userReference.equals($wikimacro.parameters.user.reference))
   {{error}}
-    {{translation key="notifications.settings.error.userReferenceAdminForbidden" parameters="$wikimacro.parameters.user" /}}
+    {{translation key="notifications.settings.error.userReferenceAdminForbidden" parameters="$~"${services.rendering.escape($escapetool.java($wikimacro.parameters.user), 'xwiki/2.1')}~"" /}}
   {{/error}}
 #else
   
   #if ("$!wikimacro.parameters.user" != "")
     #set ($targetUser = $wikimacro.parameters.user.reference)
   #else
     #set ($targetUser = $xcontext.userReference)
   #end
   #set ($dataUser = "")
   #if ($wikimacro.parameters.target == 'user')
-    #set ($dataUser = "data-user=""$services.model.serialize($targetUser)""")
+    #set ($dataUser = "data-user=""$escapetool.xml($services.model.serialize($targetUser))""")
   #end
   #set ($discard = $xwiki.jsx.use('XWiki.Notifications.Code.NotificationsEmailPreferencesMacro'))
   {{html clean="false"}}
     &lt;div class="notification-top-panel-preferences notifEmailPreferences" data-target="$escapetool.xml($wikimacro.parameters.target)" $dataUser&gt;
       &lt;div class="xform"&gt;
diff --git a/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsFiltersPreferencesMacro.xml b/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsFiltersPreferencesMacro.xml
index 061b01adb8cee..211d282f99c32 100644
--- a/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsFiltersPreferencesMacro.xml
+++ b/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsFiltersPreferencesMacro.xml
@@ -1048,15 +1048,15 @@
   {{/info}}
 ## FIXME: This check should not be needed with a proper API able to check rights on UserReference.
 ## This should be improved later with such API.
 #elseif ("$!wikimacro.parameters.user" != "" &amp;&amp; $wikimacro.parameters.user.class.simpleName != 'DocumentUserReference')
   {{error}}
-    This macro only allows to handle DocumentUserReference references and you specified a $wikimacro.parameters.user.class.simpleName reference.
+    This macro only allows to handle DocumentUserReference references and you specified a $services.rendering.escape($wikimacro.parameters.user.class.simpleName, 'xwiki/2.1') reference.
   {{/error}}
 #elseif ("$!wikimacro.parameters.user" != "" &amp;&amp; !$services.security.authorization.hasAccess('admin', $wikimacro.parameters.user.reference) &amp;&amp; !$xcontext.userReference.equals($wikimacro.parameters.user.reference))
   {{error}}
-    You don't have administration right on  $wikimacro.parameters.user.
+    You don't have administration right on $services.rendering.escape($wikimacro.parameters.user, 'xwiki/2.1').
   {{/error}}
 #else
 #set ($discard = $services.logging.deprecate("NotificationsFiltersPreferencesMacro", "This macro should not be used anymore in favor of SystemNotificationsFiltersPreferencesMacro and CustomNotificationsFiltersPreferencesMacro."))
 ## TODO: We should actually manipulate only UserReferences here.
 #if ("$!wikimacro.parameters.user" != "")
@@ -1073,11 +1073,12 @@
 #set ($discard = $xwiki.linkx.use($services.webjars.url('bootstrap-switch', 'css/bootstrap3/bootstrap-switch.min.css'), {'type': 'text/css', 'rel': 'stylesheet'}))
 ######################################################
 ### MACRO CONTENT
 ######################################################
 {{html clean="false"}}
-&lt;div class="filterPreferences xform" data-user-url="$escapetool.xml($services.rest.url($targetUser))" data-user="$services.model.serialize($targetUser)"&gt;
+&lt;div class="filterPreferences xform" data-user-url="$escapetool.xml($services.rest.url($targetUser))"
+  data-user="$escapetool.xml($services.model.serialize($targetUser))"&gt;
   &lt;div class="row"&gt;
     &lt;p class="xHint col-xs-12 col-sm-9 col-md-8 col-lg-9"&gt;
       $escapetool.xml($services.localization.render('notifications.settings.filters.preferences.hint'))
     &lt;/p&gt;
     &lt;div class="col-xs-12 col-sm-3 col-md-4 col-lg-3 text-right"&gt;
@@ -1107,11 +1108,12 @@
   #livetable("notificationFilterPreferencesLiveTable" $collist $colprops $options)
 &lt;/div&gt;
 ######################################################
 ### ADD FILTER MODAL
 ######################################################
-&lt;div class="modal fade" tabindex="-1" role="dialog" id="modal-add-filter-preference" data-user="$services.model.serialize($targetUser)"&gt;
+&lt;div class="modal fade" tabindex="-1" role="dialog" id="modal-add-filter-preference"
+  data-user="$escapetool.xml($services.model.serialize($targetUser))"&gt;
   &lt;div class="modal-dialog" role="document"&gt;
     &lt;div class="modal-content"&gt;
       &lt;div class="modal-header"&gt;
         &lt;button type="button" class="close" data-dismiss="modal" aria-label="Close"&gt;&lt;span aria-hidden="true"&gt;&amp;times;&lt;/span&gt;&lt;/button&gt;
         &lt;div class="modal-title"&gt;$escapetool.xml($services.localization.render('notifications.settings.addFilter'))&lt;/div&gt;
diff --git a/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsSystemFiltersPreferencesMacro.xml b/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsSystemFiltersPreferencesMacro.xml
index 5880eba543629..cd3e306aa4dc9 100644
--- a/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsSystemFiltersPreferencesMacro.xml
+++ b/xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-ui/src/main/resources/XWiki/Notifications/Code/NotificationsSystemFiltersPreferencesMacro.xml
@@ -843,11 +843,11 @@
   #if ("$!wikimacro.parameters.user" != "")
     #set ($targetUser = $wikimacro.parameters.user.reference)
   #else
     #set ($targetUser = $xcontext.userReference)
   #end
-  #set ($divData = "data-doc-url=""$escapetool.xml($services.rest.url($targetUser))"" data-user=""$services.model.serialize($targetUser)""")
+  #set ($divData = "data-doc-url=""$escapetool.xml($services.rest.url($targetUser))"" data-user=""$escapetool.xml($services.model.serialize($targetUser))""")
 #end
 ######################################################
 ### CSS and JAVASCRIPTS
 ######################################################
 #set ($discard = $xwiki.jsx.use('XWiki.Notifications.Code.NotificationsSystemFiltersPreferencesMacro'))

Vulnerable code:   #set ($divData = "data-user=""$services.model.serialize($targetUser)""")
    {{translation key="notifications.settings.error.userReferenceAdminForbidden" parameters="$wikimacro.parameters.user" /}}
  #set ($dataUser = "data-user=""$services.model.serialize($targetUser)""")
  #set ($divData = "data-doc-url=""$escapetool.xml($services.rest.url($targetUser))"" data-user=""$services.model.serialize($targetUser)""")
    {{translation key="notifications.settings.error.userReferenceAdminForbidden" parameters="$wikimacro.parameters.user" /}}
    #set ($dataUser = "data-user=""$services.model.serialize($targetUser)""")
    This macro only allows to handle DocumentUserReference references and you specified a $wikimacro.parameters.user.class.simpleName reference.
    You don't have administration right on  $wikimacro.parameters.user.
&lt;div class="filterPreferences xform" data-user-url="$escapetool.xml($services.rest.url($targetUser))" data-user="$services.model.serialize($targetUser)"&gt;
&lt;div class="modal fade" tabindex="-1" role="dialog" id="modal-add-filter-preference" data-user="$services.model.serialize($targetUser)"&gt;
  #set ($divData = "data-doc-url=""$escapetool.xml($services.rest.url($targetUser))"" data-user=""$services.model.serialize($targetUser)""")
Fixed code:   #set ($divData = "data-user=""$escapetool.xml($services.model.serialize($targetUser))""")
    {{translation key="notifications.settings.error.userReferenceAdminForbidden" parameters="~"${services.rendering.escape($escapetool.java($wikimacro.parameters.user), 'xwiki/2.1')}~"" /}}
  #set ($dataUser = "data-user=""$escapetool.xml($services.model.serialize($targetUser))""")
  #set ($divData = "data-doc-url=""$escapetool.xml($services.rest.url($targetUser))"" data-user=""$escapetool.xml($services.model.serialize($targetUser))""")
    {{translation key="notifications.settings.error.userReferenceAdminForbidden" parameters="$~"${services.rendering.escape($escapetool.java($wikimacro.parameters.user), 'xwiki/2.1')}~"" /}}
    #set ($dataUser = "data-user=""$escapetool.xml($services.model.serialize($targetUser))""")
    This macro only allows to handle DocumentUserReference references and you specified a $services.rendering.escape($wikimacro.parameters.user.class.simpleName, 'xwiki/2.1') reference.
    You don't have administration right on $services.rendering.escape($wikimacro.parameters.user, 'xwiki/2.1').
&lt;div class="filterPreferences xform" data-user-url="$escapetool.xml($services.rest.url($targetUser))"
  data-user="$escapetool.xml($services.model.serialize($targetUser))"&gt;
&lt;div class="modal fade" tabindex="-1" role="dialog" id="modal-add-filter-preference"
  data-user="$escapetool.xml($services.model.serialize($targetUser))"&gt;
  #set ($divData = "data-doc-url=""$escapetool.xml($services.rest.url($targetUser))"" data-user=""$escapetool.xml($services.model.serialize($targetUser))""")