Skip to Main Content
All Trimarc services are now delivered through TrustedSec! Learn more
July 10, 2025

Azure's Front Door WAF WTF: IP Restriction Bypass

Written by @ nyxgeek
Cloud Penetration Testing

The Azure Front Door Web Application Firewall (WAF) has an "IP restriction" option that can be bypassed with the inclusion of an HTTP header.

What's worse? This is actually expected behavior.

Figure 1 - WHY???

Background

There are two (2) WAFs available within Azure—Front Door WAF and the Application Gateway WAF. The Front Door WAF is Azure's Global WAF and the Application Gateway WAF is the Regional WAF.

Figure 2 - Create a WAF Policy in Azure

This particular IP restriction bypass only works in the Front Door WAF. Within the Front Door WAF, if you choose to restrict access by IP address, the default choice is a variable called RemoteAddr.

Figure 3 - Front Door WAF Policy

If the 'Match Variable' drop-down is selected, we can see our options: RemoteAddr or SocketAddr.

Figure 4 - Choose Wisely

We have two (2) ambiguously named variables to match against. So, what's the difference?

Figure 5 - What Could go Wrong?

Well, within the Front Door WAF documentation, Microsoft lays it out plainly: the RemoteAddr variable matches the original client's IP address, and it does this by respecting the X-Forwarded-For HTTP header, if set. The SocketAddr variable, on the other hand, is the IP address that the WAF sees, i.e., the real IP address. This is what any sane person would expect the filtering to take place on.

Figure 6 - Le Sigh

So, to be clear: the default selection for IP address restrictions within Front Door WAF can be bypassed simply by adding an X-Forwarded-For header with an appropriate IP address. Further, there's no clear indication that one of the two options is terrible.

Figure 7 - I mean, what *is* an IP address really?

The RemoteAddr variable also exists as an option within the Geo location matching rules, but it is not the default selection there.

Figure 8 – It *seems* to be working

Sure, admins SHOULD carefully read all documentation, but would anybody have guessed that one of the options is not secure in the slightest? It's completely unreliable for securing anything. It shouldn’t even be labeled as an IP restriction, as it gives the illusion of adding security.

While not explicitly noted in the documentation, RemoteAddr will check both the X-Forwarded-For value as well as the actual connecting IP address to see if either matches. This means that if an admin configures the WAF with RemoteAddr and does a test connect, it would allow the connection whether the X-Forwarded-For header were set or not, so long as the actual IP address matched. This could further muddy the waters when realizing the difference between RemoteAddr and SocketAddr and could lead to a dangerous 'sleeper' rule that appears to work as intended but can be bypassed easily.

During my testing, it was possible to brute-force a /16 network space within about 40 minutes and gain access to a site protected by RemoteAddr IP address restrictions. I performed this test using Burp Intruder. This is made easier if the attacker is able to get an email sent from a user in order to get some originating IP address ranges or if the target has CIDRs registered.

Figure 9 - Brute-Forcing Allowed IP Addresses With Burp Suite

You Know What Happens When You Assume…

Things get really confusing if you have ever used the Application Gateway WAF (the other Azure WAF). Within the Application Gateway WAF, the default (and only) variable for IP restriction is RemoteAddr.

Figure 10 - Application Gateway WAF

However, in the Application Gateway WAF, the RemoteAddr variable refers to the IP address that the WAF sees (equivalent to the SocketAddr variable within the Front Door WAF).

That's right! Microsoft used the same variable name in related products to mean entirely different things!

Service

Variable Name

Description

Front Door

RemoteAddr

IP address set by X-Forwarded-For or
IP address that the WAF sees

Front Door

SocketAddr

IP address that the WAF sees

Application Gateway

RemoteAddr

IP address that the WAF sees

Figure 11 – Why would they do that

It's a Feature, not a Bug

A tale as old as MSRC: this is intended behavior. On the plus side, it had a pretty fast turnaround.

2025.05.14: Submitted to MSRC

2025.05.15: MSRC Reviewing

2025.06.03: MSRC declines to address, as this behavior is intentional

Figure 12 - Confirmed feature!

Testing Setup

Alright, let's demo! First, set up a simple site that we will protect with the Front Door WAF and use to demonstrate the bypass. For our test, we'll use a site that says, "Hello world, [name]".

Figure 13 - Test Application

Then, configure Azure Front Door with a route to the test site.

Figure 14 - Front Door Route

Next, configure a Security Policy and a WAF policy.

Figure 15 - Front Door Security Policy

Then, configure a custom rule to allow traffic from a specific IP address (in this case, 123.45.67.89) and match on the RemoteAddr variable. This is the only variable susceptible to this bypass; I was unable to identify a bypass that worked when SocketAddr is chosen.

Figure 16 - Configuring Custom Rule

The RemoteAddr variable is likely chosen more often because the differences are not clearly defined on the page, and the RemoteAddr variable is pre-selected when IP address is chosen to filter on.

Finally, set the WAF to Prevention mode.

Figure 17 - WAF in Prevention Mode

Verification of Blocking Rule

Now, verify that it is blocking any normal traffic, not originating from 123.45.67.89.

