mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 22:14:26 +01:00
Make HtmlTags safer, properly sanitize in the view as well
This commit is contained in:
@@ -35,33 +35,35 @@ namespace BTCPayServer.Abstractions.Services
|
|||||||
return _htmlHelper.Raw(_jsonHelper.Serialize(model));
|
return _htmlHelper.Raw(_jsonHelper.Serialize(model));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IHtmlContent Meta(string inputHtml) => _htmlHelper.Raw(RawMeta(inputHtml, out _));
|
||||||
|
|
||||||
public string RawMeta(string inputHtml, out bool isHtmlModified)
|
public string RawMeta(string inputHtml, out bool isHtmlModified)
|
||||||
{
|
{
|
||||||
bool bHtmlModified;
|
bool bHtmlModified;
|
||||||
HtmlSanitizer _metaSanitizer = new HtmlSanitizer();
|
HtmlSanitizer sane = new HtmlSanitizer();
|
||||||
|
|
||||||
_metaSanitizer.AllowedTags.Clear();
|
sane.AllowedTags.Clear();
|
||||||
_metaSanitizer.AllowedTags.Add("meta");
|
sane.AllowedTags.Add("meta");
|
||||||
|
|
||||||
_metaSanitizer.AllowedAttributes.Clear();
|
sane.AllowedAttributes.Clear();
|
||||||
_metaSanitizer.AllowedAttributes.Add("name");
|
sane.AllowedAttributes.Add("name");
|
||||||
_metaSanitizer.AllowedAttributes.Add("http-equiv");
|
sane.AllowedAttributes.Add("http-equiv");
|
||||||
_metaSanitizer.AllowedAttributes.Add("content");
|
sane.AllowedAttributes.Add("content");
|
||||||
_metaSanitizer.AllowedAttributes.Add("value");
|
sane.AllowedAttributes.Add("value");
|
||||||
_metaSanitizer.AllowedAttributes.Add("property");
|
sane.AllowedAttributes.Add("property");
|
||||||
|
|
||||||
_metaSanitizer.AllowDataAttributes = false;
|
sane.AllowDataAttributes = false;
|
||||||
|
|
||||||
_metaSanitizer.RemovingTag += (sender, e) => bHtmlModified = true;
|
sane.RemovingTag += (sender, e) => bHtmlModified = true;
|
||||||
_metaSanitizer.RemovingAtRule += (sender, e) => bHtmlModified = true;
|
sane.RemovingAtRule += (sender, e) => bHtmlModified = true;
|
||||||
_metaSanitizer.RemovingAttribute += (sender, e) => bHtmlModified = true;
|
sane.RemovingAttribute += (sender, e) => bHtmlModified = true;
|
||||||
_metaSanitizer.RemovingComment += (sender, e) => bHtmlModified = true;
|
sane.RemovingComment += (sender, e) => bHtmlModified = true;
|
||||||
_metaSanitizer.RemovingCssClass += (sender, e) => bHtmlModified = true;
|
sane.RemovingCssClass += (sender, e) => bHtmlModified = true;
|
||||||
_metaSanitizer.RemovingStyle += (sender, e) => bHtmlModified = true;
|
sane.RemovingStyle += (sender, e) => bHtmlModified = true;
|
||||||
|
|
||||||
bHtmlModified = false;
|
bHtmlModified = false;
|
||||||
|
|
||||||
var sRet = _metaSanitizer.Sanitize(inputHtml);
|
var sRet = sane.Sanitize(inputHtml);
|
||||||
isHtmlModified = bHtmlModified;
|
isHtmlModified = bHtmlModified;
|
||||||
|
|
||||||
return sRet;
|
return sRet;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using BTCPayServer.Abstractions.Constants;
|
|||||||
using BTCPayServer.Abstractions.Contracts;
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
using BTCPayServer.Abstractions.Extensions;
|
||||||
using BTCPayServer.Abstractions.Models;
|
using BTCPayServer.Abstractions.Models;
|
||||||
|
using BTCPayServer.Abstractions.Services;
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
@@ -38,13 +39,16 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
private readonly UserManager<ApplicationUser> _userManager;
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
private readonly IFileService _fileService;
|
private readonly IFileService _fileService;
|
||||||
|
|
||||||
|
public Safe Safe { get; }
|
||||||
|
|
||||||
public GreenfieldAppsController(
|
public GreenfieldAppsController(
|
||||||
AppService appService,
|
AppService appService,
|
||||||
UriResolver uriResolver,
|
UriResolver uriResolver,
|
||||||
StoreRepository storeRepository,
|
StoreRepository storeRepository,
|
||||||
CurrencyNameTable currencies,
|
CurrencyNameTable currencies,
|
||||||
IFileService fileService,
|
IFileService fileService,
|
||||||
UserManager<ApplicationUser> userManager
|
UserManager<ApplicationUser> userManager,
|
||||||
|
Safe safe
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_appService = appService;
|
_appService = appService;
|
||||||
@@ -53,6 +57,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
_currencies = currencies;
|
_currencies = currencies;
|
||||||
_fileService = fileService;
|
_fileService = fileService;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
|
Safe = safe;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("~/api/v1/stores/{storeId}/apps/crowdfund")]
|
[HttpPost("~/api/v1/stores/{storeId}/apps/crowdfund")]
|
||||||
@@ -305,7 +310,8 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
var parsedSounds = ValidateStringArray(request.Sounds);
|
var parsedSounds = ValidateStringArray(request.Sounds);
|
||||||
var parsedColors = ValidateStringArray(request.AnimationColors);
|
var parsedColors = ValidateStringArray(request.AnimationColors);
|
||||||
Enum.TryParse<BTCPayServer.Services.Apps.CrowdfundResetEvery>(request.ResetEvery.ToString(), true, out var resetEvery);
|
Enum.TryParse<BTCPayServer.Services.Apps.CrowdfundResetEvery>(request.ResetEvery.ToString(), true, out var resetEvery);
|
||||||
|
if (request.HtmlMetaTags is not null)
|
||||||
|
request.HtmlMetaTags = Safe.RawMeta(request.HtmlMetaTags, out _);
|
||||||
return new CrowdfundSettings
|
return new CrowdfundSettings
|
||||||
{
|
{
|
||||||
Title = request.Title?.Trim() ?? request.AppName,
|
Title = request.Title?.Trim() ?? request.AppName,
|
||||||
@@ -342,6 +348,8 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
private PointOfSaleSettings ToPointOfSaleSettings(PointOfSaleAppRequest request, PointOfSaleSettings settings)
|
private PointOfSaleSettings ToPointOfSaleSettings(PointOfSaleAppRequest request, PointOfSaleSettings settings)
|
||||||
{
|
{
|
||||||
Enum.TryParse<BTCPayServer.Plugins.PointOfSale.PosViewType>(request.DefaultView.ToString(), true, out var defaultView);
|
Enum.TryParse<BTCPayServer.Plugins.PointOfSale.PosViewType>(request.DefaultView.ToString(), true, out var defaultView);
|
||||||
|
if (request.HtmlMetaTags is not null)
|
||||||
|
request.HtmlMetaTags = Safe.RawMeta(request.HtmlMetaTags, out _);
|
||||||
|
|
||||||
return new PointOfSaleSettings
|
return new PointOfSaleSettings
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -588,7 +588,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
|||||||
});
|
});
|
||||||
if (wasHtmlModified)
|
if (wasHtmlModified)
|
||||||
{
|
{
|
||||||
TempData[WellKnownTempData.ErrorMessage] = StringLocalizer["Only meta tags are allowed in HTML headers. Your HTML code has been cleaned up accordingly."].Value;
|
TempData[WellKnownTempData.SuccessMessage] = StringLocalizer["Only meta tags are allowed in HTML headers. Your HTML code has been cleaned up accordingly."].Value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -729,7 +729,7 @@ namespace BTCPayServer.Plugins.PointOfSale.Controllers
|
|||||||
await _appService.UpdateOrCreateApp(app);
|
await _appService.UpdateOrCreateApp(app);
|
||||||
if (wasHtmlModified)
|
if (wasHtmlModified)
|
||||||
{
|
{
|
||||||
TempData[WellKnownTempData.ErrorMessage] = StringLocalizer["Only meta tags are allowed in HTML headers. Your HTML code has been cleaned up accordingly."].Value;
|
TempData[WellKnownTempData.SuccessMessage] = StringLocalizer["Only meta tags are allowed in HTML headers. Your HTML code has been cleaned up accordingly."].Value;
|
||||||
} else {
|
} else {
|
||||||
TempData[WellKnownTempData.SuccessMessage] = StringLocalizer["App updated"].Value;
|
TempData[WellKnownTempData.SuccessMessage] = StringLocalizer["App updated"].Value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,7 @@
|
|||||||
object-fit: scale-down;
|
object-fit: scale-down;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@* Html.Raw OK here since Html has been cleaned before in controller *@
|
@this.Safe.Meta(Model.HtmlMetaTags)
|
||||||
@Html.Raw(Model.HtmlMetaTags)
|
|
||||||
<vc:ui-extension-point location="crowdfund-head" model="@Model"/>
|
<vc:ui-extension-point location="crowdfund-head" model="@Model"/>
|
||||||
</head>
|
</head>
|
||||||
<body class="min-vh-100 p-2">
|
<body class="min-vh-100 p-2">
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
@inject IWebHostEnvironment WebHostEnvironment
|
@inject IWebHostEnvironment WebHostEnvironment
|
||||||
@inject SettingsRepository SettingsRepository
|
@inject SettingsRepository SettingsRepository
|
||||||
@inject BTCPayServerEnvironment Env
|
@inject BTCPayServerEnvironment Env
|
||||||
|
|
||||||
@model BTCPayServer.Plugins.PointOfSale.Models.ViewPointOfSaleViewModel
|
@model BTCPayServer.Plugins.PointOfSale.Models.ViewPointOfSaleViewModel
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = string.IsNullOrEmpty(Model.Title) ? Model.StoreName : Model.Title;
|
ViewData["Title"] = string.IsNullOrEmpty(Model.Title) ? Model.StoreName : Model.Title;
|
||||||
@@ -40,8 +41,7 @@
|
|||||||
<link rel="apple-touch-startup-image" href="~/img/splash.png">
|
<link rel="apple-touch-startup-image" href="~/img/splash.png">
|
||||||
<link rel="manifest" href="@(await GetDynamicManifest(ViewData["Title"]!.ToString()))">
|
<link rel="manifest" href="@(await GetDynamicManifest(ViewData["Title"]!.ToString()))">
|
||||||
<link href="~/pos/common.css" asp-append-version="true" rel="stylesheet" />
|
<link href="~/pos/common.css" asp-append-version="true" rel="stylesheet" />
|
||||||
@* Html.Raw OK here since Html has been cleaned before in controller *@
|
@this.Safe.Meta(Model.HtmlMetaTags)
|
||||||
@Html.Raw(Model.HtmlMetaTags)
|
|
||||||
@await RenderSectionAsync("PageHeadContent", false)
|
@await RenderSectionAsync("PageHeadContent", false)
|
||||||
</head>
|
</head>
|
||||||
<body class="min-vh-100">
|
<body class="min-vh-100">
|
||||||
|
|||||||
Reference in New Issue
Block a user