1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-03 00:52: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

@ -303,7 +303,7 @@ public class OrganizationsController : Controller
throw new NotFoundException();
}
var updateBilling = !_globalSettings.SelfHosted && (model.BusinessName != organization.BusinessName ||
var updateBilling = !_globalSettings.SelfHosted && (model.BusinessName != organization.DisplayBusinessName() ||
model.BillingEmail != organization.BillingEmail);
var hasRequiredPermissions = updateBilling

View File

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Models.Business;
@ -9,9 +10,11 @@ namespace Bit.Api.AdminConsole.Models.Request.Organizations;
public class OrganizationCreateRequestModel : IValidatableObject
{
[Required]
[StringLength(50)]
[StringLength(50, ErrorMessage = "The field Name exceeds the maximum length.")]
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string Name { get; set; }
[StringLength(50)]
[StringLength(50, ErrorMessage = "The field Business Name exceeds the maximum length.")]
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string BusinessName { get; set; }
[Required]
[StringLength(256)]

View File

@ -1,16 +1,20 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using Bit.Core.AdminConsole.Entities;
using Bit.Core.Models.Data;
using Bit.Core.Settings;
using Bit.Core.Utilities;
namespace Bit.Api.AdminConsole.Models.Request.Organizations;
public class OrganizationUpdateRequestModel
{
[Required]
[StringLength(50)]
[StringLength(50, ErrorMessage = "The field Name exceeds the maximum length.")]
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string Name { get; set; }
[StringLength(50)]
[StringLength(50, ErrorMessage = "The field Business Name exceeds the maximum length.")]
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string BusinessName { get; set; }
[EmailAddress]
[Required]

View File

@ -1,14 +1,18 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.Utilities;
namespace Bit.Api.AdminConsole.Models.Request.Providers;
public class ProviderSetupRequestModel
{
[Required]
[StringLength(50)]
[StringLength(50, ErrorMessage = "The field Name exceeds the maximum length.")]
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string Name { get; set; }
[StringLength(50)]
[StringLength(50, ErrorMessage = "The field Business Name exceeds the maximum length.")]
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string BusinessName { get; set; }
[Required]
[StringLength(256)]

View File

@ -1,15 +1,19 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.Settings;
using Bit.Core.Utilities;
namespace Bit.Api.AdminConsole.Models.Request.Providers;
public class ProviderUpdateRequestModel
{
[Required]
[StringLength(50)]
[StringLength(50, ErrorMessage = "The field Name exceeds the maximum length.")]
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string Name { get; set; }
[StringLength(50)]
[StringLength(50, ErrorMessage = "The field Business Name exceeds the maximum length.")]
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string BusinessName { get; set; }
[EmailAddress]
[Required]

View File

@ -1,4 +1,5 @@
using Bit.Api.Models.Response;
using System.Text.Json.Serialization;
using Bit.Api.Models.Response;
using Bit.Core.AdminConsole.Entities;
using Bit.Core.Enums;
using Bit.Core.Models.Api;
@ -60,7 +61,9 @@ public class OrganizationResponseModel : ResponseModel
}
public Guid Id { get; set; }
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string Name { get; set; }
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string BusinessName { get; set; }
public string BusinessAddress1 { get; set; }
public string BusinessAddress2 { get; set; }

View File

@ -1,4 +1,5 @@
using Bit.Core.AdminConsole.Enums.Provider;
using System.Text.Json.Serialization;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.Auth.Enums;
using Bit.Core.Auth.Models.Data;
using Bit.Core.Enums;
@ -103,6 +104,7 @@ public class ProfileOrganizationResponseModel : ResponseModel
}
public Guid Id { get; set; }
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string Name { get; set; }
public bool UsePolicies { get; set; }
public bool UseSso { get; set; }
@ -135,6 +137,7 @@ public class ProfileOrganizationResponseModel : ResponseModel
public Guid? UserId { get; set; }
public bool HasPublicAndPrivateKeys { 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,5 @@
using Bit.Core.AdminConsole.Enums.Provider;
using System.Text.Json.Serialization;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.AdminConsole.Models.Data.Provider;
using Bit.Core.Models.Api;
using Bit.Core.Models.Data;
@ -23,6 +24,7 @@ public class ProfileProviderResponseModel : ResponseModel
}
public Guid Id { get; set; }
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string Name { get; set; }
public string Key { get; set; }
public ProviderUserStatusType Status { get; set; }

View File

@ -1,6 +1,8 @@
using Bit.Core.AdminConsole.Entities.Provider;
using System.Text.Json.Serialization;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Models.Data.Provider;
using Bit.Core.Models.Api;
using Bit.Core.Utilities;
namespace Bit.Api.AdminConsole.Models.Response.Providers;
@ -68,5 +70,6 @@ public class ProviderOrganizationOrganizationDetailsResponseModel : ProviderOrga
OrganizationName = providerOrganization.OrganizationName;
}
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string OrganizationName { get; set; }
}

View File

@ -1,5 +1,7 @@
using Bit.Core.AdminConsole.Entities.Provider;
using System.Text.Json.Serialization;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.Models.Api;
using Bit.Core.Utilities;
namespace Bit.Api.AdminConsole.Models.Response.Providers;
@ -25,6 +27,7 @@ public class ProviderResponseModel : ResponseModel
}
public Guid Id { get; set; }
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string Name { get; set; }
public string BusinessName { get; set; }
public string BusinessAddress1 { get; set; }

View File

@ -132,7 +132,7 @@ public class OrganizationSponsorshipsController : Controller
}
var (syncResponseData, offersToSend) = await _syncSponsorshipsCommand.SyncOrganization(sponsoringOrg, model.ToOrganizationSponsorshipSync().SponsorshipsBatch);
await _sendSponsorshipOfferCommand.BulkSendSponsorshipOfferAsync(sponsoringOrg.Name, offersToSend);
await _sendSponsorshipOfferCommand.BulkSendSponsorshipOfferAsync(sponsoringOrg.DisplayName(), offersToSend);
return new OrganizationSponsorshipSyncResponseModel(syncResponseData);
}

View File

@ -58,7 +58,7 @@ public class SelfHostedSponsorshipSyncJob : BaseJob
}
catch (Exception ex)
{
_logger.LogError(ex, $"Sponsorship sync for organization {org.Name} Failed");
_logger.LogError(ex, "Sponsorship sync for organization {OrganizationName} Failed", org.DisplayName());
}
}
}