Ssrf in Aspnet with Bearer Tokens
Ssrf in Aspnet with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Server-Side Request Forgery (SSRF) in ASP.NET becomes more critical when APIs rely on Bearer Tokens for authorization. In this setup, an attacker can trick a backend endpoint into making outbound HTTP requests to internal or external destinations while automatically forwarding captured Bearer Tokens. Because the server-side code often adds the Authorization header from user input or configuration without validating the target, the token intended for a downstream service can be relayed to an unintended host, amplifying the impact.
Consider an ASP.NET Core application that fetches user profile data from a third-party API. The client obtains a Bearer Token, and the server uses it to call the external API. If the endpoint that specifies the target URL is not strictly constrained, an attacker can supply a malicious URL such as http://169.169.169.254/latest/meta-data/iam/security-credentials/ (AWS metadata service). The server, executing the request with its outbound network permissions and including the Bearer Token, may leak sensitive identity information or session material to an internal, attacker-controlled endpoint.
SSRF in this context can also expose internal services that are not directly reachable from the internet. An attacker can provide an internal address like http://127.0.0.1:8080/admin or http://169.169.169.254, knowing the backend will include the Bearer Token in the request. This can lead to token exfiltration, service enumeration, or lateral movement within a cloud environment. The risk increases when the backend uses long-lived tokens or shared secrets that are not scoped with the principle of least privilege.
OpenAPI/Swagger specifications can unintentionally encourage SSRF if external servers and security schemes are defined in a way that encourages dynamic URL composition without validation. For instance, if a path parameter intended for a hostname is bound directly into a HttpClient call and an Authorization header is appended from user-controlled data, the attack surface grows. Because middleBrick scans OpenAPI 2.0, 3.0, and 3.1 specs with full $ref resolution, it can detect such mismatches between defined security schemes and runtime behavior, highlighting where Bearer Token handling may expose internal endpoints.
Real-world examples include CVE-2021-44228 patterns in logging or HTTP client wrappers where SSRF intersects with token leakage, and misconfigured internal endpoints in Kubernetes services. Attack patterns such as metadata service probing, internal network scanning, and external webhook poisoning are common when Bearer Tokens are forwarded without strict allowlists. Mitigation requires validating and restricting target URLs, avoiding the use of raw user input in request targets, and scoping tokens to specific audiences and minimal permissions.
Bearer Tokens-Specific Remediation in Aspnet — concrete code fixes
To reduce SSRF risk in ASP.NET when using Bearer Tokens, enforce strict URL allowlists, avoid concatenating untrusted input into request targets, and isolate token usage to specific, validated destinations. The following examples demonstrate secure patterns for configuring HttpClient and authorization headers in ASP.NET Core.
1. Validate target URLs before use
Ensure that any user-supplied URL is parsed and compared against an allowlist of permitted hosts. Do not forward arbitrary URLs to services that carry Bearer Tokens.
using System;
using System.Net.Http;
using System.Threading.Tasks;
public class ProxyService
{
private readonly HttpClient _httpClient;
private readonly string[] _allowedHosts = { "api.trusted.com", "internal.service.local" };
public ProxyService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<HttpResponseMessage> CallAllowedEndpointAsync(string userSuppliedHost, string path, string token)
{
var host = new Uri(userSuppliedHost).Host;
if (Array.IndexOf(_allowedHosts, host) < 0)
{
throw new ArgumentException("Host not allowed");
}
var request = new HttpRequestMessage(HttpMethod.Get, $"https://{host}/{path}");
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
return await _httpClient.SendAsync(request);
}
}
2. Use typed clients with configuration-bound base addresses
Define named HTTP clients with fixed base addresses in configuration and avoid dynamic host overrides. This prevents runtime redirection to unintended endpoints while still attaching Bearer Tokens.
// Program.cs or Startup.cs
builder.Services.AddHttpClient("ExternalApi", client =>
{
client.BaseAddress = new Uri("https://api.trusted.com/");
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", builder.Configuration["Tokens:ExternalApi"]);
});
// Consumer service
public class ExternalClient
{
private readonly HttpClient _httpClient;
public ExternalClient(IHttpClientFactory factory) => _httpClient = factory.CreateClient("ExternalApi");
public async Task<string> GetProfileAsync() =>
await _httpClient.GetStringAsync("v1/profile");
}
3. Avoid passing raw tokens via query strings or fragments
Ensure Bearer Tokens are only sent in the Authorization header and never embedded in URLs, which can be logged or leaked via referrers.
// Bad: token in URL
// await httpClient.GetAsync($"https://api.example.com/data?token={token}");
// Good: token in header
var request = new HttpRequestMessage(HttpMethod.Get, "https://api.example.com/data");
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
var response = await httpClient.SendAsync(request);
4. Limit token scope and lifetime
Configure tokens with minimal scopes and short lifetimes. In ASP.NET, use policy-based authorization to validate token audiences and roles before allowing outbound calls that include the token.
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Audience = "api://specific-api";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "https://trusted-issuer.com"
};
});Related CWEs: ssrf
| CWE ID | Name | Severity |
|---|---|---|
| CWE-918 | Server-Side Request Forgery (SSRF) | CRITICAL |
| CWE-441 | Unintended Proxy or Intermediary (Confused Deputy) | HIGH |