From 01073084abf3edfd60d698a2f65abac084d54f09 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Fri, 27 Feb 2026 22:20:04 +0330 Subject: [PATCH] =?UTF-8?q?security:=20remove=20callback=20URL=20from=20us?= =?UTF-8?q?er=20input=20=E2=80=94=20read=20from=20FrontOfficeBaseUrl=20con?= =?UTF-8?q?fig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PackageService: build callback URL from FrontOfficeBaseUrl config instead of request.CallbackUrl - TransactionsService: same fix — callback URL from config - Prevents potential open redirect vulnerability (user could send arbitrary URL) All callback URLs now come from appsettings FrontOfficeBaseUrl or CmsBaseUrl. --- src/CMSMicroservice.WebApi/Services/PackageService.cs | 10 +++++----- .../Services/TransactionsService.cs | 8 ++++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/CMSMicroservice.WebApi/Services/PackageService.cs b/src/CMSMicroservice.WebApi/Services/PackageService.cs index 9b2ffae..c279901 100644 --- a/src/CMSMicroservice.WebApi/Services/PackageService.cs +++ b/src/CMSMicroservice.WebApi/Services/PackageService.cs @@ -182,9 +182,9 @@ public class PackageService : PackageContract.PackageContractBase .Select(u => new { u.Mobile }) .FirstOrDefaultAsync(context.CancellationToken); - // Embed orderId in callback URL so FrontOffice can pass it back for verification - var separator = request.CallbackUrl.Contains('?') ? "&" : "?"; - var callbackWithOrder = $"{request.CallbackUrl}{separator}orderId={purchase.Id}"; + // Callback URL از config — نه از ورودی کاربر (امنیت) + var frontOfficeBaseUrl = _configuration["FrontOfficeBaseUrl"] ?? "https://localhost:5268"; + var callbackUrl = $"{frontOfficeBaseUrl}/profile/payment-callback?orderId={purchase.Id}"; var paymentResult = await _paymentGateway.InitiatePaymentAsync(new PaymentRequest { @@ -192,7 +192,7 @@ public class PackageService : PackageContract.PackageContractBase UserId = userId, Mobile = user?.Mobile ?? string.Empty, Description = $"خرید پکیج {package.Title}", - CallbackUrl = callbackWithOrder + CallbackUrl = callbackUrl }, context.CancellationToken); if (!paymentResult.IsSuccess) @@ -216,7 +216,7 @@ public class PackageService : PackageContract.PackageContractBase GatewayProvider = _configuration["PaymentProvider"] ?? "zarinpal", MerchantId = _configuration["ZarinPal:MerchantId"] ?? "", Amount = package.Price, - CallbackUrl = request.CallbackUrl, + CallbackUrl = callbackUrl, Description = $"خرید پکیج {package.Title}", Mobile = user?.Mobile, UserId = userId, diff --git a/src/CMSMicroservice.WebApi/Services/TransactionsService.cs b/src/CMSMicroservice.WebApi/Services/TransactionsService.cs index dbc4966..dfd2d25 100644 --- a/src/CMSMicroservice.WebApi/Services/TransactionsService.cs +++ b/src/CMSMicroservice.WebApi/Services/TransactionsService.cs @@ -162,6 +162,10 @@ public class TransactionsService : TransactionsContract.TransactionsContractBase _context.Transactions.Add(transaction); await _context.SaveChangesAsync(context.CancellationToken); + // Callback URL از config — نه از ورودی کاربر (امنیت) + var frontOfficeBaseUrl = _configuration["FrontOfficeBaseUrl"] ?? "https://localhost:5268"; + var callbackUrl = $"{frontOfficeBaseUrl}/profile/payment-callback"; + // Initiate payment with gateway var paymentResult = await _paymentGateway.InitiatePaymentAsync(new PaymentRequest { @@ -169,7 +173,7 @@ public class TransactionsService : TransactionsContract.TransactionsContractBase UserId = userId, Mobile = request.Mobile ?? user?.Mobile ?? string.Empty, Description = request.Description ?? "پرداخت آنلاین", - CallbackUrl = request.CallbackUrl + CallbackUrl = callbackUrl }, context.CancellationToken); if (!paymentResult.IsSuccess) @@ -191,7 +195,7 @@ public class TransactionsService : TransactionsContract.TransactionsContractBase GatewayProvider = _configuration["PaymentProvider"] ?? "zarinpal", MerchantId = _configuration["ZarinPal:MerchantId"] ?? "", Amount = request.Amount, - CallbackUrl = request.CallbackUrl, + CallbackUrl = callbackUrl, Description = request.Description ?? "پرداخت آنلاین", Mobile = request.Mobile ?? user?.Mobile, UserId = userId,