CVE-2023-49337: Insufficient Information (NVD-CWE-noinfo)
value: Concrete CMS before 9.2.3 allows Stored XSS on the Admin Dashboard via /dashboard/system/basics/name. (8.5 and earlier are unaffected.)
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-02-29T01:41Z
Repository: https://github.com/concretecms/concretecms
Language: PHP
Files changed: concrete/attributes/site/controller.php, concrete/authentication/concrete/controller.php, concrete/blocks/top_navigation_bar/controller.php, concrete/controllers/single_page/dashboard/system/multisite/sites.php, concrete/controllers/single_page/dashboard/system/seo/bulk.php, concrete/controllers/single_page/register.php, concrete/elements/header_required.php, concrete/single_pages/dashboard/system/express/entities/view_details.php, concrete/single_pages/login.php, concrete/src/Application/UserInterface/Sitemap/TreeCollection/Entry/Group/SiteGroup.php, concrete/src/Application/UserInterface/Sitemap/TreeCollection/Entry/SiteEntry.php, concrete/src/Entity/Attribute/Value/Value/SiteValue.php, concrete/src/Entity/Site/SiteTree.php, concrete/src/Form/Service/Widget/SiteSelector.php, concrete/src/Install/InstallerOptions.php
Commit date: 2023-11-09 15:29:12 -0800
Commit message: Sanitize site name everywhere

Diff: diff --git a/concrete/attributes/site/controller.php b/concrete/attributes/site/controller.php
index 5271011a18..70dd5fba80 100644
--- a/concrete/attributes/site/controller.php
+++ b/concrete/attributes/site/controller.php
@@ -54,21 +54,21 @@ public function form()
         if (is_object($this->getValue())) {
             $siteID = $this->getValue()->getSiteID();
         }
         $sites = array('' => t('** Select Site'));
         foreach($this->app->make('site')->getList() as $site) {
-            $sites[$site->getSiteID()] = $site->getSiteName();
+            $sites[$site->getSiteID()] = h($site->getSiteName());
         }
         $form = $this->app->make('helper/form');
         print $form->select($this->field('siteID'), $sites, $siteID);
     }
 
     public function getDisplayValue()
     {
         $site = $this->getValue();
         if (is_object($site)) {
-            return $site->getSiteName();
+            return h($site->getSiteName());
         }
     }
 
 	public function createAttributeValue($site)
 	{
diff --git a/concrete/authentication/concrete/controller.php b/concrete/authentication/concrete/controller.php
index af98566c39..3c73eea5ec 100644
--- a/concrete/authentication/concrete/controller.php
+++ b/concrete/authentication/concrete/controller.php
@@ -293,11 +293,11 @@ private function passwordUpgrade(?UserInfo $userInfo, ErrorList $error, bool $is
                 if ($fromName === '') {
                     $fromName = $isForgotPassword ? t('Forgot Password') : t('Password Reset');
                 }
                 $mh->from($fromEmail, $fromName);
             }
-            $mh->addParameter('siteName', tc('SiteName', $this->app->make('site')->getSite()->getSiteName()));
+            $mh->addParameter('siteName', h(tc('SiteName', $this->app->make('site')->getSite()->getSiteName())));
             $mh->load('forgot_password');
             $mh->setIsThrowOnFailure(true);
             try {
                 $mh->sendMail();
             } catch (Throwable $x) {
diff --git a/concrete/blocks/top_navigation_bar/controller.php b/concrete/blocks/top_navigation_bar/controller.php
index c057de33ca..4f9c9e2f5e 100644
--- a/concrete/blocks/top_navigation_bar/controller.php
+++ b/concrete/blocks/top_navigation_bar/controller.php
@@ -124,11 +124,11 @@ public function getRequiredFeatures(): array
     }
 
     public function add()
     {
         $site = $this->app->make('site')->getSite();
-        $brandingText = $site->getSiteName();
+        $brandingText = h($site->getSiteName());
         /** @var Detector $detector */
         $detector = $this->app->make('multilingual/detector');
 
         $this->set('includeTransparency', false);
         $this->set('includeStickyNav', false);
@@ -248,11 +248,11 @@ public function view()
         if (!isset($logo)) {
             $this->set('logo', null);
         }
         if ($this->includeBrandText && !$this->brandingText) {
             $site = $this->app->make('site')->getSite();
-            $brandingText = $site->getSiteName();
+            $brandingText = h($site->getSiteName());
             $this->set('brandingText', $brandingText);
         }
         if ($this->brandingTransparentLogo) {
             $transparentLogo = File::getByID($this->brandingTransparentLogo);
             if ($transparentLogo) {
diff --git a/concrete/controllers/single_page/dashboard/system/multisite/sites.php b/concrete/controllers/single_page/dashboard/system/multisite/sites.php
index 12902c4ab8..7173f80a4a 100644
--- a/concrete/controllers/single_page/dashboard/system/multisite/sites.php
+++ b/concrete/controllers/single_page/dashboard/system/multisite/sites.php
@@ -216,11 +216,11 @@ protected function setCurrentSite(?Site $site): void
         $this->set('site', $site);
         if ($site === null || $site->getSiteID() === null) {
             $menu = null;
         } else {
             $breadcrumb = $this->app->make(DashboardBreadcrumbFactory::class)->getBreadcrumb($this->getPageObject());
-            $breadcrumb->add(new Item('', $site->getSiteName()));
+            $breadcrumb->add(new Item('', h($site->getSiteName())));
             $this->setBreadcrumb($breadcrumb);
             $menu = new Element('dashboard/system/multisite/site/menu', '', $this->getPageObject(), ['site' => $site]);
         }
         $this->set('siteMenu', $menu);
     }
diff --git a/concrete/controllers/single_page/dashboard/system/seo/bulk.php b/concrete/controllers/single_page/dashboard/system/seo/bulk.php
index d623fee670..240a8a131d 100644
--- a/concrete/controllers/single_page/dashboard/system/seo/bulk.php
+++ b/concrete/controllers/single_page/dashboard/system/seo/bulk.php
@@ -114,11 +114,11 @@ protected function getSiteNameForPage(Page $page): string
             } else {
                 $locale = $defaultLocale;
             }
             $siteName = $this->getSiteNameForLocale($locale);
         } else {
-            $siteName = $this->app->make('site')->getSite()->getSiteName();
+            $siteName = h($this->app->make('site')->getSite()->getSiteName());
         }
 
         return $siteName;
     }
 
