at work we have an ASP.NET Core 7.0 MVC app. It is a CMS with sites for several brands across many cultures, so there are a lot of URL variants used. Lately, we have noticed that our app allows redirects to a page from the URL parameter, so for example, https://example.com/http:/google.com will redirect to the Google site. And that is a very undesirable effect. I have created a middleware to catch every single request which contains double http/https prefix:
public class RedirectDetectorMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public RedirectDetectorMiddleware(RequestDelegate next, ILogger<RedirectDetectorMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
var url = context.Request.Path.ToString();
_logger.LogInformation("Request entering {MiddlewareName} with URL: {Url}", nameof(RedirectDetectorMiddleware), url);
if (url.Contains(HttpContextItems.InvalidHttp) || url.Contains(HttpContextItems.InvalidHttps) || url.Contains(HttpContextItems.InvalidFtp))
{
_logger.LogInformation("Redirect from the following URL was blocked: {Url}", url);
context.Response.StatusCode = StatusCodes.Status404NotFound;
context.Request.Path = $"/{context.Response.StatusCode}";
}
await _next(context);
}
}
From logs I can see that every single undesired URL which enters said middleware is the blocked, but the problem is some redirections are happening even before the middleware (which is placed near the top of the Configure method in Startup class).
How can we effectively resolve this issue?
EDIT:
As requested, here is a Configure method from the Startup.cs class:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IUrlRewriteService urlRewriteService, IHostApplicationLifetime lifetime, ILogger<Startup> logger)
{
app.UseForwardedHeaders();
app.UseSynchronousIO();
if (!_isEditServer && _isEnableRewriteModule)
{
using var iisUrlRewriteStreamReader = new StreamReader(urlRewriteService.DownloadRewriteRulesFile());
var options = new RewriteOptions()
.AddIISUrlRewrite(iisUrlRewriteStreamReader);
app.UseRewriter(options);
}
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/500");
app.UseNotFoundPage();
app.UseHsts();
}
app.UseRestrictedEpiserverAccess();
app.UseHttpsRedirection();
app.UseNotFoundHandler();
app.UseOptimizelyNotFoundHandler();
app.UseMiddleware<RedirectDetectorMiddleware>();
app.UseStaticFiles(new StaticFileOptions
{
ContentTypeProvider = FileExtensionContentTypeProviderFactory.Create(),
});
app.UseRouting();
app.UseCors();
app.UseWebMarkupMin();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapContent();
endpoints.MapControllers();
endpoints.MapRazorPages();
endpoints.MapControllerRoute(
name: "Default",
pattern: "{controller}/{action=Index}");
endpoints.MapControllerRoute(
name: "Admin",
pattern: "Admin/{controller}/{action=Index}");
endpoints.MapControllerRoute(
name: "EPiServer CMS",
pattern: "EPiServer/CMS/{controller}/{action=Index}");
endpoints.MapControllerRoute(
name: "Custom routes",
pattern: "custom-routes/{controller}/{action=Index}");
endpoints.MapControllerRoute(
name: "Api",
pattern: "api/{controller}/{action=Index}");
});
lifetime.ApplicationStarted.Register(() => InitializeOnlyOnceDuringStartup(logger));
if (_isEditServer && _azureServiceBusIsEnabled)
{
app.Subscribe().Event<CertificateSaved>().Start();
app.Subscribe().Event<CertificateDeleted>().Start();
}
}
Show us your
Configure
method.@Dai I have updated the original post with it.
It looks like you might have an IIS Rewrite rule that does it. Also, I’m curious what the purpose of
RewriteOptions().AddIISUrlRewrite
is when IIS<rewrite>
works entirely independently of ASP.NET Core…I have looked through all of them, there are quite a few, but there is no rule which could do that.
My only suggestion then is to enable IIS request tracing (the kind that uses ETW) and use that to find out where the redirect is coming from.
Show 3 more comments