Merge pull request #3549 from sbwalker/dev
HTML encode notifications sent by non-admins to prevent HTML injection
This commit is contained in:
commit
3793f618a8
|
@ -442,7 +442,7 @@
|
||||||
_homepageid = site.HomePageId.Value.ToString();
|
_homepageid = site.HomePageId.Value.ToString();
|
||||||
}
|
}
|
||||||
_isdeleted = site.IsDeleted.ToString();
|
_isdeleted = site.IsDeleted.ToString();
|
||||||
_sitemap = PageState.Alias.Protocol + PageState.Alias.Name + "/pages/sitemap.xml";
|
_sitemap = PageState.Alias.Protocol + PageState.Alias.Name + "/sitemap.xml";
|
||||||
_siteguid = site.SiteGuid;
|
_siteguid = site.SiteGuid;
|
||||||
_version = site.Version;
|
_version = site.Version;
|
||||||
|
|
||||||
|
|
|
@ -162,7 +162,8 @@
|
||||||
if (PageState == null || refresh || PageState.Alias.SiteId != SiteState.Alias.SiteId)
|
if (PageState == null || refresh || PageState.Alias.SiteId != SiteState.Alias.SiteId)
|
||||||
{
|
{
|
||||||
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
||||||
if (authState.User.Identity.IsAuthenticated)
|
// verify user is authenticated for current site
|
||||||
|
if (authState.User.Identity.IsAuthenticated && authState.User.Claims.Any(item => item.Type == "sitekey" && item.Value == SiteState.Alias.SiteKey))
|
||||||
{
|
{
|
||||||
user = await UserService.GetUserAsync(authState.User.Identity.Name, SiteState.Alias.SiteId);
|
user = await UserService.GetUserAsync(authState.User.Identity.Name, SiteState.Alias.SiteId);
|
||||||
if (user != null)
|
if (user != null)
|
||||||
|
|
|
@ -88,8 +88,8 @@
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
// force user to provide email address (email may be missing if using external login)
|
// force authenticated user to provide email address (email may be missing if using external login)
|
||||||
if (PageState.User != null && string.IsNullOrEmpty(PageState.User.Email) && PageState.Route.PagePath != "profile")
|
if (PageState.User != null && PageState.User.IsAuthenticated && string.IsNullOrEmpty(PageState.User.Email) && PageState.Route.PagePath != "profile")
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(Utilities.NavigateUrl(PageState.Alias.Path, "profile", "returnurl=" + WebUtility.UrlEncode(PageState.Route.PathAndQuery)));
|
NavigationManager.NavigateTo(Utilities.NavigateUrl(PageState.Alias.Path, "profile", "returnurl=" + WebUtility.UrlEncode(PageState.Route.PathAndQuery)));
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -161,6 +161,12 @@ namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
if (ModelState.IsValid && notification.SiteId == _alias.SiteId && IsAuthorized(notification.FromUserId))
|
if (ModelState.IsValid && notification.SiteId == _alias.SiteId && IsAuthorized(notification.FromUserId))
|
||||||
{
|
{
|
||||||
|
if (!User.IsInRole(RoleNames.Admin))
|
||||||
|
{
|
||||||
|
// content must be HTML encoded for non-admins to prevent HTML injection
|
||||||
|
notification.Subject = WebUtility.HtmlEncode(notification.Subject);
|
||||||
|
notification.Body = WebUtility.HtmlEncode(notification.Body);
|
||||||
|
}
|
||||||
notification = _notifications.AddNotification(notification);
|
notification = _notifications.AddNotification(notification);
|
||||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Notification, notification.NotificationId, SyncEventActions.Create);
|
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Notification, notification.NotificationId, SyncEventActions.Create);
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Notification Added {NotificationId}", notification.NotificationId);
|
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Notification Added {NotificationId}", notification.NotificationId);
|
||||||
|
@ -181,6 +187,12 @@ namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
if (ModelState.IsValid && notification.SiteId == _alias.SiteId && notification.NotificationId == id && _notifications.GetNotification(notification.NotificationId, false) != null && (IsAuthorized(notification.FromUserId) || IsAuthorized(notification.ToUserId)))
|
if (ModelState.IsValid && notification.SiteId == _alias.SiteId && notification.NotificationId == id && _notifications.GetNotification(notification.NotificationId, false) != null && (IsAuthorized(notification.FromUserId) || IsAuthorized(notification.ToUserId)))
|
||||||
{
|
{
|
||||||
|
if (!User.IsInRole(RoleNames.Admin))
|
||||||
|
{
|
||||||
|
// content must be HTML encoded for non-admins to prevent HTML injection
|
||||||
|
notification.Subject = WebUtility.HtmlEncode(notification.Subject);
|
||||||
|
notification.Body = WebUtility.HtmlEncode(notification.Body);
|
||||||
|
}
|
||||||
notification = _notifications.UpdateNotification(notification);
|
notification = _notifications.UpdateNotification(notification);
|
||||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Notification, notification.NotificationId, SyncEventActions.Update);
|
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Notification, notification.NotificationId, SyncEventActions.Update);
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Notification Updated {NotificationId}", notification.NotificationId);
|
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Notification Updated {NotificationId}", notification.NotificationId);
|
||||||
|
|
|
@ -58,21 +58,21 @@ namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
if (path.StartsWith("/" + alias.Path) && (Constants.ReservedRoutes.Any(item => path.Contains("/" + item + "/"))))
|
if (path.StartsWith("/" + alias.Path) && (Constants.ReservedRoutes.Any(item => path.Contains("/" + item + "/"))))
|
||||||
{
|
{
|
||||||
context.Request.Path = path.Replace("/" + alias.Path, "");
|
context.Request.Path = path.Substring(alias.Path.Length + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle sitemap.xml root request (does not support subfolder aliases)
|
// handle sitemap.xml request
|
||||||
if (context.Request.Path.StartsWithSegments("/sitemap.xml"))
|
if (context.Request.Path.ToString().Contains("/sitemap.xml") && !context.Request.Path.ToString().Contains("/pages"))
|
||||||
{
|
{
|
||||||
context.Request.Path = "/pages" + context.Request.Path;
|
context.Request.Path = "/pages/sitemap.xml";
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle robots.txt root request (does not support subfolder aliases)
|
// handle robots.txt root request (does not support subfolder aliases)
|
||||||
if (context.Request.Path.StartsWithSegments("/robots.txt"))
|
if (context.Request.Path.StartsWithSegments("/robots.txt") && string.IsNullOrEmpty(alias.Path))
|
||||||
{
|
{
|
||||||
// allow all and specify site map
|
// allow all user agents and specify site map
|
||||||
var robots = $"User-agent: *\n\nSitemap: {context.Request.Scheme}://{alias.Name}/pages/sitemap.xml";
|
var robots = $"User-agent: *\n\nSitemap: {context.Request.Scheme}://{alias.Name}/sitemap.xml";
|
||||||
context.Response.ContentType = "text/plain";
|
context.Response.ContentType = "text/plain";
|
||||||
await context.Response.WriteAsync(robots);
|
await context.Response.WriteAsync(robots);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -53,7 +53,8 @@ namespace Oqtane.Pages
|
||||||
{
|
{
|
||||||
if (_userPermissions.IsAuthorized(null, PermissionNames.View, page.PermissionList) && page.IsNavigation)
|
if (_userPermissions.IsAuthorized(null, PermissionNames.View, page.PermissionList) && page.IsNavigation)
|
||||||
{
|
{
|
||||||
sitemap.Add(new Sitemap { Url = _alias.Protocol + _alias.Name + Utilities.NavigateUrl(_alias.Path, page.Path, ""), ModifiedOn = DateTime.UtcNow });
|
var rooturl = _alias.Protocol + (string.IsNullOrEmpty(_alias.Path) ? _alias.Name : _alias.Name.Substring(0, _alias.Name.IndexOf("/")));
|
||||||
|
sitemap.Add(new Sitemap { Url = rooturl + Utilities.NavigateUrl(_alias.Path, page.Path, ""), ModifiedOn = DateTime.UtcNow });
|
||||||
|
|
||||||
foreach (var pageModule in pageModules.Where(item => item.PageId == page.PageId))
|
foreach (var pageModule in pageModules.Where(item => item.PageId == page.PageId))
|
||||||
{
|
{
|
||||||
|
@ -72,7 +73,7 @@ namespace Oqtane.Pages
|
||||||
var urls = ((ISitemap)moduleobject).GetUrls(_alias.Path, page.Path, pageModule.Module);
|
var urls = ((ISitemap)moduleobject).GetUrls(_alias.Path, page.Path, pageModule.Module);
|
||||||
foreach (var url in urls)
|
foreach (var url in urls)
|
||||||
{
|
{
|
||||||
sitemap.Add(new Sitemap { Url = _alias.Protocol + _alias.Name + url.Url, ModifiedOn = DateTime.UtcNow });
|
sitemap.Add(new Sitemap { Url = rooturl + url.Url, ModifiedOn = DateTime.UtcNow });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace Oqtane.Security
|
||||||
var claims = context.Principal.Claims;
|
var claims = context.Principal.Claims;
|
||||||
|
|
||||||
// check if principal has roles and matches current site
|
// check if principal has roles and matches current site
|
||||||
if (!claims.Any(item => item.Type == ClaimTypes.Role) || claims.FirstOrDefault(item => item.Type == "sitekey")?.Value != alias.SiteKey)
|
if (!claims.Any(item => item.Type == ClaimTypes.Role) || claims.Any(item => item.Type == "sitekey" && item.Value == alias.SiteKey))
|
||||||
{
|
{
|
||||||
var userRepository = context.HttpContext.RequestServices.GetService(typeof(IUserRepository)) as IUserRepository;
|
var userRepository = context.HttpContext.RequestServices.GetService(typeof(IUserRepository)) as IUserRepository;
|
||||||
var userRoleRepository = context.HttpContext.RequestServices.GetService(typeof(IUserRoleRepository)) as IUserRoleRepository;
|
var userRoleRepository = context.HttpContext.RequestServices.GetService(typeof(IUserRoleRepository)) as IUserRoleRepository;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user