Recently Ive been helping with a few implementations for Azure Frontdoor in front of API Management and I wanted to talk a little about the WAF implementation. WAF can help protect your API if its running through Frontdoor first and you can apply WAF rules before your API runs so you can off load some of the DDOS protection and also use the WAF rules to check for vulnerabilities before it gets to your code. This is all great stuff but the documentation is pretty high level and ive had a few people ask about this so I thought it would be good to put together a few postman test examples to show what the WAF can and can not do.

In this first post ill talk about using the original Frontdoor SKU with WAF and then ill do a followup part 2 where we will look at the new Frontdoor Premium SKU and see what extra things it can do.

First lets take a quick look at the architecture which is shown below.

I am just going to use the out of the box Echo API which API Management gives you which just echo’s back the request you sent it. Im then going to put Frontdoor with routing rules to forward messages to APIM and then test it with Postman. I will configure the WAF on frontdoor and then send a bunch of postman requests.

In this post I want to focus on the behaviours to expect in your postman tests which will show what Frontdoor and WAF will do. There isnt really any custom configuration of the WAF. Ive just added it as a policy on the Frontdoor and ive got the settings on the policy as shown below.

In this post I am using the Microsoft_DefaultRuleSet_1.1 or DSR1.1.

Tests

In the test cases I want to show which scenarios will work and your WAF will protect your API and I also want to show which scenarios it will not cover.

Check GET request works – Pass

This is a basic test to just check the Get method on the echo API will work

Expected BehaviourWe expect an HTTP 200 response
Actual BehaviourThis should work fine and WAF will let this request pass through

Request:

GET /echo/resource?param1=sam1ple&param2=1 HTTP/1.1
Host: {mikeshost}.com
Ocp-Apim-Subscription-Key: {MikesKey}

SQL Injection in Query String should fail with apostrophe – Pass

This test will use an ‘ character in the query string parameter which should trigger a SQL injection WAF rule to block the request.

Expected BehaviourThe WAF should block the request
Actual BehaviourRequest blocked by WAF with HTTP 403 response

Request:

GET /echo/resource?param1=sam1ple&param2=' HTTP/1.1
Host: {mikeshost}.com
Ocp-Apim-Subscription-Key: {MikesKey}

SQL Injection in Query String should fail with 1=1 – Pass

This is another test which should trigger the SQL injection rule. We will use a 1=1 clause in the SQL query which should trigger the rule.

Expected Behaviour The WAF should block the request
Actual Behaviour Request blocked by WAF with HTTP 403 response

Request:

GET /echo/resource?param1=sam1ple&param2=SELECT * FROM Users WHERE UserId = 105 OR 1=1; HTTP/1.1
Host: {mikeshost}.com
Ocp-Apim-Subscription-Key: {MikesKey}

Check PUT request works – Pass

This is a basic test for the ECHO api put operation to check it works.

Expected BehaviourThis should be successful and not blocked by WAF and should return a response
Actual BehaviourHTTP 200 and we are displayed the request we sent

Request:

PUT /echo/resource HTTP/1.1
Host: {mikeshost}.com
Ocp-Apim-Subscription-Key: {MikesKey}
Content-Type: application/json
Content-Length: 100

{
    "vehicleType": "train",
    "maxSpeed": 125,
    "avgSpeed": 90,
    "speedUnit": "mph"
}

SQL Injection in Query String should fail with apostrophe – Pass

In this case I am sending a PUT request but I will include an apostrophe in a query string parameter which should trigger the WAF rules.

Expected BehaviourWAF will block the request
Actual BehaviourHTTP 403 and a message that WAF blocks the request

Request:

PUT /echo/resource?test=' HTTP/1.1
Host: {mikeshost}.com
Ocp-Apim-Subscription-Key: {MikesKey}
Content-Type: application/json
Content-Length: 100

{
    "vehicleType": "train",
    "maxSpeed": 125,
    "avgSpeed": 90,
    "speedUnit": "mph"
}

SQL Injection in Query String should fail with 1=1 – Pass

In this case I am replicating the test we did earlier but this time with a PUT request rather than the GET request. I am including the 1=1 to try to trigger the SQL injection rule.

Expected BehaviourWAF will block the request
Actual BehaviourHTTP 403 with a message that WAF blocks the request

Request:

