Navigation Menu

Skip to content

Commit

Permalink
Fix several HTML injections
Browse files Browse the repository at this point in the history
  • Loading branch information
NicolasDorier committed Jan 21, 2023
1 parent 5f24b41 commit 02070d6
Show file tree
Hide file tree
Showing 22 changed files with 59 additions and 43 deletions.
8 changes: 6 additions & 2 deletions BTCPayServer/Controllers/UIAppsController.cs
Expand Up @@ -13,6 +13,7 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;

namespace BTCPayServer.Controllers
{
Expand All @@ -23,18 +24,21 @@ public partial class UIAppsController : Controller
public UIAppsController(
UserManager<ApplicationUser> userManager,
StoreRepository storeRepository,
AppService appService)
AppService appService,
IHtmlHelper html)
{
_userManager = userManager;
_storeRepository = storeRepository;
_appService = appService;
Html = html;
}

private readonly UserManager<ApplicationUser> _userManager;
private readonly StoreRepository _storeRepository;
private readonly AppService _appService;

public string CreatedAppId { get; set; }
public IHtmlHelper Html { get; }

public class AppUpdated
{
Expand Down Expand Up @@ -175,7 +179,7 @@ public IActionResult DeleteApp(string appId)
if (app == null)
return NotFound();

return View("Confirm", new ConfirmModel("Delete app", $"The app <strong>{app.Name}</strong> and its settings will be permanently deleted. Are you sure?", "Delete"));
return View("Confirm", new ConfirmModel("Delete app", $"The app <strong>{Html.Encode(app.Name)}</strong> and its settings will be permanently deleted. Are you sure?", "Delete"));
}

[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
Expand Down
4 changes: 3 additions & 1 deletion BTCPayServer/Controllers/UIManageController.APIKeys.cs
Expand Up @@ -2,9 +2,11 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Abstractions.Models;
using BTCPayServer.Abstractions.Services;
using BTCPayServer.Client;
using BTCPayServer.Data;
using BTCPayServer.Models;
Expand Down Expand Up @@ -41,7 +43,7 @@ public async Task<IActionResult> DeleteAPIKey(string id)
return View("Confirm", new ConfirmModel
{
Title = "Delete API key",
Description = $"Any application using the API key <strong>{key.Label ?? key.Id}<strong> will immediately lose access.",
Description = $"Any application using the API key <strong>{Html.Encode(key.Label ?? key.Id)}<strong> will immediately lose access.",
Action = "Delete",
ActionName = nameof(DeleteAPIKeyPost)
});
Expand Down
6 changes: 5 additions & 1 deletion BTCPayServer/Controllers/UIManageController.cs
Expand Up @@ -16,6 +16,7 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging;
using MimeKit;
Expand All @@ -38,6 +39,7 @@ public partial class UIManageController : Controller
private readonly Fido2Service _fido2Service;
private readonly LinkGenerator _linkGenerator;
private readonly UserLoginCodeService _userLoginCodeService;
private readonly IHtmlHelper Html;
private readonly UserService _userService;
readonly StoreRepository _StoreRepository;

Expand All @@ -54,7 +56,8 @@ public partial class UIManageController : Controller
Fido2Service fido2Service,
LinkGenerator linkGenerator,
UserService userService,
UserLoginCodeService userLoginCodeService
UserLoginCodeService userLoginCodeService,
IHtmlHelper htmlHelper
)
{
_userManager = userManager;
Expand All @@ -68,6 +71,7 @@ UserLoginCodeService userLoginCodeService
_fido2Service = fido2Service;
_linkGenerator = linkGenerator;
_userLoginCodeService = userLoginCodeService;
Html = htmlHelper;
_userService = userService;
_StoreRepository = storeRepository;
}
Expand Down
12 changes: 6 additions & 6 deletions BTCPayServer/Controllers/UIServerController.Users.cs
Expand Up @@ -225,15 +225,15 @@ public async Task<IActionResult> DeleteUser(string userId)
{
// return
return View("Confirm", new ConfirmModel("Delete admin",
$"Unable to proceed: As the user <strong>{user.Email}</strong> is the last enabled admin, it cannot be removed."));
$"Unable to proceed: As the user <strong>{Html.Encode(user.Email)}</strong> is the last enabled admin, it cannot be removed."));
}

return View("Confirm", new ConfirmModel("Delete admin",
$"The admin <strong>{user.Email}</strong> will be permanently deleted. This action will also delete all accounts, users and data associated with the server account. Are you sure?",
$"The admin <strong>{Html.Encode(user.Email)}</strong> will be permanently deleted. This action will also delete all accounts, users and data associated with the server account. Are you sure?",
"Delete"));
}