diff --git a/concrete/controllers/single_page/register.php b/concrete/controllers/single_page/register.php
index 1fb1c16666..9a5ac38e50 100644
--- a/concrete/controllers/single_page/register.php
+++ b/concrete/controllers/single_page/register.php
@@ -167,11 +167,11 @@ public function do_register()
                     foreach ($attribs as $ak) {
                         $attribValues[] = $ak->getAttributeKeyDisplayName('text') . ': ' . $process->getAttribute($ak->getAttributeKeyHandle(),
                                 'display');
                     }
                     $mh->addParameter('attribs', $attribValues);
-                    $mh->addParameter('siteName', tc('SiteName', \Core::make('site')->getSite()->getSiteName()));
+                    $mh->addParameter('siteName', h(tc('SiteName', \Core::make('site')->getSite()->getSiteName())));
 
                     if ($config->get('concrete.email.register_notification.address')) {
                         if ($config->get('concrete.email.register_notification.name')) {
                             $fromName = $config->get('concrete.email.register_notification.name');
                         } else {
diff --git a/concrete/elements/header_required.php b/concrete/elements/header_required.php
index c973db3b67..069dd1a113 100644
--- a/concrete/elements/header_required.php
+++ b/concrete/elements/header_required.php
@@ -59,11 +59,11 @@
                 if ($c->isSystemPage()) {
                     $pageTitle = t($pageTitle);
                 }
                 $seo->addTitleSegmentBefore($pageTitle);
             }
-            $seo->setSiteName(tc('SiteName', $site->getSiteName()));
+            $seo->setSiteName(h(tc('SiteName', $site->getSiteName())));
             $seo->setTitleFormat($appConfig->get('concrete.seo.title_format'));
             $seo->setTitleSegmentSeparator($appConfig->get('concrete.seo.title_segment_separator'));
             $pageTitle = $seo->getTitle();
         }
     }
