HIGH ssrf server sideaspnetbearer tokens

Ssrf Server Side in Aspnet with Bearer Tokens

Ssrf Server Side in Aspnet with Bearer Tokens — how this specific combination creates or exposes the vulnerability

Server-side request forgery (SSRF) in ASP.NET applications becomes especially nuanced when Bearer tokens are involved. In many integrations, an ASP.NET backend calls external APIs on behalf of a user or service, attaching an access token in the Authorization header as a Bearer credential. This pattern is common when calling Microsoft Graph, third‑party SaaS APIs, or internal services that rely on OAuth 2.0 tokens. SSRF arises when an attacker can influence the target URL of these outbound HTTP requests, tricking the server into making arbitrary network calls that it should not.

The combination of SSRF and Bearer tokens introduces two critical risks. First, the attacker can force the server to send the token to an arbitrary host, potentially capturing it if the server’s request is intercepted or if the attacker controls a malicious endpoint that logs headers. Second, SSRF can be used to reach internal services that are not exposed to the internet but accept requests from the application; if those internal services trust the Bearer token, the attacker gains lateral movement or data access they should not have. A typical vulnerable pattern in ASP.NET involves accepting a user-supplied URL and using HttpClient to call it while attaching a token from configuration or a token introspection endpoint without proper validation of the destination.

Consider an endpoint designed to fetch user profile data from an external identity provider. If the endpoint URL is supplied by the caller and passed directly to HttpClient without strict allowlisting or parsing, an attacker can supply a URL such as http://169.169.169.255/latest/meta-data/iam/security-credentials/ to exploit the instance metadata service, while the request carries a valid Bearer token. Even if the token is short-lived, the exposure combined with SSRF can enable token exfiltration or unauthorized internal API calls. In OAuth 2.0 flows, tokens may also be refreshed via backend calls; SSRF can disrupt or poison these flows by redirecting token requests to malicious actors, leading to token replay or substitution.

An additional subtlety is outbound service-to-service communication where Bearer tokens are stored in configuration and used automatically. If an SSRF vector exists in a component that makes outbound calls, the attacker can indirectly force the application to present privileged tokens to arbitrary endpoints, bypassing intended network segmentation. This is especially dangerous in ASP.NET when developers assume that outbound calls from the server are safe because they originate from a trusted backend. The presence of Bearer tokens does not mitigate SSRF; instead, it raises the impact because the token can be used to authenticate to otherwise restricted resources.

Using middleBrick, you can detect such issues by scanning the unauthenticated attack surface and observing whether the API exposes endpoints that accept arbitrary URLs or headers that could be abused to redirect outbound calls while leaking authorization headers. The scanner’s checks include input validation, data exposure, and unsafe consumption patterns that are relevant to SSRF and token leakage. For API definitions expressed as OpenAPI/Swagger 2.0, 3.0, or 3.1, middleBrick resolves $ref references and cross-references definitions with runtime findings to highlight risky parameter bindings.

Bearer Tokens-Specific Remediation in Aspnet — concrete code fixes

Remediation focuses on preventing untrusted input from influencing outbound request URLs and ensuring Bearer tokens are never exposed to destinations that are not explicitly trusted. Below are concrete patterns and code examples for safe handling in ASP.NET.

  • Validate and allowlist destination URLs: Do not forward user-supplied URLs directly to HttpClient. Instead, maintain a strict allowlist of domains or use a mapping from trusted keys to URLs.
  • Avoid attaching Bearer tokens to requests whose destination is user-controlled. If you must call external services, retrieve the token per call only for known, verified endpoints.
  • Use typed clients and configure HttpClient with a base address and default headers in Startup or Program.cs, avoiding runtime concatenation of user input into the request URI.
  • Implement schema and host validation for any URI that your code might accept, rejecting dangerous schemes and unexpected hosts.

Example of a vulnerable controller that should be fixed:

// Vulnerable example — do not use
[ApiController]
[Route("api/[controller]")]
public class ProfileController : ControllerBase
{
    private readonly HttpClient _httpClient;
    public ProfileController(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    [HttpGet("external")]
    public async Task<IActionResult> GetExternalProfile(string url, string accessToken)
    {
        // Dangerous: user-supplied URL and token forwarded without validation
        var request = new HttpRequestMessage(HttpMethod.Get, url);
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
        var response = await _httpClient.SendAsync(request);
        var content = await response.Content.ReadAsStringAsync();
        return Ok(content);
    }
}

Safer implementation using an allowlist and typed client:

// Safer approach
public static class ServiceCollectionExtensions
{
    public void AddTrustedProfileClient(this IServiceCollection services, IConfiguration configuration)
    {
        services.AddHttpClient("TrustedProfileClient", client =>
        {
            var baseAddress = configuration["TrustedApi:BaseAddress"];
            client.BaseAddress = new Uri(baseAddress);
            var token = configuration["TrustedApi:Token"];
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
        });
    }
}

[ApiController]
[Route("api/[controller]")]
public class ProfileController : ControllerBase
{
    private readonly IHttpClientFactory _clientFactory;
    private static readonly HashSet<string> AllowedHosts = new() { "api.trustedprovider.com" };

    public ProfileController(IHttpClientFactory clientFactory)
    {
        _clientFactory = clientFactory;
    }

    [HttpGet("profile")]
    public async Task<IActionResult> GetProfile()
    {
        var uri = new UriBuilder("https://api.trustedprovider.com/v1/profile")
        {
            // No user input in path or query unless explicitly validated and sanitized
        }.Uri;

        if (!AllowedHosts.Contains(uri.Host))
        {
            return Forbid();
        }

        var client = _clientFactory.CreateClient("TrustedProfileClient");
        var response = await client.GetAsync(uri);
        response.EnsureSuccessStatusCode();
        var content = await response.Content.ReadAsStringAsync();
        return Ok(content);
    }
}

Key points in the safer example:

  • The base address and token are configured centrally and not derived from user input.
  • The destination host is validated against an allowlist before the request is issued.
  • User input is not used to construct the request URI or the Authorization header in the vulnerable pattern; instead, a fixed, trusted endpoint is called.

Additional measures include inspecting Referer and Origin headers, using outbound firewall rules where possible, and monitoring for anomalous token usage. middleBrick’s scans can surface risky parameter bindings and missing validation that could lead to SSRF; its findings include remediation guidance to help you implement these controls.

Frequently Asked Questions

Why does using Bearer tokens not prevent SSRF in ASP.NET APIs?
Bearer tokens are credentials presented to a downstream service. SSRF is about the server making unauthorized network requests to destinations an attacker can choose. Supplying a token does not restrict where the request can go; it can actually increase impact if the token is sent to an attacker-controlled server or if internal services trust that token.
What should I validate when my ASP.NET API calls external APIs with Bearer tokens?
You should validate the destination hostname against a strict allowlist, enforce HTTPS, avoid user-controlled paths or hosts, and ensure tokens are not dynamically injected from user input. Prefer configuration-based tokens for known services and avoid forwarding tokens to arbitrary endpoints.