return View("Confirm", new ConfirmModel("Delete user", $"The user <strong>{user.Email}</strong> will be permanently deleted. Are you sure?", "Delete"));
return View("Confirm", new ConfirmModel("Delete user", $"The user <strong>{Html.Encode(user.Email)}</strong> will be permanently deleted. Are you sure?", "Delete"));
}

[HttpPost("server/users/{userId}/delete")]
Expand All @@ -259,9 +259,9 @@ public async Task<IActionResult> ToggleUser(string userId, bool enable)
if (!enable && await _userService.IsUserTheOnlyOneAdmin(user))
{
return View("Confirm", new ConfirmModel("Disable admin",
$"Unable to proceed: As the user <strong>{user.Email}</strong> is the last enabled admin, it cannot be disabled."));
$"Unable to proceed: As the user <strong>{Html.Encode(user.Email)}</strong> is the last enabled admin, it cannot be disabled."));
}
return View("Confirm", new ConfirmModel($"{(enable ? "Enable" : "Disable")} user", $"The user <strong>{user.Email}</strong> will be {(enable ? "enabled" : "disabled")}. Are you sure?", (enable ? "Enable" : "Disable")));
return View("Confirm", new ConfirmModel($"{(enable ? "Enable" : "Disable")} user", $"The user <strong>{Html.Encode(user.Email)}</strong> will be {(enable ? "enabled" : "disabled")}. Are you sure?", (enable ? "Enable" : "Disable")));
}

[HttpPost("server/users/{userId}/toggle")]
Expand All @@ -288,7 +288,7 @@ public async Task<IActionResult> SendVerificationEmail(string userId)
if (user == null)
return NotFound();

return View("Confirm", new ConfirmModel("Send verification email", $"This will send a verification email to <strong>{user.Email}</strong>.", "Send"));
return View("Confirm", new ConfirmModel("Send verification email", $"This will send a verification email to <strong>{Html.Encode(user.Email)}</strong>.", "Send"));
}

[HttpPost("server/users/{userId}/verification-email")]
Expand Down
7 changes: 5 additions & 2 deletions BTCPayServer/Controllers/UIServerController.cs
Expand Up @@ -89,7 +89,8 @@ public partial class UIServerController : Controller
Logs logs,
LinkGenerator linkGenerator,
EmailSenderFactory emailSenderFactory,
IHostApplicationLifetime applicationLifetime
IHostApplicationLifetime applicationLifetime,
IHtmlHelper html
)
{
_policiesSettings = policiesSettings;
Expand All @@ -113,6 +114,7 @@ IHostApplicationLifetime applicationLifetime
_linkGenerator = linkGenerator;
_emailSenderFactory = emailSenderFactory;
ApplicationLifetime = applicationLifetime;
Html = html;
}

[Route("server/maintenance")]
Expand Down Expand Up @@ -296,6 +298,7 @@ private async Task RunSSHCore(SshClient sshClient, string ssh)

public IHttpClientFactory HttpClientFactory { get; }
public IHostApplicationLifetime ApplicationLifetime { get; }
public IHtmlHelper Html { get; }

[Route("server/policies")]
public async Task<IActionResult> Policies()
Expand Down Expand Up @@ -836,7 +839,7 @@ public async Task<IActionResult> DeleteDynamicDnsService(string hostname)
return NotFound();
return View("Confirm",
new ConfirmModel("Delete dynamic DNS service",
$"Deleting the dynamic DNS service for <strong>{hostname}</strong> means your BTCPay Server will stop updating the associated DNS record periodically.", "Delete"));
$"Deleting the dynamic DNS service for <strong>{Html.Encode(hostname)}</strong> means your BTCPay Server will stop updating the associated DNS record periodically.", "Delete"));
}

[HttpPost("server/services/dynamic-dns/{hostname}/delete")]
Expand Down
6 changes: 3 additions & 3 deletions BTCPayServer/Controllers/UIStoresController.Onchain.cs
Expand Up @@ -800,9 +800,9 @@ private string WalletWarning(bool isHotWallet, string info)
? ""
: " or imported it into an external wallet. If you no longer have access to your private key (recovery seed), immediately replace the wallet";
return
$"<p class=\"text-danger fw-bold\">Please note that this is a <strong>{walletType} wallet</strong>!</p>" +
$"<p class=\"text-danger fw-bold\">Do not proceed if you have not backed up the wallet{additionalText}.</p>" +
$"<p class=\"text-start mb-0\">This action will erase the current wallet data from the server. {info}</p>";
$"<p class=\"text-danger fw-bold\">Please note that this is a <strong>{Html.Encode(walletType)} wallet</strong>!</p>" +
$"<p class=\"text-danger fw-bold\">Do not proceed if you have not backed up the wallet{Html.Encode(additionalText)}.</p>" +
$"<p class=\"text-start mb-0\">This action will erase the current wallet data from the server. {Html.Encode(info)}</p>";
}