diff --git a/concrete/single_pages/dashboard/system/express/entities/view_details.php b/concrete/single_pages/dashboard/system/express/entities/view_details.php
index 27d3edd05f..da44f17b4d 100644
--- a/concrete/single_pages/dashboard/system/express/entities/view_details.php
+++ b/concrete/single_pages/dashboard/system/express/entities/view_details.php
@@ -114,11 +114,11 @@
 
                 <tbody>
                 <?php foreach ($sites as $site) { ?>
                     <tr>
                         <td>
-                            <?php echo $site->getSiteName() ?>
+                            <?php echo h($site->getSiteName()); ?>
                         </td>
 
                         <td style="white-space: nowrap" class="text-center">
                             <?php
                             $siteResultsNode = $resultsNode->getSiteResultsNode($site);
diff --git a/concrete/single_pages/login.php b/concrete/single_pages/login.php
index 2df84e6adf..4cb860c8f3 100644
--- a/concrete/single_pages/login.php
+++ b/concrete/single_pages/login.php
@@ -24,11 +24,11 @@
 
 $attribute_mode = (isset($required_attributes) && count($required_attributes));
 $site = app('site')->getSite() ?? null;
 $siteName = '';
 if ($site) {
-    $siteName = $site->getSiteName();
+    $siteName = h($site->getSiteName());
 }
 
 ?>
 
 <div class="login-page">
diff --git a/concrete/src/Application/UserInterface/Sitemap/TreeCollection/Entry/Group/SiteGroup.php b/concrete/src/Application/UserInterface/Sitemap/TreeCollection/Entry/Group/SiteGroup.php
index cbd7839fb3..5d3c732a3a 100644
--- a/concrete/src/Application/UserInterface/Sitemap/TreeCollection/Entry/Group/SiteGroup.php
+++ b/concrete/src/Application/UserInterface/Sitemap/TreeCollection/Entry/Group/SiteGroup.php
@@ -13,11 +13,11 @@ public function __construct(Site $site)
         $this->site = $site;
     }
 
     public function getEntryGroupLabel()
     {
-        return $this->site->getSiteName();
+        return h($this->site->getSiteName());
     }
 
     public function getEntryGroupIdentifier()
     {
         return $this->site->getSiteID();
diff --git a/concrete/src/Application/UserInterface/Sitemap/TreeCollection/Entry/SiteEntry.php b/concrete/src/Application/UserInterface/Sitemap/TreeCollection/Entry/SiteEntry.php
index 7dab3a285b..67ecf17dc1 100644
--- a/concrete/src/Application/UserInterface/Sitemap/TreeCollection/Entry/SiteEntry.php
+++ b/concrete/src/Application/UserInterface/Sitemap/TreeCollection/Entry/SiteEntry.php
@@ -17,11 +17,11 @@ public function __construct(Site $site)
         $this->site = $site;
     }
 
     public function getLabel()
     {
-        return $this->site->getSiteName();
+        return h($this->site->getSiteName());
     }
 
     public function getSiteTreeID()
     {
         return $this->site->getSiteTreeID();
diff --git a/concrete/src/Entity/Attribute/Value/Value/SiteValue.php b/concrete/src/Entity/Attribute/Value/Value/SiteValue.php
index 8178e79cb2..cb95ac38d6 100644
--- a/concrete/src/Entity/Attribute/Value/Value/SiteValue.php
+++ b/concrete/src/Entity/Attribute/Value/Value/SiteValue.php
@@ -37,10 +37,10 @@ public function getValue()
     }
 
     public function __toString()
     {
         if (is_object($this->site)) {
-            return (string) $this->site->getSiteName();
+            return (string) h($this->site->getSiteName());
         }
         return '';
     }
 }
diff --git a/concrete/src/Entity/Site/SiteTree.php b/concrete/src/Entity/Site/SiteTree.php
index e7d501f606..50978cf7cc 100644
--- a/concrete/src/Entity/Site/SiteTree.php
+++ b/concrete/src/Entity/Site/SiteTree.php
@@ -47,9 +47,9 @@ public function getSiteType()
         return $this->getLocale()->getSite()->getType();
     }
 
     public function getDisplayName()
     {
-        return $this->getLocale()->getSite()->getSiteName();
+        return h($this->getLocale()->getSite()->getSiteName());
     }
 
 }