PUT /echo/resource?test=SELECT * FROM Users WHERE UserId = 105 OR 1=1; HTTP/1.1
Host: {mikeshost}.com
Ocp-Apim-Subscription-Key: {MikesKey}
Content-Type: application/json
Content-Length: 100

{
    "vehicleType": "train",
    "maxSpeed": 125,
    "avgSpeed": 90,
    "speedUnit": "mph"
}

SQL Injection in plain text body should fail with 1=1 – Fail

In this request we are using a plain text request with a SQL statement which we hope will trigger the WAF rule.

Desired BehaviourWe would like the WAF rule to trigger and block the request
Actual BehaviourThe request is not blocked and is forwarded to APIM and we get a 200 response code and the text we sent is returned back

Request:

PUT /echo/resource HTTP/1.1
Host: {mikeshost}.com
Ocp-Apim-Subscription-Key: {mikeskey}
Content-Type: text/plain
Content-Length: 46

SELECT * FROM Users WHERE UserId = 105 OR 1=1;

SQL Injection in Json body should fail with 1=1 – Fail

In this test we will send a json message with a sql statement in the json message.

Desired BehaviourWe hope that this will trigger the WAF rule and the request is blocked
Actual BehaviourThe request is not blocked and it is forwarded to the APIM where the Echo API is returns the message to us

Request:

PUT /echo/resource HTTP/1.1
Host: {mikeshost}.com
Ocp-Apim-Subscription-Key: {mikeskey}
Content-Type: application/json
Content-Length: 143

{
    "vehicleType": "train",
    "maxSpeed": 125,
    "avgSpeed": 90,
    "speedUnit": "SELECT * FROM Users WHERE UserId = 105 OR 1=1;"
}

SQL Injection in form body should fail – Pass

In this request we will send a x-www-form-urlencoded request to the API. The request will include a SQL injection in the SQL statement which we hope will trigger the SQL injection rules.

Expected BehaviourThe request is blocked by WAF
Actual BehaviourThe request is blocked by WAF and we get an HTTP 403 response

Request:

PUT /echo/resource HTTP/1.1
Host: {mikeshost}.com
Ocp-Apim-Subscription-Key: {mikeskey}
Content-Type: application/x-www-form-urlencoded
Content-Length: 74

SQL=SELECT%20*%20FROM%20Users%20WHERE%20UserId%20%3D%20105%20OR%201%3D1%3B

XSS in form parameter should fail – Pass

In this request we will send an x-www-form-urlencoded request which will contain a potential XSS attack which we hope will trigger the WAF rules.

Expected BehaviourThe request is blocked by WAF
Actual BehaviourWe get an http 403 response and the request is blocked by WAF

Request:

PUT /echo/resource HTTP/1.1
Host: {mikeshost}.com
Ocp-Apim-Subscription-Key: {mikeskey}
Content-Type: application/x-www-form-urlencoded
Content-Length: 93

test=%3Cscript%3Ealert(%E2%80%9CThis%20is%20a%20XSS%20Exploit%20Test%E2%80%9D)%3C%2Fscript%3E

XSS in Json body should fail – Fail

In this test we will send a request which is a json message which contains text which could be a potential XSS attack. We hope that this will trigger the WAF rule.

Desired Behaviour The request is blocked by WAF
Actual BehaviourThe request is not blocked and is forwarded to APIM and it is echo’d back to us and we get an HTTP 200 response.

Request:

PUT /echo/resource HTTP/1.1
Host: {mikeshost}.com
Ocp-Apim-Subscription-Key: {mikeskey}
Content-Type: application/json
Content-Length: 149

{
    "vehicleType": "train",
    "maxSpeed": 125,
    "avgSpeed": 90,
    "speedUnit": "<script>alert(“This is a XSS Exploit Test”)</script>"
}

Summary

In this post I wanted to help you easily see what you can do with the out of the box WAF rules and also what types of request it will not block. The documentation is quite vague on describing this so I thought that some examples showing some of the common use cases would help to visualise this.

The key takeaways from this post are that you can effectively use the WAF rules to check for SQL injection and XSS attempts in the query string and in x-www-form-urlencoded requests but the rules can not check for json message bodies.

If you want to checkout my postman collection to try this for yourself you can get it from here:

https://github.com/michaelstephensonuk/CodeSnippets/blob/main/Frontdoor-WAF/Frontdoor%20-%20Original.postman_collection.json

 

Buy Me A Coffee