private string WalletReplaceWarning(bool isHotWallet)
Expand Down
9 changes: 6 additions & 3 deletions BTCPayServer/Controllers/UIStoresController.cs
Expand Up @@ -65,7 +65,8 @@ public partial class UIStoresController : Controller
WebhookSender webhookNotificationManager,
IDataProtectionProvider dataProtector,
IOptions<LightningNetworkOptions> lightningNetworkOptions,
IOptions<ExternalServicesOptions> externalServiceOptions)
IOptions<ExternalServicesOptions> externalServiceOptions,
IHtmlHelper html)
{
_RateFactory = rateFactory;
_Repo = repo;
Expand All @@ -89,6 +90,7 @@ public partial class UIStoresController : Controller
_BtcpayServerOptions = btcpayServerOptions;
_BTCPayEnv = btcpayEnv;
_externalServiceOptions = externalServiceOptions;
Html = html;
}

readonly BTCPayServerOptions _BtcpayServerOptions;
Expand All @@ -113,6 +115,7 @@ public partial class UIStoresController : Controller

public string? GeneratedPairingCode { get; set; }
public WebhookSender WebhookNotificationManager { get; }
public IHtmlHelper Html { get; }
public LightningNetworkOptions LightningNetworkOptions { get; }
public IDataProtector DataProtector { get; }

Expand Down Expand Up @@ -180,7 +183,7 @@ public async Task<IActionResult> DeleteStoreUser(string userId)
var user = await _UserManager.FindByIdAsync(userId);
if (user == null)
return NotFound();
return View("Confirm", new ConfirmModel("Remove store user", $"This action will prevent <strong>{user.Email}</strong> from accessing this store and its settings. Are you sure?", "Remove"));
return View("Confirm", new ConfirmModel("Remove store user", $"This action will prevent <strong>{Html.Encode(user.Email)}</strong> from accessing this store and its settings. Are you sure?", "Remove"));
}

[HttpPost("{storeId}/users/{userId}/delete")]
Expand Down Expand Up @@ -776,7 +779,7 @@ public async Task<IActionResult> RevokeToken(string tokenId)
var token = await _TokenRepository.GetToken(tokenId);
if (token == null || token.StoreId != CurrentStore.Id)
return NotFound();
return View("Confirm", new ConfirmModel("Revoke the token", $"The access token with the label <strong>{token.Label}</strong> will be revoked. Do you wish to continue?", "Revoke"));
return View("Confirm", new ConfirmModel("Revoke the token", $"The access token with the label <strong>{Html.Encode(token.Label)}</strong> will be revoked. Do you wish to continue?", "Revoke"));
}

[HttpPost("{storeId}/tokens/{tokenId}/revoke")]
Expand Down
2 changes: 1 addition & 1 deletion BTCPayServer/Views/Shared/Crowdfund/UpdateCrowdfund.cshtml
Expand Up @@ -334,7 +334,7 @@

<div class="d-flex gap-3 mt-3">
<a class="btn btn-secondary" asp-action="ListInvoices" asp-controller="UIInvoice" asp-route-storeId="@Model.StoreId" asp-route-searchterm="@Model.SearchTerm">Invoices</a>
<a id="DeleteApp" class="btn btn-outline-danger" asp-controller="UIApps" asp-action="DeleteApp" asp-route-appId="@Model.AppId" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The app <strong>@Model.AppName</strong> and its settings will be permanently deleted." data-confirm-input="DELETE">Delete this app</a>
<a id="DeleteApp" class="btn btn-outline-danger" asp-controller="UIApps" asp-action="DeleteApp" asp-route-appId="@Model.AppId" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The app <strong>@Html.Encode(Model.AppName)</strong> and its settings will be permanently deleted." data-confirm-input="DELETE">Delete this app</a>
</div>

<partial name="_Confirm" model="@(new ConfirmModel("Delete app", "This app will be removed from this store.", "Delete"))" />
Expand Down
Expand Up @@ -265,7 +265,7 @@

<div class="d-flex gap-3 mt-3">
<a class="btn btn-secondary" asp-action="ListInvoices" asp-controller="UIInvoice" asp-route-storeId="@Model.StoreId" asp-route-searchterm="@Model.SearchTerm">Invoices</a>
<a id="DeleteApp" class="btn btn-outline-danger" asp-controller="UIApps" asp-action="DeleteApp" asp-route-appId="@Model.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The app <strong>@Model.AppName</strong> and its settings will be permanently deleted." data-confirm-input="DELETE">Delete this app</a>
<a id="DeleteApp" class="btn btn-outline-danger" asp-controller="UIApps" asp-action="DeleteApp" asp-route-appId="@Model.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The app <strong>@Html.Encode(Model.AppName)</strong> and its settings will be permanently deleted." data-confirm-input="DELETE">Delete this app</a>
</div>

