1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-04 17:42:49 -05: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:
Rui Tomé
2024-03-05 10:56:48 +00:00
committed by GitHub
parent 997af0f6ab
commit 9d59e4dc9e
49 changed files with 312 additions and 79 deletions

View File

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Text.Json;
using Bit.Core.Auth.Enums;
using Bit.Core.Auth.Models;
@ -17,8 +18,14 @@ public class Organization : ITableObject<Guid>, IStorableSubscriber, IRevisable,
public Guid Id { get; set; }
[MaxLength(50)]
public string Identifier { get; set; }
/// <summary>
/// This value is HTML encoded. For display purposes use the method DisplayName() instead.
/// </summary>
[MaxLength(50)]
public string Name { get; set; }
/// <summary>
/// This value is HTML encoded. For display purposes use the method DisplayBusinessName() instead.
/// </summary>
[MaxLength(50)]
public string BusinessName { get; set; }
[MaxLength(50)]
@ -104,6 +111,22 @@ public class Organization : ITableObject<Guid>, IStorableSubscriber, IRevisable,
}
}
/// <summary>
/// Returns the name of the organization, HTML decoded ready for display.
/// </summary>
public string DisplayName()
{
return WebUtility.HtmlDecode(Name);
}
/// <summary>
/// Returns the business name of the organization, HTML decoded ready for display.
/// </summary>
public string DisplayBusinessName()
{
return WebUtility.HtmlDecode(BusinessName);
}
public string BillingEmailAddress()
{
return BillingEmail?.ToLowerInvariant()?.Trim();
@ -111,12 +134,12 @@ public class Organization : ITableObject<Guid>, IStorableSubscriber, IRevisable,
public string BillingName()
{
return BusinessName;
return DisplayBusinessName();
}
public string SubscriberName()
{
return Name;
return DisplayName();
}
public string BraintreeCustomerIdPrefix()

View File

@ -1,4 +1,5 @@
using Bit.Core.AdminConsole.Enums.Provider;
using System.Net;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.Entities;
using Bit.Core.Utilities;
@ -7,7 +8,13 @@ namespace Bit.Core.AdminConsole.Entities.Provider;
public class Provider : ITableObject<Guid>
{
public Guid Id { get; set; }
/// <summary>
/// This value is HTML encoded. For display purposes use the method DisplayName() instead.
/// </summary>
public string Name { get; set; }
/// <summary>
/// This value is HTML encoded. For display purposes use the method DisplayBusinessName() instead.
/// </summary>
public string BusinessName { get; set; }
public string BusinessAddress1 { get; set; }
public string BusinessAddress2 { get; set; }
@ -30,4 +37,20 @@ public class Provider : ITableObject<Guid>
Id = CoreHelpers.GenerateComb();
}
}
/// <summary>
/// Returns the name of the provider, HTML decoded ready for display.
/// </summary>
public string DisplayName()
{
return WebUtility.HtmlDecode(Name);
}
/// <summary>
/// Returns the business name of the provider, HTML decoded ready for display.
/// </summary>
public string DisplayBusinessName()
{
return WebUtility.HtmlDecode(BusinessName);
}
}

View File

@ -1,4 +1,6 @@
using Bit.Core.AdminConsole.Enums.Provider;
using System.Text.Json.Serialization;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.Utilities;
namespace Bit.Core.Models.Data.Organizations.OrganizationUsers;
@ -6,6 +8,7 @@ public class OrganizationUserOrganizationDetails
{
public Guid OrganizationId { get; set; }
public Guid? UserId { get; set; }
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string Name { get; set; }
public bool UsePolicies { get; set; }
public bool UseSso { get; set; }
@ -37,6 +40,7 @@ public class OrganizationUserOrganizationDetails
public string PublicKey { get; set; }
public string PrivateKey { get; set; }
public Guid? ProviderId { get; set; }
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string ProviderName { get; set; }
public ProviderType? ProviderType { get; set; }
public string FamilySponsorshipFriendlyName { get; set; }

View File

@ -1,4 +1,7 @@
using Bit.Core.Enums;
using System.Net;
using System.Text.Json.Serialization;
using Bit.Core.Enums;
using Bit.Core.Utilities;
namespace Bit.Core.AdminConsole.Models.Data.Provider;
@ -7,6 +10,10 @@ public class ProviderOrganizationOrganizationDetails
public Guid Id { get; set; }
public Guid ProviderId { get; set; }
public Guid OrganizationId { get; set; }
/// <summary>
/// This value is HTML encoded. For display purposes use the method DisplayName() instead.
/// </summary>
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string OrganizationName { get; set; }
public string Key { get; set; }
public string Settings { get; set; }
@ -16,4 +23,12 @@ public class ProviderOrganizationOrganizationDetails
public int? Seats { get; set; }
public string Plan { get; set; }
public OrganizationStatusType Status { get; set; }
/// <summary>
/// Returns the name of the organization, HTML decoded ready for display.
/// </summary>
public string DisplayName()
{
return WebUtility.HtmlDecode(OrganizationName);
}
}