diff --git a/concrete/src/Form/Service/Widget/SiteSelector.php b/concrete/src/Form/Service/Widget/SiteSelector.php
index f10737e449..2d95383d95 100644
--- a/concrete/src/Form/Service/Widget/SiteSelector.php
+++ b/concrete/src/Form/Service/Widget/SiteSelector.php
@@ -31,11 +31,11 @@ public function selectSite($fieldName, $siteID = false, $includeCurrent = false,
 
         $sites = '';
         foreach(\Core::make('site')->getList() as $site) {
             $sp = new \Permissions($site);
             if ($sp->canViewSiteInSelector()) {
-                $sites .= '<option ' . ($site->getSiteID() == $siteID ? 'selected' : '') . ' value="' . $site->getSiteID() . '">' . $site->getSiteName() . '</option>';
+                $sites .= '<option ' . ($site->getSiteID() == $siteID ? 'selected' : '') . ' value="' . $site->getSiteID() . '">' . h($site->getSiteName()) . '</option>';
             }
         }
 
         $currentLine = '';
         $allLine = '';
diff --git a/concrete/src/Install/InstallerOptions.php b/concrete/src/Install/InstallerOptions.php
index 72f77c32be..c4fe1cc12a 100644
--- a/concrete/src/Install/InstallerOptions.php
+++ b/concrete/src/Install/InstallerOptions.php
@@ -249,11 +249,11 @@ public function setStartingPointHandle($value)
      *
      * @return string
      */
     public function getSiteName()
     {
-        return $this->siteName;
+        return h($this->siteName);
     }
 
     /**
      * Get the name of the site.
      *

Vulnerable code:             $sites[$site->getSiteID()] = $site->getSiteName();
            return $site->getSiteName();
            $mh->addParameter('siteName', tc('SiteName', $this->app->make('site')->getSite()->getSiteName()));
        $brandingText = $site->getSiteName();
            $brandingText = $site->getSiteName();
            $breadcrumb->add(new Item('', $site->getSiteName()));
            $siteName = $this->app->make('site')->getSite()->getSiteName();
                    $mh->addParameter('siteName', tc('SiteName', \Core::make('site')->getSite()->getSiteName()));
            $seo->setSiteName(tc('SiteName', $site->getSiteName()));
                            <?php echo $site->getSiteName() ?>
    $siteName = $site->getSiteName();
        return $this->site->getSiteName();
        return $this->site->getSiteName();
            return (string) $this->site->getSiteName();
        return $this->getLocale()->getSite()->getSiteName();
                $sites .= '<option ' . ($site->getSiteID() == $siteID ? 'selected' : '') . ' value="' . $site->getSiteID() . '">' . $site->getSiteName() . '</option>';
        return $this->siteName;
Fixed code:             $sites[$site->getSiteID()] = h($site->getSiteName());
            return h($site->getSiteName());
            $mh->addParameter('siteName', h(tc('SiteName', $this->app->make('site')->getSite()->getSiteName())));
        $brandingText = h($site->getSiteName());
            $brandingText = h($site->getSiteName());
            $breadcrumb->add(new Item('', h($site->getSiteName())));
            $siteName = h($this->app->make('site')->getSite()->getSiteName());
                    $mh->addParameter('siteName', h(tc('SiteName', \Core::make('site')->getSite()->getSiteName())));
            $seo->setSiteName(h(tc('SiteName', $site->getSiteName())));
                            <?php echo h($site->getSiteName()); ?>
    $siteName = h($site->getSiteName());
        return h($this->site->getSiteName());
        return h($this->site->getSiteName());
            return (string) h($this->site->getSiteName());
        return h($this->getLocale()->getSite()->getSiteName());
                $sites .= '<option ' . ($site->getSiteID() == $siteID ? 'selected' : '') . ' value="' . $site->getSiteID() . '">' . h($site->getSiteName()) . '</option>';
        return h($this->siteName);