CVE-2022-0821 (published 2022-03-11T00:15Z)

Improper Authorization in GitHub repository orchardcms/orchardcore prior to 1.3.0.

Severity: MEDIUM
CVSS v2 base score: 4.0 (AV:N/AC:L/Au:S/C:N/I:P/A:N)
CVSS v3 base score: 6.5, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N)

Weakness information:
cwe_id: NVD-CWE-Other
cwe_name: Other
description: NVD is only using a subset of CWE for mapping instead of the entire CWE, and the weakness type is not covered by that subset.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/orchardcms/orchardcore
commit_details: repo_url: https://github.com/orchardcms/orchardcore
author: Sébastien Ros
author_date: 2022-03-10 10:03:52-08:00
msg: Fix missing permission checks and encoding. (#11344)
repository: repo_url: https://github.com/orchardcms/orchardcore
repo_name: OrchardCMS/OrchardCore
description: Orchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.
repo_language: C#
owner: orchardcms
file_changes: filename: LocalizationSetContentPickerAdminController.cs
change_type: ModificationType.MODIFY
diff: @@ -1,6 +1,7 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using OrchardCore.Admin;
 using OrchardCore.ContentFields.Settings;
@@ -9,9 +10,11 @@ using OrchardCore.ContentLocalization;
 using OrchardCore.ContentManagement;
 using OrchardCore.ContentManagement.Metadata;
 using OrchardCore.ContentManagement.Records;
+using OrchardCore.Contents;
 using OrchardCore.Modules;
 using YesSql;
 using YesSql.Services;
+using IHttpContextAccessor = Microsoft.AspNetCore.Http.IHttpContextAccessor;
 
 namespace OrchardCore.ContentFields.Controllers
 {
@@ -23,18 +26,23 @@ namespace OrchardCore.ContentFields.Controllers
         private readonly IContentLocalizationManager _contentLocalizationManager;
         private readonly IContentManager _contentManager;
         private readonly ISession _session;
+        private readonly IAuthorizationService _authorizationService;
+        private readonly IHttpContextAccessor _httpContextAccessor;
 
         public LocalizationSetContentPickerAdminController(
             IContentDefinitionManager contentDefinitionManager,
             IContentLocalizationManager contentLocalizationManager,
             IContentManager contentManager,
-            ISession session
-            )
+            ISession session,
+            IAuthorizationService authorizationService,
+            IHttpContextAccessor httpContextAccessor)
         {
             _contentDefinitionManager = contentDefinitionManager;
             _contentLocalizationManager = contentLocalizationManager;
             _contentManager = contentManager;
             _session = session;
+            _authorizationService = authorizationService;
+            _httpContextAccessor = httpContextAccessor;
         }
 
         [HttpGet]
@@ -71,12 +79,15 @@ namespace OrchardCore.ContentFields.Controllers
 
             foreach (var contentItem in cleanedContentItems)
             {
-                results.Add(new VueMultiselectItemViewModel
+                if (await _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User, CommonPermissions.ViewContent, contentItem))
                 {
-                    Id = contentItem.Key, //localization set
-                    DisplayText = contentItem.Value.ToString(),
-                    HasPublished = await _contentManager.HasPublishedVersionAsync(contentItem.Value)
-                });
+                    results.Add(new VueMultiselectItemViewModel
+                    {
+                        Id = contentItem.Key, //localization set
+                        DisplayText = contentItem.Value.ToString(),
+                        HasPublished = await _contentManager.HasPublishedVersionAsync(contentItem.Value)
+                    });
+                }
             }
 
             return new ObjectResult(results);

programming_language: C#
filename: ContentController.cs
change_type: ModificationType.MODIFY
diff: @@ -1,10 +1,13 @@
 using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using OrchardCore.Admin;
 using OrchardCore.ContentManagement;
 using OrchardCore.ContentManagement.Display;
+using OrchardCore.Contents;
 using OrchardCore.DisplayManagement.ModelBinding;
 using YesSql;
+using IHttpContextAccessor = Microsoft.AspNetCore.Http.IHttpContextAccessor;
 
 namespace OrchardCore.Demo.Controllers
 {
@@ -14,17 +17,23 @@ namespace OrchardCore.Demo.Controllers
         private readonly IContentManager _contentManager;
         private readonly ISession _session;
         private readonly IUpdateModelAccessor _updateModelAccessor;
+        private readonly IAuthorizationService _authorizationService;
+        private readonly IHttpContextAccessor _httpContextAccessor;
 
         public ContentController(
             IContentManager contentManager,
             IContentItemDisplayManager contentDisplay,
             ISession session,
-            IUpdateModelAccessor updateModelAccessor)
+            IUpdateModelAccessor updateModelAccessor,
+            IAuthorizationService authorizationService,
+            IHttpContextAccessor httpContextAccessor)
         {
             _contentManager = contentManager;
             _contentDisplay = contentDisplay;
             _session = session;
             _updateModelAccessor = updateModelAccessor;
+            _authorizationService = authorizationService;
+            _httpContextAccessor = httpContextAccessor;
         }
 
         public async Task<ActionResult> Display(string contentItemId)
