Penetration Test for Azure Functions Using ZAP API Scan

Shervyna Ruan
The Startup
Published in
6 min readApr 14, 2020

Contents:

  1. Sample SQL Injection Vulnerability Function App
  2. Penetration Test with ZAP Api Scan (Docker)
    a. Generate Open Api Definition for your Api
    b. ZAP + containerized azure function
    c. ZAP + not containerized azure function
  3. Zap reports
  4. (Penetration Test with OWASP ZAP Desktop)

In this post I will demonstrate how you can run a penetration test against your Azure Functions with Zap api scan (Docker). Using the ZAP docker image allows you to add this penetration testing step into your automated pipelines.

Documentation for ZAP api scan : https://www.zaproxy.org/blog/2017-06-19-scanning-apis-with-zap/

1. Sample SQL Injection Vulnerability Function App

Let me show you a bit about my function app with SQL injection vulnerabilities that I will be using in this post first. Here is the link to my SQL injection vulnerability sample azure function app: https://github.com/shervyna/azure_function_penetration_test

In my postgres DB running on docker, I inserted three user data:

The screenshot on the right below shows that I can do sql injections to my app and get all the user data from DB:

2. Penetration Test with ZAP Api Scan (Docker)

a. Generate OpenApi Definition for your Api

You will need to prepare an OpenApi definition for your function apis. ZAP will get the urls that it needs to scan from this OpenApi definition file. If you don’t have one yet, here is one way that you can generate an OpenApi definition file for your azure functions easily:

Create an API Management service and add your functions api to it. You might have to edit some fields in the API Management before you export the definition(ex: add query params). You can then export the OpenApi definition by right clicking on your api:

Right click on the api -> export

Follow this documentation for more information on how to create api management for your azure function and generate OpenApi definition: https://docs.microsoft.com/en-us/azure/azure-functions/functions-openapi-definition#generate-the-openapi-definition

P.S. If you just want to generate an OpenApi definition and do not plan to use API management for your project, remember to delete the instance so that it doesn’t cost extra money.

b. ZAP + Containerized Azure Function

One issue you might encounter when working with dockerized azure functions is that if your authlevel in function.json is set to “function”, then you will have to change them to “anonymous” before containerizing it, because azure functions will use authlevel=”function” even when developing locally if it is running in the container.

Change the ip and port of the server url in your OpenApi definition file to where your function is running on. In my sample docker app, my function can be accessed from http://localhost:7071, therefore:

Once you finishing changing the url, you can start pulling the ZAP docker image and run a ZAP api scan by using the commands below:

docker pull owasp/zap2docker-weeklydocker run --network="host" \
-v {path_to_your_files}:/zap/wrk/:rw \
-t owasp/zap2docker-weekly zap-api-scan.py \
-t {open_api_file_name} \
-f openapi \
-r zapReport.html

Replace {path_to_your_files} to the path to your folder where you put your OpenAPI definition file. For example, if you named your OpenApi file as openapi.json and put the file under ~/Documents/azFuncPenTest/, then you will run:

docker run --network="host" \
-v ~/Documents/azFuncPenTest/:/zap/wrk/:rw \
-t owasp/zap2docker-weekly zap-api-scan.py \
-t openapi.json \
-f openapi \
-r zapReport.html

If you need to pass in some valid params in order to make a successful request, you can use the formhandler add on as below. Zap will replace the params that you defined in your OpenApi file with the values you passed in from this command.

docker run --network="host" \
-v {path_to_your_files}/:/zap/wrk/:rw \
-t owasp/zap2docker-weekly zap-api-scan.py \
-t {open_api_file_name} \
-f openapi \
-r zapReport.html
-z "-config formhandler.fields.field(0).fieldId=name -config formhandler.fields.field(0).value=amy" \

If you have many params that you want to replace, you can create a property file as below and put it in the same folder with your OpenApi definition file:

{name}.prop

and run:

docker run --network="host" \
-v {path_to_your_files}/:/zap/wrk/:rw \
-t owasp/zap2docker-weekly zap-api-scan.py \
-t {open_api_file_name} \
-f openapi \
-r zapReport.html
-z "-configfile /zap/wrk/conf.prop" \

You can see that ZAP has successfully recognized the SQL injection vulnerability of our app:

P.S. Sometimes zap is not able to generate urls from the open api definition if it only has 1 url defined, and zap just quits without scanning, as shown in the 2 screenshots below. In this case, try executing the same command again then it works fine again. (This issue is tracked here: https://github.com/zaproxy/zaproxy/issues/5936)

(……skipping logs in the middle……)

c. ZAP + Not-Containerized Azure Function

To make zap able to access out of the container, you need to replace the http://localhost:7071/api server url in your OpenApi definition file with http://host.docker.internal:7071/api . Alternatively, you can also replace the server url with the ip of your machine. For mac, you can get the ip of your machine using this command:

ifconfig en0 |awk '/inet / {print $2; }'

Then, replace the server url with the ip as the screenshot below: (or use host.docker.internal)

Then, you can start scanning with the commands below(similar to the previous commands, but you dont need — network=”host” in this case):

docker pull owasp/zap2docker-weeklydocker run -v {path_to_your_files}/:/zap/wrk/:rw \
-t owasp/zap2docker-weekly zap-api-scan.py \
-t {open_api_file_name} \
-f openapi \
-r zapReport.html

3. ZAP reports

A zap report will be generated to the same folder where you put your OpenAPI file. Here is a screenshot of how the zap report looks like:

4. (Penetration Test with OWASP ZAP Desktop)

You might want to use the ZAP docker image if you plan to do an automated penetration test in a CI/CD pipeline (Here is a link that shows you how to add this pentest step to your CI/CD pipeline). However, if you want more information or more control on how zap is scanning your apis during development, you can use the OWASP ZAP Desktop tool.

For example, you can easily get a full list of urls that OWASP ZAP have tried to attacked your app under the active scan tab, as well as the request and response for each urls:

You can also adjust the attack strength from Default to Insane:

If you want to run Fuzzing instead of a scan, you can also do this in the OWASP ZAP desktop easily:

Thanks for reading! :)

--

--