<partial name="_Confirm" model="@(new ConfirmModel("Delete app", "This app will be removed from this store.", "Delete"))" />
Expand Down
4 changes: 2 additions & 2 deletions BTCPayServer/Views/UIApps/ListApps.cshtml
@@ -1,4 +1,4 @@
@using BTCPayServer.Services.Apps
@using BTCPayServer.Services.Apps
@using BTCPayServer.Abstractions.Models
@model ListAppsViewModel
@{
Expand Down Expand Up @@ -103,7 +103,7 @@
<a asp-action="@app.UpdateAction" asp-controller="UIApps" asp-route-appId="@app.Id" asp-route-storeId="@app.StoreId">Settings</a>
<span> - </span>
}
<a asp-action="DeleteApp" asp-route-appId="@app.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The app <strong>@app.AppName</strong> and its settings will be permanently deleted from your store <strong>@app.StoreName</strong>." data-confirm-input="DELETE">Delete</a>
<a asp-action="DeleteApp" asp-route-appId="@app.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The app <strong>@Html.Encode(app.AppName)</strong> and its settings will be permanently deleted from your store <strong>@Html.Encode(app.StoreName)</strong>." data-confirm-input="DELETE">Delete</a>
</td>
</tr>
}
Expand Down
@@ -1,4 +1,4 @@
@using BTCPayServer.Views.Apps
@using BTCPayServer.Views.Apps
@using BTCPayServer.Abstractions.Extensions
@using BTCPayServer.Abstractions.Models
@model BTCPayServer.Models.CustodianAccountViewModels.EditCustodianAccountViewModel
Expand Down Expand Up @@ -35,7 +35,7 @@
<input type="submit" value="Continue" class="btn btn-primary" id="Save"/>
</div>
</form>
<a asp-action="DeleteCustodianAccount" asp-route-storeId="@Model.CustodianAccount.StoreId" asp-route-accountId="@Model.CustodianAccount.Id" class="btn btn-outline-danger" role="button" id="DeleteCustodianAccountConfig" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The custodian account <strong>@Model.CustodianAccount.Name</strong> will be permanently deleted." data-confirm-input="DELETE">
<a asp-action="DeleteCustodianAccount" asp-route-storeId="@Model.CustodianAccount.StoreId" asp-route-accountId="@Model.CustodianAccount.Id" class="btn btn-outline-danger" role="button" id="DeleteCustodianAccountConfig" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The custodian account <strong>@Html.Encode(Model.CustodianAccount.Name)</strong> will be permanently deleted." data-confirm-input="DELETE">
<span class="fa fa-trash"></span> Delete this custodian account
</a>
</div>
Expand Down
4 changes: 2 additions & 2 deletions BTCPayServer/Views/UILNURL/EditLightningAddress.cshtml
@@ -1,4 +1,4 @@
@using BTCPayServer.Views.Stores
@using BTCPayServer.Views.Stores
@using BTCPayServer.Abstractions.Extensions
@using BTCPayServer.Abstractions.Models
@model UILNURLController.EditLightningAddressVM
Expand Down Expand Up @@ -139,7 +139,7 @@
</td>
<td class="text-end">
<button type="submit" title="Remove" name="command" value="@($"remove:{Model.Items[index].Username}")"
class="btn btn-link px-0 remove" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The Lightning Address <strong>@address</strong> will be removed." data-confirm-input="REMOVE">
class="btn btn-link px-0 remove" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The Lightning Address <strong>@Html.Encode(address)</strong> will be removed." data-confirm-input="REMOVE">
Remove
</button>
</td>
Expand Down
2 changes: 1 addition & 1 deletion BTCPayServer/Views/UIManage/APIKeys.cshtml
Expand Up @@ -70,7 +70,7 @@
}
</td>
<td class="text-end">
<a asp-action="DeleteAPIKey" asp-route-id="@keyData.Id" asp-controller="UIManage" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="Any application using the API key <strong>@(keyData.Label ?? keyData.Id)<strong> will immediately lose access." data-confirm-input="DELETE">Delete</a>
<a asp-action="DeleteAPIKey" asp-route-id="@keyData.Id" asp-controller="UIManage" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="Any application using the API key <strong>@Html.Encode(keyData.Label ?? keyData.Id)</strong> will immediately lose access." data-confirm-input="DELETE">Delete</a>
<span>-</span>
<button type="button" class="btn btn-link only-for-js p-0" data-qr="@index">Show QR</button>
</td>
Expand Down

0 comments on commit 02070d6

Please sign in to comment.