@@ -36,6 +45,11 @@ namespace OrchardCore.Demo.Controllers
                 return NotFound();
             }
 
+            if (!await _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User, CommonPermissions.ViewContent, contentItem))
+            {
+                return Forbid();
+            }
+
             var shape = await _contentDisplay.BuildDisplayAsync(contentItem, _updateModelAccessor.ModelUpdater);
             return View(shape);
         }
@@ -50,6 +64,11 @@ namespace OrchardCore.Demo.Controllers
                 return NotFound();
             }
 
+            if (!await _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User, CommonPermissions.EditContent, contentItem))
+            {
+                return Forbid();
+            }
+
             var shape = await _contentDisplay.BuildEditorAsync(contentItem, _updateModelAccessor.ModelUpdater, false);
             return View(shape);
         }
@@ -64,6 +83,11 @@ namespace OrchardCore.Demo.Controllers
                 return NotFound();
             }
 
+            if (!await _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User, CommonPermissions.EditContent, contentItem))
+            {
+                return Forbid();
+            }
+
             var shape = await _contentDisplay.UpdateEditorAsync(contentItem, _updateModelAccessor.ModelUpdater, false);
 
             if (!ModelState.IsValid)

programming_language: C#
filename: AdminController.cs
change_type: ModificationType.MODIFY
diff: @@ -112,6 +112,11 @@ namespace OrchardCore.Features.Controllers
         [HttpPost]
         public async Task<IActionResult> Disable(string id)
         {
+            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageFeatures))
+            {
+                return Forbid();
+            }
+
             var feature = (await _shellFeaturesManager.GetAvailableFeaturesAsync())
                 .FirstOrDefault(f => !f.IsTheme() && f.Id == id);
 
@@ -134,6 +139,11 @@ namespace OrchardCore.Features.Controllers
         [HttpPost]
         public async Task<IActionResult> Enable(string id)
         {
+            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageFeatures))
+            {
+                return Forbid();
+            }
+
             var feature = (await _shellFeaturesManager.GetAvailableFeaturesAsync())
                 .FirstOrDefault(f => !f.IsTheme() && f.Id == id);
 

programming_language: C#
filename: AdminController.cs
change_type: ModificationType.MODIFY
diff: @@ -85,6 +85,11 @@ namespace OrchardCore.Roles.Controllers
         [HttpPost]
         public async Task<IActionResult> Create(CreateRoleViewModel model)
         {
+            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageRoles))
+            {
+                return Forbid();
+            }
+
             if (ModelState.IsValid)
             {
                 model.RoleName = model.RoleName.Trim();

programming_language: C#
filename: SeoContentDriver.cs
change_type: ModificationType.MODIFY
diff: @@ -1,4 +1,6 @@
 using System;
+using System.Text.Encodings.Web;
+using System.Text.Json;
 using System.Threading.Tasks;
 using Microsoft.AspNetCore.Html;
 using OrchardCore.ContentManagement;
@@ -21,6 +23,7 @@ namespace OrchardCore.Seo.Drivers
         private readonly IPageTitleBuilder _pageTitleBuilder;
         private readonly IResourceManager _resourceManager;
         private readonly IShortcodeService _shortcodeService;
+        private readonly HtmlEncoder _htmlEncoder;
 
         private bool _primaryContentRendered { get; set; }
 
@@ -28,13 +31,15 @@ namespace OrchardCore.Seo.Drivers
             IContentManager contentManager,
             IPageTitleBuilder pageTitleBuilder,
             IResourceManager resourceManager,
-            IShortcodeService shortcodeService
+            IShortcodeService shortcodeService,
+            HtmlEncoder htmlEncoder
             )
         {
             _contentManager = contentManager;
             _pageTitleBuilder = pageTitleBuilder;
             _resourceManager = resourceManager;
             _shortcodeService = shortcodeService;
+            _htmlEncoder = htmlEncoder;
         }
 
         public override async Task<IDisplayResult> DisplayAsync(ContentItem contentItem, BuildDisplayContext context)
@@ -60,9 +65,14 @@ namespace OrchardCore.Seo.Drivers
                 return null;
             }
 