Figure 18 - WAF Functioning Correctly in Browser

Perfect. Our request is blocked, as expected.

We can confirm the blocking again, with curl:

Figure 19 - WAF Functioning Correctly With curl

Here is just the header with curl, showing a 403 response.

Figure 20 - WAF Functioning - HEAD Response

Identifying Front Door WAF

A quick note on identification of Front Door WAF vs the Application Gateway WAF. If it is a Front Door WAF, you should see both x-azure-ref and x-cache headers present.

Figure 21 - Headers Indicating Front Door WAF

If the target is using the Application Gateway WAF, there is no positive indicator that I could find. Your indicators in that case would be the Microsoft IP address and the lack of the headers noted above.

Bypassing IP Restriction

By simply adding X-Forwarded-For: [IP address], you can bypass this restriction.

Figure 22 - IP Restriction Bypass

That's it. Simple.

Again, this does not work if the rules are configured to use the SocketAddr variable, but the RemoteAddr variable is pre-selected when creating a new IP restriction and is likely chosen out of ignorance between the options. After all, in the Application Gateway, RemoteAddr is totally safe.

Figure 23 - "IP address Matching"

BONUS POWERUP!

Remember, when a Custom Rule is matched, no other WAF rules are checked. The EXTENSIVE list of OWASP attack detections is skipped entirely. There are no secondary checks, it's all or none. So, if you ARE able to use this to gain access to a dev site or something that the admins assumed was protected, you may be able to scan away with impunity.

Figure 24 - Can't Detect What You Don't Scan For

Detection

I have put together a simple PowerShell script that you can run from Azure Cloud Shell. Simply go to "Manage files" and upload the script: https://github.com/nyxgeek/frontdoor_waf_wtf/.

Alternatively, you can curl the file with:

curl -O
https://raw.githubusercontent.com/nyxgeek/frontdoor_waf_wtf/refs/heads/main/azure_frontdoor_waf_wtf.ps1

Then run the script:
./azure_frontdoor_waf_wtf.ps1

Figure 25 - RemoteAddr Detection

This tool will report on whether any of the Front Door WAF rules use the insecure RemoteAddr variable.

This RemoteAddr WAF check has also been made into a module in GraphRunner (https://github.com/dafthack/GraphRunner). You will need to perform an extra step to check for this, because the GraphRunner tokens are Graph tokens by default.

After importing the GraphRunner module, get a token for the Management endpoint, using:

Get-GraphTokens -Resource 'https://management.azure.com/'

Figure 26 - Getting a Management Token

Next, run:

Check-FrontDoorWAF -Tokens $tokens

Figure 27 - Check-FrontDoorWAF

Note: After running this module, you'll need to run Get-GraphTokens again to get a normal Graph token again.

Remediation

Luckily, the fix is simple enough: simply update your Front Door WAF configuration to use SocketAddr. However, if you are actually using the functionality of the RemoteAddr and need to be able to differentiate between people on the other side of a proxy, it's easy enough to add a second "If" condition that requires the SocketAddr to match the IP address of your proxy server.

The following screenshot shows an example of a rule that will allow specific IP addresses from behind the proxy (e.g., X-Forwarded-For: 123.45.67.89) while still requiring that the actual IP address is your proxy address (e.g., 1.2.3.4)

Figure 28 - Combining RemoteAddr and SocketAddr

Conclusion

Where to begin?

  1. The RemoteAddr option in Front Door WAF shouldn't be listed under IP restrictions because it's really just matching a header value. If Microsoft wanted to include a pre-built X-Forwarded-For match option, they should have labeled it that. Microsoft already gives the option to match a string in a header value, so what value does this RemoteAddr IP matching 'feature' add? Who's idea was it pretend HTTP header matching is an option for IP or region restrictions?
  2. The variable names should be consistent between products (RemoteAddr vs SocketAddr). What is safe and secure in one version of the product should not be the opposite in another. Why would they do that? Perhaps each WAF team was operating in a complete silo, or perhaps the Front Door WAF developers had never actually used the Application Gateway WAF.
  3. The huge security hole that is opened with RemoteAddr should be more clearly documented in the blade where you create the rule. If you're going to offer a faux IP restriction, it should have giant flashing letters saying that it's not to be trusted on its own.

 It's silly to perform WAF filtering on a user-controlled-header and especially silly to call it an IP restriction. People will get the wrong idea that they're actually protected if they select the default option without digging deeper. This is especially true if they have previously used the Application Gateway WAF, where the RemoteAddr variable actually is secure.

Figure 29 - Cmon, it's locked

This is like selling a front door that doesn't actually lock, but it looks as though it does. It will appear to work until somebody actually tries to break in. If an admin wants to filter solely on a user-supplied header, let them build their own string match against the header values, but don't offer it as a type of IP restriction, because it certainly does a poor job at that.

If you use Azure Front Door WAF, please make sure you are matching on the SocketAddr variable!

Special thanks to Aaron James @TrustedSec for his feedback.

Reference

Configure an IP restriction rule with a WAF for Azure Front Door

https://learn.microsoft.com/en-us/azure/web-application-firewall/afds/waf-front-door-configure-ip-restriction