Api Key Exposure in Aspnet with Redis
Api Key Exposure in Aspnet with Redis
Storing API keys directly in Redis from an ASP.NET application can expose credentials when configuration or connection practices are insecure. ASP.NET applications often use Redis for distributed caching or session state, and developers may inadvertently store sensitive values such as ApiKey or ConnectionString in Redis without adequate safeguards. The exposure risk arises from a combination of insecure application configuration, insufficient runtime access controls, and lack of encryption in transit or at rest.
For example, an ASP.NET Core app might push an API key into Redis using a string key that is predictable and accessible to unauthorized code paths. If the Redis instance is reachable without authentication, or if the connection uses a default port without TLS, an attacker who can reach the Redis port may read or alter cached data. This becomes particularly dangerous when the same Redis instance is shared across multiple applications or tenants, increasing the likelihood of cross-tenant data access.
Common patterns that contribute to exposure include:
- Caching third-party API keys under generic names such as
external_api_keywithout namespacing by tenant or environment. - Logging or diagnostic code that inadvertently dumps cached keys, for example by scanning keys with
SCANor reading large hash fields. - Using the same Redis instance for non-sensitive cache data and sensitive configuration values, blurring trust boundaries.
Attackers may leverage these exposures to steal API keys, which can lead to unauthorized external API access, data exfiltration, or cost abuse. Because Redis does not enforce fine-grained permissions by default, overly permissive network rules or missing ACLs can allow broad read access. In an ASP.NET context, if configuration loading falls back to reading keys from Redis when local configuration is missing, an attacker who can read Redis can effectively bypass intended secret management boundaries.
To understand how this manifests during a scan, middleBrick tests whether API keys or other sensitive values are discoverable through unauthenticated or weakly authenticated access paths. It checks whether Redis endpoints are exposed unnecessarily, whether TLS is enforced, and whether key names follow predictable patterns that facilitate enumeration. These checks align with the broader OWASP API Top 10 and relevant compliance mappings that highlight data exposure risks.
Redis-Specific Remediation in Aspnet
Remediation focuses on secure storage, strict network controls, and avoiding the storage of raw API keys in Redis whenever possible. When caching is necessary, store only non-sensitive, ephemeral data. For secrets, rely on a dedicated secret manager and inject values into ASP.NET configuration at runtime.
Use strong ACLs to limit access by role or application identity. Configure Redis to require authentication and enforce TLS to protect data in transit. In ASP.NET, structure your configuration providers so that Redis is used for cache data only, not as a primary store for credentials.
If you must store non-sensitive tokens or identifiers in Redis, ensure key names are namespaced and unpredictable. Rotate any exposed keys immediately and audit access logs. The following examples demonstrate secure patterns for interacting with Redis in ASP.NET, emphasizing configuration and safe usage.
Example 1: Secure Configuration with Redis Cache for Non-Sensitive Data
Use Redis as a cache for public or non-sensitive data, while keeping API keys in configuration providers that are not stored in Redis.
// Program.cs in ASP.NET Core
var builder = WebApplication.CreateBuilder(args);
// Configure Redis as a cache, not a secret store
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration["Redis:ConnectionString"];
options.InstanceName = "MyApp:";
});
// Keep API keys in secure configuration sources (e.g., user secrets, environment variables)
builder.Configuration.AddUserSecrets<Program>();
var app = builder.Build();
// Example controller that reads a cached value, not an API key
var logger = app.Services.GetRequiredService<ILogger<WeatherForecastController>>();
app.MapGet("/forecast", (IDistributedCache cache) =>
{
var cached = cache.GetString("weather_summary");
return Results.Ok(cached ?? "No cached data");
});
app.Run();
Example 2: Using Redis with Strong ACL and TLS in Aspnet
Ensure your Redis connection string enforces TLS and uses a dedicated, limited-privilege credential.
// appsettings.json (do NOT store raw API keys here)
{
"Redis": {
"ConnectionString": "your-redis.redis.cache.windows.net:6380,password=StrongPassword,ssl=true,abortConnect=false"
}
}
// Usage in a service that respects ACLs
public class DataService
{
private readonly IDatabase _redis;
public DataService(IConnectionMultiplexer redis)
{
_redis = redis.GetDatabase();
}
public async Task SetSafeCacheValueAsync(string key, string value)
{
// Namespaced key to avoid collisions
await _redis.StringSetAsync($"safeapp:{key}", value, TimeSpan.FromMinutes(10));
}
public async Task GetSafeCacheValueAsync(string key)
{
return await _redis.StringGetAsync($"safeapp:{key}");
}
}
Example 3: Avoid Storing API Keys in Redis
Do not write API keys into Redis. Instead, retrieve them from a secure source at startup and keep them in memory within the ASP.NET configuration model.
// Do NOT do this:
// await _redis.StringSetAsync("api_key", "super-secret-key");
// Do this:
// Load from environment or user secrets at startup
var apiKey = builder.Configuration["ExternalService:ApiKey"];
if (string.IsNullOrEmpty(apiKey))
{
throw new InvalidOperationException("Missing required external API key.");
}
// Use apiKey directly in your HTTP client, do not persist to Redis