Insecure or unset HTTP headers - Cache Control - C-Sharp

Insecure or unset HTTP headers - Cache Control - C-Sharp

Need

Implementation of secure and appropriate Cache Control headers

Context

  • Usage of C# 7.0 for modern language features and enhancements
  • Usage of Microsoft.AspNetCore for building web applications in .NET Core
  • Usage of Microsoft.AspNetCore.Mvc for building web applications with ASP.NET Core
  • Usage of Microsoft.AspNetCore.StaticFiles for serving static files in ASP.NET Core
  • Usage of Microsoft.Extensions.Hosting for building and hosting .NET Core applications

Description

Non compliant code

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}
        
        

In the above code, the application is configured to use several middleware components, including static files, routing, and authorization. However, it does not set the Cache Control HTTP header, which means that the application is not instructing the client on how to cache the content.

This can lead to potential security risks as an attacker could exploit this vulnerability to cache sensitive information, which could then be used for malicious purposes such as identity theft or other forms of fraud.

Moreover, if the Cache Control header is set, but it's set to an insecure value, it could also lead to similar security risks. For example, if the header is set to public for a page that contains sensitive information, then that page could be cached by intermediate proxies and potentially be accessed by unauthorized users.

Steps

  • Add the Cache-Control header to the HTTP response.
  • Set the value of the Cache-Control header to an appropriate and secure value.
  • Configure the Cache-Control header to specify caching directives that meet the application's requirements.
  • Consider using the 'no-store' directive to prevent caching of sensitive information.
  • Consider using the 'no-cache' directive to allow caching but require revalidation of the cached content.
  • Consider using the 'private' directive to restrict caching to the user's browser only.
  • Consider using the 'public' directive to allow caching by both the user's browser and intermediate caches.
  • Consider using the 'max-age' directive to specify the maximum time in seconds that the response can be cached.
  • Consider using the 's-maxage' directive to specify the maximum time in seconds that the response can be cached by shared caches.
  • Consider using the 'must-revalidate' directive to require revalidation of the cached content.
  • Consider using the 'proxy-revalidate' directive to require revalidation of the cached content by intermediate caches.
  • Consider using the 'immutable' directive to indicate that the response will not change over time.
  • Consider using the 'no-transform' directive to prevent transformations of the response by intermediate caches or proxies.

Compliant code

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        // Add secure Cache-Control header
        app.Use(async (context, next) =>
        {
            context.Response.GetTypedHeaders().CacheControl =
                new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
                {
                    Public = true,
                    MaxAge = TimeSpan.FromSeconds(60)
                };
            await next();
        });
    }

    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}
        
        

The above code fixes the vulnerability by adding a secure Cache-Control header to the HTTP response. This is done in the Configure method of the application, which is where middleware is configured.

The Use method is used to add a middleware delegate to the application's request pipeline. This delegate sets the Cache-Control header of the HTTP response.

The CacheControlHeaderValue class is used to create a new Cache-Control header. The Public property is set to true, which means that the response can be cached by both the user's browser and intermediate caches. The MaxAge property is set to 60 seconds, which means that the response can be cached for a maximum of 60 seconds.

This configuration ensures that the application's HTTP responses are cached in a secure manner, which helps to protect against certain types of attacks and improve performance.

Remember to adjust the Cache-Control directives according to your application's requirements. For example, if you're dealing with sensitive information, you might want to use the 'no-store' directive to prevent caching. If you want to allow caching but require revalidation of the cached content, you can use the 'no-cache' directive.

References