View File

@ -1,4 +1,6 @@
using Bit.Core.AdminConsole.Enums.Provider;
using System.Text.Json.Serialization;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.Utilities;
namespace Bit.Core.AdminConsole.Models.Data.Provider;
@ -7,6 +9,7 @@ public class ProviderOrganizationProviderDetails
public Guid Id { get; set; }
public Guid ProviderId { get; set; }
public Guid OrganizationId { get; set; }
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string ProviderName { get; set; }
public ProviderType ProviderType { get; set; }
}

View File

@ -1,4 +1,6 @@
using Bit.Core.AdminConsole.Enums.Provider;
using System.Text.Json.Serialization;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.Utilities;
namespace Bit.Core.AdminConsole.Models.Data.Provider;
@ -6,6 +8,7 @@ public class ProviderUserOrganizationDetails
{
public Guid OrganizationId { get; set; }
public Guid? UserId { get; set; }
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string Name { get; set; }
public bool UsePolicies { get; set; }
public bool UseSso { get; set; }
@ -33,6 +36,7 @@ public class ProviderUserOrganizationDetails
public string PrivateKey { get; set; }
public Guid? ProviderId { get; set; }
public Guid? ProviderUserId { get; set; }
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string ProviderName { get; set; }
public Core.Enums.PlanType PlanType { get; set; }
public bool LimitCollectionCreationDeletion { get; set; }

View File

@ -1,4 +1,6 @@
using Bit.Core.AdminConsole.Enums.Provider;
using System.Text.Json.Serialization;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.Utilities;
namespace Bit.Core.AdminConsole.Models.Data.Provider;
@ -6,6 +8,7 @@ public class ProviderUserProviderDetails
{
public Guid ProviderId { get; set; }
public Guid? UserId { get; set; }
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string Name { get; set; }
public string Key { get; set; }
public ProviderUserStatusType Status { get; set; }

View File

@ -1,4 +1,6 @@
using Bit.Core.AdminConsole.Enums.Provider;
using System.Text.Json.Serialization;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.Utilities;
namespace Bit.Core.AdminConsole.Models.Data.Provider;
@ -7,6 +9,7 @@ public class ProviderUserUserDetails
public Guid Id { get; set; }
public Guid ProviderId { get; set; }
public Guid? UserId { get; set; }
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string Name { get; set; }
public string Email { get; set; }
public ProviderUserStatusType Status { get; set; }

View File

@ -828,7 +828,7 @@ public class OrganizationService : IOrganizationService
await customerService.UpdateAsync(organization.GatewayCustomerId, new CustomerUpdateOptions
{
Email = organization.BillingEmail,
Description = organization.BusinessName
Description = organization.DisplayBusinessName()
});
}
}
@ -1285,7 +1285,7 @@ public class OrganizationService : IOrganizationService
orgUser.Email = null;
await _eventService.LogOrganizationUserEventAsync(orgUser, EventType.OrganizationUser_Confirmed);
await _mailService.SendOrganizationConfirmedEmailAsync(organization.Name, user.Email);
await _mailService.SendOrganizationConfirmedEmailAsync(organization.DisplayName(), user.Email);
await DeleteAndPushUserRegistrationAsync(organizationId, user.Id);
succeededUsers.Add(orgUser);
result.Add(Tuple.Create(orgUser, ""));

View File

@ -131,7 +131,7 @@ public class PolicyService : IPolicyService
await organizationService.DeleteUserAsync(policy.OrganizationId, orgUser.Id,
savingUserId);
await _mailService.SendOrganizationUserRemovedForPolicyTwoStepEmailAsync(
org.Name, orgUser.Email);
org.DisplayName(), orgUser.Email);
}
}
break;
@ -147,7 +147,7 @@ public class PolicyService : IPolicyService
await organizationService.DeleteUserAsync(policy.OrganizationId, orgUser.Id,
savingUserId);
await _mailService.SendOrganizationUserRemovedForPolicySingleOrgEmailAsync(
org.Name, orgUser.Email);
org.DisplayName(), orgUser.Email);
}
}
break;