+            var shortCodeContext = new Context
+            {
+                ["ContentItem"] = contentItem
+            };
+
             if (!String.IsNullOrEmpty(aspect.PageTitle))
             {
-                _pageTitleBuilder.SetFixedTitle(new HtmlString(await RenderAsync(aspect.PageTitle, contentItem)));
+                _pageTitleBuilder.SetFixedTitle(new HtmlString(_htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.PageTitle, shortCodeContext))));
             }
 
             if (!String.IsNullOrEmpty(aspect.MetaDescription))
@@ -70,7 +80,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Name = "description",
-                    Content = await RenderAsync(aspect.MetaDescription, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.MetaDescription, shortCodeContext))
                 });
             }
 
@@ -79,7 +89,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Name = "keywords",
-                    Content = await RenderAsync(aspect.MetaKeywords, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.MetaKeywords, shortCodeContext))
                 });
             }
 
@@ -97,7 +107,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Name = "robots",
-                    Content = await RenderAsync(aspect.MetaRobots, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.MetaRobots, shortCodeContext))
                 });
             }
 
@@ -105,11 +115,11 @@ namespace OrchardCore.Seo.Drivers
             {
                 // Generate a new meta entry as the builder is preopulated.
                 _resourceManager.RegisterMeta(new MetaEntry(
-                    await RenderAsync(customMetaTag.Name, contentItem),
-                    await RenderAsync(customMetaTag.Property, contentItem),
-                    await RenderAsync(customMetaTag.Content, contentItem),
-                    await RenderAsync(customMetaTag.HttpEquiv, contentItem),
-                    await RenderAsync(customMetaTag.Charset, contentItem)));
+                    _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(customMetaTag.Name, shortCodeContext)),
+                    _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(customMetaTag.Property, shortCodeContext)),
+                    _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(customMetaTag.Content, shortCodeContext)),
+                    _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(customMetaTag.HttpEquiv, shortCodeContext)),
+                    _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(customMetaTag.Charset, shortCodeContext))));
             }
 
             // OpenGraph.
@@ -118,7 +128,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Property = "og:type",
-                    Content = await RenderAsync(aspect.OpenGraphType, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphType, shortCodeContext))
                 });
             }
 
@@ -127,7 +137,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Property = "og:title",
-                    Content = await RenderAsync(aspect.OpenGraphTitle, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphTitle, shortCodeContext))
                 });
             }
 
@@ -136,7 +146,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Property = "og:description",
-                    Content = await RenderAsync(aspect.OpenGraphDescription, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphDescription, shortCodeContext))
                 });
             }
 
@@ -145,7 +155,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Property = "og:image",
-                    Content = await RenderAsync(aspect.OpenGraphImage, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphImage, shortCodeContext))
                 });
             }
 
@@ -154,7 +164,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Property = "og:image:alt",
-                    Content = await RenderAsync(aspect.OpenGraphImageAlt, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphImageAlt, shortCodeContext))
                 });
             }
 
@@ -163,7 +173,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Property = "og:url",
-                    Content = await RenderAsync(aspect.OpenGraphUrl, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphUrl, shortCodeContext))
                 });
             }
 
@@ -172,7 +182,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Property = "og:site_name",
-                    Content = await RenderAsync(aspect.OpenGraphSiteName, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphSiteName, shortCodeContext))
                 });
             }
 
@@ -181,7 +191,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Property = "fb:app_id",
-                    Content = await RenderAsync(aspect.OpenGraphAppId, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphAppId, shortCodeContext))
                 });
             }
 
@@ -190,7 +200,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Property = "og:locale",
-                    Content = await RenderAsync(aspect.OpenGraphLocale, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphLocale, shortCodeContext))
                 });
             }
 
@@ -200,7 +210,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Property = "twitter:card",
-                    Content = await RenderAsync(aspect.TwitterCard, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterCard, shortCodeContext))
                 });
             }
 
@@ -209,7 +219,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Property = "twitter:site",
-                    Content = await RenderAsync(aspect.TwitterSite, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterSite, shortCodeContext))
                 });
             }
 
@@ -218,7 +228,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Name = "twitter:title",
-                    Content = await RenderAsync(aspect.TwitterTitle, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterTitle, shortCodeContext))
                 });
             }
 
@@ -227,7 +237,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Name = "twitter:description",
-                    Content = await RenderAsync(aspect.TwitterDescription, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterDescription, shortCodeContext))
                 });
             }
 
@@ -236,7 +246,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Name = "twitter:image",
-                    Content = await RenderAsync(aspect.TwitterImage, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterImage, shortCodeContext))
                 });
             }
 
@@ -245,7 +255,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Name = "twitter:image:alt",
-                    Content = await RenderAsync(aspect.TwitterImageAlt, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterImageAlt, shortCodeContext))
                 });
             }
 
