mirror of
https://github.com/bitwarden/server
synced 2026-01-03 17:14:00 +00:00
[AC-1637] Sanitize Business and Organization Names from html script injection prior to storing in db (#3302)
* [AC-1637] Added HtmlEncodingStringConverter to encode/decode special chars on JSON serialization/deserialization
* [AC-1637] Added unit tests for HtmlEncodingStringConverter
* [AC-1637] Moved expected values on unit tests to the arrange phase
* [AC-1637] Added HtmlEncodingStringConverter to properties that are for input/output of Org Name and Business name
* [AC-1637] Modified views in Admin project to decode values to display
* [AC-1637] Replaced Html.Raw with HttpUtility.HtmlDecode
* [AC-1637] Added JsonConverter to Provider DTOs
* [AC-1637] Modified HandlebarsMailService to decode organization name before sending emails
* Revert "[AC-1637] Added JsonConverter to Provider DTOs"
This reverts commit 94d507cf93.
* [AC-1637] Fixed Admin panel organization search
* [AC-1637] Sanitizing Organization name and business name on creation in Admin panel
* [AC-1637] Sanitizing organization name and business name on creation by a provider
* [AC-1637] Sanitizing provider name on creation and on viewing in admin panel
* [AC-1637] Added sanitization to more places where Org name is used
* [AC-1637] Swapped using HttpUtility for WebUtility since the later is part of the dotnet framework
* [AC-1637] Updated error messages
* [AC-1637] Decoding on Admin panel add existing organization
* [AC-1637] Fix HTML decoding issues
* [AC-1637] Refactor HTML decoding in View and Model classes on Admin panel
* [AC-1637] Refactor provider name and business name usages to use methods that output decoded values
* [AC-1637] Fixed typo
* [AC-1637] Renamed Provider methods to retrieve Decoded Name and BusinessName
* [AC-1637] Renamed Organization methods to retrieve Decoded Name and BusinessName
* [AC-1637] Update the display name method in the `ProviderOrganizationOrganizationDetails` class to `DisplayName()`
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Bit.Admin.AdminConsole.Models;
|
||||
using System.Net;
|
||||
using Bit.Admin.AdminConsole.Models;
|
||||
using Bit.Admin.Enums;
|
||||
using Bit.Admin.Services;
|
||||
using Bit.Admin.Utilities;
|
||||
@@ -119,8 +120,9 @@ public class OrganizationsController : Controller
|
||||
count = 1;
|
||||
}
|
||||
|
||||
var encodedName = WebUtility.HtmlEncode(name);
|
||||
var skip = (page - 1) * count;
|
||||
var organizations = await _organizationRepository.SearchAsync(name, userEmail, paid, skip, count);
|
||||
var organizations = await _organizationRepository.SearchAsync(encodedName, userEmail, paid, skip, count);
|
||||
return View(new OrganizationsModel
|
||||
{
|
||||
Items = organizations as List<Organization>,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Bit.Admin.AdminConsole.Models;
|
||||
using System.Net;
|
||||
using Bit.Admin.AdminConsole.Models;
|
||||
using Bit.Admin.Enums;
|
||||
using Bit.Admin.Utilities;
|
||||
using Bit.Core;
|
||||
@@ -188,8 +189,9 @@ public class ProvidersController : Controller
|
||||
count = 1;
|
||||
}
|
||||
|
||||
var encodedName = WebUtility.HtmlEncode(name);
|
||||
var skip = (page - 1) * count;
|
||||
var unassignedOrganizations = await _organizationRepository.SearchUnassignedToProviderAsync(name, ownerEmail, skip, count);
|
||||
var unassignedOrganizations = await _organizationRepository.SearchUnassignedToProviderAsync(encodedName, ownerEmail, skip, count);
|
||||
var viewModel = new OrganizationUnassignedToProviderSearchViewModel
|
||||
{
|
||||
OrganizationName = string.IsNullOrWhiteSpace(name) ? null : name,
|
||||
@@ -199,7 +201,7 @@ public class ProvidersController : Controller
|
||||
Items = unassignedOrganizations.Select(uo => new OrganizationSelectableViewModel
|
||||
{
|
||||
Id = uo.Id,
|
||||
Name = uo.Name,
|
||||
Name = uo.DisplayName(),
|
||||
PlanType = uo.PlanType
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Net;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Entities.Provider;
|
||||
using Bit.Core.AdminConsole.Enums.Provider;
|
||||
@@ -36,8 +37,8 @@ public class OrganizationEditModel : OrganizationViewModel
|
||||
BillingInfo = billingInfo;
|
||||
BraintreeMerchantId = globalSettings.Braintree.MerchantId;
|
||||
|
||||
Name = org.Name;
|
||||
BusinessName = org.BusinessName;
|
||||
Name = org.DisplayName();
|
||||
BusinessName = org.DisplayBusinessName();
|
||||
BillingEmail = provider?.Type == ProviderType.Reseller ? provider.BillingEmail : org.BillingEmail;
|
||||
PlanType = org.PlanType;
|
||||
Plan = org.Plan;
|
||||
@@ -184,8 +185,8 @@ public class OrganizationEditModel : OrganizationViewModel
|
||||
|
||||
public Organization ToOrganization(Organization existingOrganization)
|
||||
{
|
||||
existingOrganization.Name = Name;
|
||||
existingOrganization.BusinessName = BusinessName;
|
||||
existingOrganization.Name = WebUtility.HtmlEncode(Name.Trim());
|
||||
existingOrganization.BusinessName = WebUtility.HtmlEncode(BusinessName.Trim());
|
||||
existingOrganization.BillingEmail = BillingEmail?.ToLowerInvariant()?.Trim();
|
||||
existingOrganization.PlanType = PlanType.Value;
|
||||
existingOrganization.Plan = Plan;
|
||||
|
||||
@@ -11,8 +11,8 @@ public class ProviderEditModel : ProviderViewModel
|
||||
public ProviderEditModel(Provider provider, IEnumerable<ProviderUserUserDetails> providerUsers, IEnumerable<ProviderOrganizationOrganizationDetails> organizations)
|
||||
: base(provider, providerUsers, organizations)
|
||||
{
|
||||
Name = provider.Name;
|
||||
BusinessName = provider.BusinessName;
|
||||
Name = provider.DisplayName();
|
||||
BusinessName = provider.DisplayBusinessName();
|
||||
BillingEmail = provider.BillingEmail;
|
||||
BillingPhone = provider.BillingPhone;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
@inject Bit.Admin.Services.IAccessControlService AccessControlService
|
||||
@model OrganizationEditModel
|
||||
@{
|
||||
ViewData["Title"] = (Model.Provider != null ? "Client " : string.Empty) + "Organization: " + Model.Organization.Name;
|
||||
ViewData["Title"] = (Model.Provider != null ? "Client " : string.Empty) + "Organization: " + Model.Name;
|
||||
|
||||
var canViewOrganizationInformation = AccessControlService.UserHasPermission(Permission.Org_OrgInformation_View);
|
||||
var canViewBillingInformation = AccessControlService.UserHasPermission(Permission.Org_BillingInformation_View);
|
||||
@@ -58,7 +58,7 @@
|
||||
</script>
|
||||
}
|
||||
|
||||
<h1>@(Model.Provider != null ? "Client " : string.Empty)Organization <small>@Model.Organization.Name</small></h1>
|
||||
<h1>@(Model.Provider != null ? "Client " : string.Empty)Organization <small>@Model.Name</small></h1>
|
||||
|
||||
@if (Model.Provider != null)
|
||||
{
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<a asp-action="@Model.Action" asp-route-id="@org.Id">@org.Name</a>
|
||||
<a asp-action="@Model.Action" asp-route-id="@org.Id">@org.DisplayName()</a>
|
||||
</td>
|
||||
<td>
|
||||
@org.Plan
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
@inject Bit.Core.Settings.GlobalSettings GlobalSettings
|
||||
@model OrganizationViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Organization: " + Model.Organization.Name;
|
||||
ViewData["Title"] = "Organization: " + Model.Organization.DisplayName();
|
||||
}
|
||||
|
||||
<h1>Organization <small>@Model.Organization.Name</small></h1>
|
||||
<h1>Organization <small>@Model.Organization.DisplayName()</small></h1>
|
||||
|
||||
@if (Model.Provider != null)
|
||||
{
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
@model Bit.Core.AdminConsole.Entities.Provider.Provider
|
||||
<dl class="row">
|
||||
<dt class="col-sm-4 col-lg-3">Provider Name</dt>
|
||||
<dd class="col-sm-8 col-lg-9">@Model.Name</dd>
|
||||
|
||||
<dd class="col-sm-8 col-lg-9">@Model.DisplayName()</dd>
|
||||
|
||||
<dt class="col-sm-4 col-lg-3">Provider Type</dt>
|
||||
<dd class="col-sm-8 col-lg-9">@(Model.Type.GetDisplayAttribute()?.GetName())</dd>
|
||||
</dl>
|
||||
</dl>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
@Html.HiddenFor(m => Model.Items[i].Id, new { @readonly = "readonly", autocomplete = "off" })
|
||||
@Html.CheckBoxFor(m => Model.Items[i].Selected)
|
||||
</td>
|
||||
<td>@Html.ActionLink(Model.Items[i].Name, "Edit", "Organizations", new { id = Model.Items[i].Id }, new { target = "_blank" })</td>
|
||||
<td>@Html.ActionLink(Model.Items[i].DisplayName(), "Edit", "Organizations", new { id = Model.Items[i].Id }, new { target = "_blank" })</td>
|
||||
<td>@(Model.Items[i].PlanType.GetDisplayAttribute()?.Name ?? Model.Items[i].PlanType.ToString())</td>
|
||||
</tr>
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
@model ProviderEditModel
|
||||
@{
|
||||
ViewData["Title"] = "Provider: " + Model.Provider.Name;
|
||||
ViewData["Title"] = "Provider: " + Model.Provider.DisplayName();
|
||||
|
||||
var canEdit = AccessControlService.UserHasPermission(Permission.Provider_Edit);
|
||||
}
|
||||
|
||||
<h1>Provider <small>@Model.Provider.Name</small></h1>
|
||||
<h1>Provider <small>@Model.Provider.DisplayName()</small></h1>
|
||||
|
||||
<h2>Provider Information</h2>
|
||||
@await Html.PartialAsync("_ViewInformation", Model)
|
||||
@@ -17,12 +17,12 @@
|
||||
<h2>General</h2>
|
||||
<dl class="row">
|
||||
<dt class="col-sm-4 col-lg-3">Name</dt>
|
||||
<dd class="col-sm-8 col-lg-9">@Model.Provider.Name</dd>
|
||||
<dd class="col-sm-8 col-lg-9">@Model.Provider.DisplayName()</dd>
|
||||
</dl>
|
||||
<h2>Business Information</h2>
|
||||
<dl class="row">
|
||||
<dt class="col-sm-4 col-lg-3">Business Name</dt>
|
||||
<dd class="col-sm-8 col-lg-9">@Model.Provider.BusinessName</dd>
|
||||
<dd class="col-sm-8 col-lg-9">@Model.Provider.DisplayBusinessName()</dd>
|
||||
</dl>
|
||||
<h2>Billing</h2>
|
||||
<div class="row">
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<a asp-action="@Model.Action" asp-route-id="@provider.Id">@(provider.Name ?? "Pending")</a>
|
||||
<a asp-action="@Model.Action" asp-route-id="@provider.Id">@(!string.IsNullOrEmpty(provider.DisplayName()) ? provider.DisplayName() : "Pending")</a>
|
||||
</td>
|
||||
<td>@provider.Type.GetDisplayAttribute()?.GetShortName()</td>
|
||||
<td>@provider.Status</td>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
{
|
||||
<tr>
|
||||
<td class="align-middle">
|
||||
<a asp-controller="Organizations" asp-action="Edit" asp-route-id="@providerOrganization.OrganizationId">@providerOrganization.OrganizationName</a>
|
||||
<a asp-controller="Organizations" asp-action="Edit" asp-route-id="@providerOrganization.OrganizationId">@providerOrganization.DisplayName()</a>
|
||||
</td>
|
||||
<td>
|
||||
@providerOrganization.Status
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
@model ProviderViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Provider: " + Model.Provider.Name;
|
||||
ViewData["Title"] = "Provider: " + Model.Provider.DisplayName();
|
||||
}
|
||||
|
||||
<h1>Provider <small>@Model.Provider.Name</small></h1>
|
||||
<h1>Provider <small>@Model.Provider.DisplayName()</small></h1>
|
||||
|
||||
<h2>Information</h2>
|
||||
@await Html.PartialAsync("_ViewInformation", Model)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<div class="col-sm">
|
||||
<div class="form-group">
|
||||
<label asp-for="Name"></label>
|
||||
<input type="text" class="form-control" asp-for="Name" required>
|
||||
<input type="text" class="form-control" asp-for="Name" value="@Model.Name" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -68,7 +68,7 @@
|
||||
<div class="col-sm">
|
||||
<div class="form-group">
|
||||
<label asp-for="BusinessName"></label>
|
||||
<input type="text" class="form-control" asp-for="BusinessName">
|
||||
<input type="text" class="form-control" asp-for="BusinessName" value="@Model.BusinessName">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user