CVE-2022-0822 (C#, published 2022-03-11T01:15Z)
Description: value: Cross-site Scripting (XSS) - Reflected in GitHub repository orchardcms/orchardcore prior to 1.3.0.
Severity: LOW (CVSS v3 base score: 5.4)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/orchardcms/orchardcore
Files changed:
src/OrchardCore.Modules/OrchardCore.ContentFields/Controllers/LocalizationSetContentPickerAdminController.cs
src/OrchardCore.Modules/OrchardCore.Demo/Controllers/ContentController.cs
src/OrchardCore.Modules/OrchardCore.Features/Controllers/AdminController.cs
src/OrchardCore.Modules/OrchardCore.Roles/Controllers/AdminController.cs
src/OrchardCore.Modules/OrchardCore.Seo/Drivers/SeoContentDriver.cs
src/OrchardCore.Modules/OrchardCore.Shortcodes/Controllers/AdminController.cs
src/OrchardCore.Modules/OrchardCore.Tenants/Controllers/FeatureProfilesController.cs
Commit message: Fix missing permission checks and encoding. (#11344)



Vulnerable code:
            ISession session
            )
                results.Add(new VueMultiselectItemViewModel
                    Id = contentItem.Key, //localization set
                    DisplayText = contentItem.Value.ToString(),
                    HasPublished = await _contentManager.HasPublishedVersionAsync(contentItem.Value)
                });
            IUpdateModelAccessor updateModelAccessor)
            IShortcodeService shortcodeService
                _pageTitleBuilder.SetFixedTitle(new HtmlString(await RenderAsync(aspect.PageTitle, contentItem)));
                    Content = await RenderAsync(aspect.MetaDescription, contentItem)
                    Content = await RenderAsync(aspect.MetaKeywords, contentItem)
                    Content = await RenderAsync(aspect.MetaRobots, contentItem)
                    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)));
                    Content = await RenderAsync(aspect.OpenGraphType, contentItem)
                    Content = await RenderAsync(aspect.OpenGraphTitle, contentItem)
                    Content = await RenderAsync(aspect.OpenGraphDescription, contentItem)
                    Content = await RenderAsync(aspect.OpenGraphImage, contentItem)
                    Content = await RenderAsync(aspect.OpenGraphImageAlt, contentItem)
                    Content = await RenderAsync(aspect.OpenGraphUrl, contentItem)
                    Content = await RenderAsync(aspect.OpenGraphSiteName, contentItem)
                    Content = await RenderAsync(aspect.OpenGraphAppId, contentItem)
                    Content = await RenderAsync(aspect.OpenGraphLocale, contentItem)
                    Content = await RenderAsync(aspect.TwitterCard, contentItem)
                    Content = await RenderAsync(aspect.TwitterSite, contentItem)
                    Content = await RenderAsync(aspect.TwitterTitle, contentItem)
                    Content = await RenderAsync(aspect.TwitterDescription, contentItem)
                    Content = await RenderAsync(aspect.TwitterImage, contentItem)
                    Content = await RenderAsync(aspect.TwitterImageAlt, contentItem)
                    Content = await RenderAsync(aspect.TwitterCreator, contentItem)
                    Content = await RenderAsync(aspect.TwitterUrl, contentItem)
                _resourceManager.RegisterHeadScript(new HtmlString($"<script type=\"application/ld+json\">\n{aspect.GoogleSchema}\n</script>"));

        private ValueTask<string> RenderAsync(string template, ContentItem contentItem)
            => _shortcodeService.ProcessAsync(template,
                    new Context
                    {
                        ["ContentItem"] = contentItem
                    });
            IHtmlLocalizer<AdminController> htmlLocalizer
                    Usage = model.Usage,
                    Usage = model.Usage,
            IStringLocalizer<AdminController> stringLocalizer,
            IHtmlLocalizer<AdminController> htmlLocalizer

Fixed code:
using Microsoft.AspNetCore.Authorization;
using OrchardCore.Contents;
using IHttpContextAccessor = Microsoft.AspNetCore.Http.IHttpContextAccessor;
        private readonly IAuthorizationService _authorizationService;
        private readonly IHttpContextAccessor _httpContextAccessor;
            ISession session,
            IAuthorizationService authorizationService,
            IHttpContextAccessor httpContextAccessor)
            _authorizationService = authorizationService;
            _httpContextAccessor = httpContextAccessor;
                if (await _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User, CommonPermissions.ViewContent, contentItem))
                    results.Add(new VueMultiselectItemViewModel
                    {
                        Id = contentItem.Key, //localization set
                        DisplayText = contentItem.Value.ToString(),
                        HasPublished = await _contentManager.HasPublishedVersionAsync(contentItem.Value)
                    });
                }
using Microsoft.AspNetCore.Authorization;
using OrchardCore.Contents;
using IHttpContextAccessor = Microsoft.AspNetCore.Http.IHttpContextAccessor;
        private readonly IAuthorizationService _authorizationService;
        private readonly IHttpContextAccessor _httpContextAccessor;
            IUpdateModelAccessor updateModelAccessor,
            IAuthorizationService authorizationService,
            IHttpContextAccessor httpContextAccessor)
            _authorizationService = authorizationService;
            _httpContextAccessor = httpContextAccessor;
            if (!await _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User, CommonPermissions.ViewContent, contentItem))
            {
                return Forbid();
            }

            if (!await _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User, CommonPermissions.EditContent, contentItem))
            {
                return Forbid();
            }

            if (!await _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User, CommonPermissions.EditContent, contentItem))
            {
                return Forbid();
            }

            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageFeatures))
            {
                return Forbid();
            }

            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageFeatures))
            {
                return Forbid();
            }

            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageRoles))
            {
                return Forbid();
            }

using System.Text.Encodings.Web;
using System.Text.Json;
        private readonly HtmlEncoder _htmlEncoder;
            IShortcodeService shortcodeService,
            HtmlEncoder htmlEncoder
            _htmlEncoder = htmlEncoder;
            var shortCodeContext = new Context
            {
                ["ContentItem"] = contentItem
            };

                _pageTitleBuilder.SetFixedTitle(new HtmlString(_htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.PageTitle, shortCodeContext))));
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.MetaDescription, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.MetaKeywords, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.MetaRobots, shortCodeContext))
                    _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))));
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphType, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphTitle, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphDescription, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphImage, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphImageAlt, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphUrl, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphSiteName, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphAppId, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphLocale, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterCard, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterSite, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterTitle, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterDescription, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterImage, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterImageAlt, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterCreator, shortCodeContext))
                    Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterUrl, shortCodeContext))
                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>"));

using OrchardCore.Infrastructure.Html;
        private readonly IHtmlSanitizerService _htmlSanitizerService;
            IHtmlLocalizer<AdminController> htmlLocalizer,
            IHtmlSanitizerService htmlSanitizerService
            _htmlSanitizerService = htmlSanitizerService;
                    Usage = _htmlSanitizerService.Sanitize(model.Usage),
                    Usage = _htmlSanitizerService.Sanitize(model.Usage),
            IStringLocalizer<FeatureProfilesController> stringLocalizer,
            IHtmlLocalizer<FeatureProfilesController> htmlLocalizer