HIGH aspnetcache poisoning

Cache Poisoning in Aspnet

Cache Poisoning in ASP.NET

Cache poisoning occurs when an attacker manipulates shared caching mechanisms to serve stale or malicious responses to legitimate users. In ASP.NET applications, this commonly happens when HTTP caching headers (such as Cache-Control, Expires, or Vary) are misconfigured, allowing sensitive or user-specific responses to be served from a shared cache like IIS Output Caching, Azure Front Door, or a reverse proxy.

Typical scenarios include:

  • User-specific data (e.g., personalized dashboards) being cached without per-user variation in the Vary header.
  • Authentication tokens or session identifiers not being accounted for in cache keys.
  • Improper use of Donut Output Cache where fragments are cached inconsistently.
  • Reverse proxies caching 302 redirect responses or error pages (e.g., 500 errors) that should be user-specific.

For example, consider an ASP.NET MVC action that returns user-specific data:

public ActionResult Dashboard()
{
    var model = _userService.GetDashboardData(User.Identity.Name);
    return View(model);
}

If the response is cached without regard to the authenticated user, an attacker could trigger a cache miss for one user and poison the cache with data intended for another. This is especially dangerous when applications use in-memory or distributed caches like MemoryCache or Redis without proper key scoping.

ASP.NET's output caching mechanism, when misconfigured, can inadvertently cache responses based on query strings or headers that do not fully distinguish users. For instance:

<system.web
href="http://schemas.microsoft.com/.NetConfiguration/v2/cacheSettings"
>
  <outputCacheSettings policy="UseQueryString" />
  <cacheAllowedVaryByParams="none" />
</system.web>

If policy="UseQueryString" is set but cacheAllowedVaryByParams="none", then different query strings do not create separate cache entries, leading to incorrect responses being served.

Real-world exploitation involves sending a request with a crafted query string or header that bypasses authentication checks while the response is cached for a different context. Attackers may use tools to iteratively poison caches by observing response differences and leveraging timing or error-based feedback.

Such vulnerabilities fall under the OWASP API Top 10 category Broken Object Level Authorization and can lead to data exposure, session hijacking, or privilege escalation when cached responses contain sensitive information intended for another user.

Detection in ASP.NET Applications

Detection of cache poisoning vulnerabilities in ASP.NET applications requires validating that caching mechanisms respect user context and authorization boundaries. Systems like middleBrick perform black-box scanning by analyzing HTTP responses for improper caching headers and cross-referencing them with request patterns.

For example, middleBrick might submit two nearly identical requests to an ASP.NET endpoint — one authenticated as User A with data {"user": "alice", "role": "admin"}, and another as User B with {"user": "bob", "role": "user"}. If the response to User B's request includes cached content that reflects User A's data (e.g., admin panel snippets), this indicates a potential cache poisoning vector.

middleBrick checks for the following indicators:

  • Missing or overly broad Vary headers (e.g., Vary: Accept-Encoding without user-specific variation).
  • Cache-Control headers that permit public caching of authenticated responses.
  • Identical response bodies for requests with different authentication tokens or session cookies.
  • Use of DonutOutputCache where fragment caching does not properly isolate user roles.

During scanning, middleBrick sends parallel probe requests with manipulated query strings or headers to trigger different cache paths and observes whether responses vary appropriately. It also analyzes OpenAPI/Swagger specifications to detect endpoints marked as authenticated but observed to return unauthenticated content due to caching misconfigurations.

Findings include specific path examples, request headers used, and severity-based prioritization aligned with OWASP API Top 10. The platform provides remediation guidance directly tied to ASP.NET configuration best practices.

Remediation in ASP.NET

Remediation involves configuring ASP.NET's caching infrastructure to ensure that responses are varied by user context and authorization state. Key steps include:

  1. Set appropriate Vary headers to include authentication-related headers. For example:
<system.web
    <caching>
      <outputCacheLocation mode="Disabled" />
      <outputCacheSettings policy="UseQueryString" />
      <cacheAllowedVaryByParams="authUser" />
    </caching>
</system.web>
  1. Use per-user caching in distributed caches. When using MemoryCache or Redis, include user identity in the cache key:
var cacheKey = $"dashboard:{User.Identity.Name}";
var cachedData = cache.Get(cacheKey);
if (cachedData == null)
{
    cachedData = _userService.GetDashboardData(User.Identity.Name);
    cache.Set(cacheKey, cachedData, TimeSpan.FromMinutes(10));
}
  1. Disable output caching for sensitive endpoints by adding a directive in Web.config or via attributes:
<system.web
tag Elements="false" />
<pages validateRequest="true" />
  1. Apply role-based caching policies. For example, ensure admin panels are never cached:
[OutputCache(VaryByParam="none", Duration=0, Location=OutputCacheLocation.Any)]
[Authorize(Roles = "Admin")]
public ActionResult AdminPanel() { ... }

ASP.NET provides built-in support for fragment caching with DonutOutputCache, but developers must ensure that cached fragments are scoped to user roles. Using VaryByCustom="User"] and overriding GetVaryByCustom in Global.asax allows fine-grained control:

public override string GetVaryByCustom(HttpContext context)
{
    if (context.Request.User.IsInRole("Admin"))
    {
        return "AdminDashboard";
    }
    return base.GetVaryByCustom(context);
}

These practices prevent unauthorized data from being served due to cache poisoning and align with secure caching patterns recommended by NIST and OWASP.

Frequently Asked Questions

Can cache poisoning lead to credential exposure in ASP.NET applications?
Yes. If a cached response contains sensitive data such as authentication tokens, user roles, or personal information and is served to an unauthorized user due to improper caching variation, it can result in credential leakage. Attackers may exploit this to escalate privileges or impersonate other users. middleBrick detects such scenarios by comparing responses across authenticated contexts and flagging mismatches in cached content.
How does middleBrick test for cache poisoning without authentication?
middleBrick performs black-box scanning by sending unauthenticated requests that simulate different user contexts through manipulated headers, query strings, or cookies. It observes whether responses vary appropriately based on expected user-specific data. If a response intended for one user context is served in another's request due to misconfigured caching, it is flagged as a potential cache poisoning vulnerability.