@@ -254,7 +264,7 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Name = "twitter:creator",
-                    Content = await RenderAsync(aspect.TwitterCreator, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterCreator, shortCodeContext))
                 });
             }
 
@@ -263,23 +273,29 @@ namespace OrchardCore.Seo.Drivers
                 _resourceManager.RegisterMeta(new MetaEntry
                 {
                     Name = "twitter:url",
-                    Content = await RenderAsync(aspect.TwitterUrl, contentItem)
+                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterUrl, shortCodeContext))
                 });
             }
 
             if (!String.IsNullOrEmpty(aspect.GoogleSchema))
             {
-                _resourceManager.RegisterHeadScript(new HtmlString($"<script type=\"application/ld+json\">\n{aspect.GoogleSchema}\n</script>"));
+                var json = await _shortcodeService.ProcessAsync(aspect.GoogleSchema, shortCodeContext);
+
+                try
+                {
+                    // Validate json format
+                    JsonDocument.Parse(json);
+                }
+                catch
+                {
+                    json = "{ \"error\": \"Invalid JSON content in SEO settings\" }";
+                }
+
+                _resourceManager.RegisterHeadScript(new HtmlString($"<script type=\"application/ld+json\">\n{json}\n</script>"));
+
             }
 
             return null;
         }
-
-        private ValueTask<string> RenderAsync(string template, ContentItem contentItem)
-            => _shortcodeService.ProcessAsync(template,
-                    new Context
-                    {
-                        ["ContentItem"] = contentItem
-                    });
     }
 }

programming_language: C#
filename: AdminController.cs
change_type: ModificationType.MODIFY
diff: @@ -11,6 +11,7 @@ using Microsoft.Extensions.Localization;
 using Newtonsoft.Json;
 using OrchardCore.DisplayManagement;
 using OrchardCore.DisplayManagement.Notify;
+using OrchardCore.Infrastructure.Html;
 using OrchardCore.Liquid;
 using OrchardCore.Modules;
 using OrchardCore.Navigation;
@@ -33,6 +34,7 @@ namespace OrchardCore.Shortcodes.Controllers
         private readonly INotifier _notifier;
         private readonly IStringLocalizer S;
         private readonly IHtmlLocalizer H;
+        private readonly IHtmlSanitizerService _htmlSanitizerService;
         private readonly dynamic New;
 
         public AdminController(
@@ -43,7 +45,8 @@ namespace OrchardCore.Shortcodes.Controllers
             INotifier notifier,
             IShapeFactory shapeFactory,
             IStringLocalizer<AdminController> stringLocalizer,
-            IHtmlLocalizer<AdminController> htmlLocalizer
+            IHtmlLocalizer<AdminController> htmlLocalizer,
+            IHtmlSanitizerService htmlSanitizerService
             )
         {
             _authorizationService = authorizationService;
@@ -54,6 +57,7 @@ namespace OrchardCore.Shortcodes.Controllers
             New = shapeFactory;
             S = stringLocalizer;
             H = htmlLocalizer;
+            _htmlSanitizerService = htmlSanitizerService;
         }
 
         public async Task<IActionResult> Index(ContentOptions options, PagerParameters pagerParameters)
@@ -159,7 +163,7 @@ namespace OrchardCore.Shortcodes.Controllers
                 {
                     Content = model.Content,
                     Hint = model.Hint,
-                    Usage = model.Usage,
+                    Usage = _htmlSanitizerService.Sanitize(model.Usage),
                     DefaultValue = model.DefaultValue,
                     Categories = JsonConvert.DeserializeObject<string[]>(model.SelectedCategories)
                 };
@@ -256,7 +260,7 @@ namespace OrchardCore.Shortcodes.Controllers
                 {
                     Content = model.Content,
                     Hint = model.Hint,
-                    Usage = model.Usage,
+                    Usage = _htmlSanitizerService.Sanitize(model.Usage),
                     DefaultValue = model.DefaultValue,
                     Categories = JsonConvert.DeserializeObject<string[]>(model.SelectedCategories)
                 };

programming_language: C#
filename: FeatureProfilesController.cs
change_type: ModificationType.MODIFY
diff: @@ -40,8 +40,8 @@ namespace OrchardCore.Tenants.Controllers
             ISiteService siteService,
             INotifier notifier,
             IShapeFactory shapeFactory,
-            IStringLocalizer<AdminController> stringLocalizer,
-            IHtmlLocalizer<AdminController> htmlLocalizer
+            IStringLocalizer<FeatureProfilesController> stringLocalizer,
+            IHtmlLocalizer<FeatureProfilesController> htmlLocalizer
             )
         {
             _authorizationService = authorizationService;

programming_language: C#