Dynamic Security Testing Your Web Application API

By José Carréra

Security Testing involves evaluating a software product in order to identify any flaws and gaps from a security and vulnerability point of view [Singh, 2019]. In order to identify these vulnerabilities companies can apply a mixture of approaches, ideally combining static and dynamic testing techniques.

In this article you will learn how to get a dynamic scan running against your web application API using OWASP ZAP, the world’s most widely used web app scanner, which is free and open source. The tool will be used to trigger a security scan against the restful-booker app, a website built by Mark Winteringham for those wanting to learn more about API testing and tools.

There are multiple ways to run a scan using ZAP, one option is to run using its Desktop app, which is available for Mac OS/X, Windows and Linux. Although that might be a good way to get familiar with the tool and its features, this is not something you can use in your CI/CD environment, which won’t necessarily lend itself to DevOps/DevSecOps.

Taking that into consideration, this article will focus on demonstrating how to trigger a scan using its docker runner. If you are interested, there are also other available options, such as: CLI runner and GitHub actions.

What are static and dynamic analysis?

There are multiple ways of analysing an application for issues. In the context of security testing there is also a clear distinction between static and dynamic analysis techniques/tools that can be applied.

ISTQB states the fundamental difference between a static and a dynamic analysis, the first one relates to evaluating the code without actually executing it, and the latter requires the execution of the software being tested, so it can be evaluated. 

Academics in the software engineering community have spent decades devising multiple ways to unearth flaws from code, but for the most part, the methods fall into one of the two categories of scanning: static application security testing (SAST) and dynamic application security testing (DAST). (State of Software security)

Static Analysis

Allows development teams to identify security vulnerabilities early in the development life cycle, where multiple tools are available for most software languages and allows integration with commonly used IDEs. This setup can become a powerful ally by providing immediate feedback to developers and giving them the opportunity to prevent issues/vulnerabilities from being pushed to the codebase. (ISTQB)

A list of source code analysis tools can be found at OWASP, including tools like: Checkmarx and Sonarqube.

Dynamic Analysis

Commonly referred to as Dynamic Application Security Testing (DAST) evaluates how the application interacts with its environment. It excels at finding issues with server and deployment configuration and authentication issues. [State of Software Security]

Arachni, Wapiti and ZAP are examples of open source tools that perform this type of testing, OWASP also provides a list of vulnerability scanning tools.

Figure 1 - State of Software Security - Static + Dynamic analysis strength

Figure 1, displayed above, presents a quote from the State of Software Security report, where it emphasizes the importance of combining both strategies to maximize the chances of uncovering flaws.

How to run security scan with ZAP’s docker image

ZAP’s docker images provide different ways for us to trigger a scan, which allows us to perform different types of scans: Baseline scan, full scan or API scan.

In this section I’ll focus on describing how to trigger an API scan against the restful-booker app.

The API scan is tuned to focus on attacks that are relevant for APIs defined by OpenAPI, SOAP or GraphQL.

The script will do the following:

  1. Import the API definition supplied

    1. Identify the URLs to be scanned

    2. Identify the Host app

  2. Actively scan the API using a custom scan profile tuned for APIs

    1. Apply default or custom configuration rules

  3. Report any issues found to the command line

    1. Generate html/xml/md/json report, if specified in the run command

In order for you to understand how it works, it is important for us to define how ZAP defines active scan. 

“Active scanning, however, attempts to find other vulnerabilities by using known attacks against the selected targets. Active scanning is a real attack on those targets and can put the targets at risk, so do not use active scanning against targets you do not have permission to test.”  (ZAP Getting started Guide)

Thanks to having  docker installed, running ZAP’s image and triggering an API scan is a relatively quick and simple task.


There are some requirements for you to be able to trigger a scan using ZAP’s Docker container, which are:

  • Docker is installed

  • Application to be tested has a swagger/OpenAPI file available through

    • An endpoint; or

    • A local file

  • Existing swagger/OpenAPI file is valid

    • If file is invalid (ex. contains syntactical errors) it will fail to import its definition

    • Several packages and online tools are available to help with this validation, for example: Swagger Editor, by Smartbear

  • Application is running (Locally or in a test environment)

  • ZAP’s Docker container is able to connect to the running app

Running a scan

In this section we describe the steps to get your scan running. A fork of the restful-booker-app, which contains a valid swagger file is available here, if you want to try the same steps.

  • Start restful-booker-app locally

docker-compose up
  • Pull ZAP’s docker image, using stable release

docker pull owasp/zap2docker-stable
  • Trigger API Scan

docker run --network=host -v $(pwd):/zap/wrk/:rw --tty owasp/zap2docker-stable zap-api-scan.py -t ./swagger.yaml -f openapi

Docker command options breakdown:

  • --network=host Points in the ZAP docker container to point to the host machine.

  • -v(pwd):zap/wrk/:rw – Shares the files in the current directory with the container, this allows it to access the local swagger.yaml file.

  • --tty owasp/zap2docker-stable zap-api-scan.py – Allocates a pseudo-TTY, allowing command to execute and its output to be shown in the terminal.

  • -t ./swagger.yaml – Sets the target API definition to be scanned, in this example this is a path to a local file.

  • -f openapi – Specified the format of the API

Modifying the run command to generate an html report with the results

docker run --user=root --network=host -v $(pwd):/zap/wrk/:rw --tty owasp/zap2docker-stable zap-api-scan.py -t ./swagger.yaml -f openapi -r api-scan-report.html
  • --user=root - Specifies that the container will run as root user, this is used to allow it to write the html report to the disk.

  • -r api-scan-report.html – Specifies the file to write the full ZAP report 

Understanding the scan results 

While the security scan is running, the terminal will continue printing information regarding its execution. Figure 1, displayed below, shows the short output option which is available by adding -s to the run command explained in the previous section. The last printed line will contain a summary of the results indicating a total number per category. 

Figure 2 - Terminal short output format when adding -s to run command

If you do not specify the -s flag, by default execution will print to the console information related to the rules that were tested and passed, alongside that it will also display example URLs that were attempted. The screenshot, presented next, contains a partial view of the terminal, which once again ends with the summary results.

Figure 3 - Screenshot of terminal output with default format, which displays PASS data and example URLs

As mentioned before, adding -r property will indicate that an html report should be generated at the end of the scan. The next image displays how the HTML report presents a summary of the alerts by risk level and its short description.

Figure 4 - Screenshot of HTML report summary

The HTML report will also contain further details on each of the alerts that were raised. This will contain details of the HTTP request that was performed, an indication of a possible solution and references to the vulnerability definition across different data sources. A screenshot of one of the alerts raised is presented on figure 4.


Figure 5 - Screenshot of Alert detail on the HTML report

Configuring set of rules applied

When a scan is triggered, ZAP will use its default rule set, but this can be modified by specifying the -c option when running your docker container.

Figure 5 contains an example of some of the rules that are applied, where we can see its severity and short description. Therefore, in order to have the rules customized all that is needed is for this file to exist locally, so you can specify its path when running docker. This allows you to ignore rules that are not meaningful for your circumstances or simply adjust its severity. 

Figure 6 - Example subset of applied rules and its default configuration

The block below shows how the command would look like when specifying your local customized rules.

docker run --user=root --network=host -v $(pwd):/zap/wrk/:rw --tty owasp/zap2docker-stable zap-api-scan.py -c ./api-scan-conf.config -t ./swagger.yaml -f openapi

Triggering the security scans is just the beginning

Getting started with running security tests is definitely the easiest part of the job, alongside that it is important that the security scanning is also part of your continuous integration cycle, it is easy to access and does provide quick feedback for the development team. There is also the need that security issues are treated like any other requirements, so it doesn’t just sit at the bottom of your team’s backlog.

Fixing security issues identified by the scanning tools is not always an easy task, which can also lead to a steep learning curve for everyone involved. Understanding the terminology used, properly triaging through the findings and implementing possible solutions might require more effort than initially imagined.

A good way to start is by considering the severity defined by the report and following up on the references given. Those references will allow you and your team to learn more about the identified threat, so you can make a well informed decision on the urgency of a given fix. References also commonly include possible approaches on how to fix the raised alert, which can also be very handy. Finally, just like other non-functional areas in software development, security issues are often treated without the deserved priority, getting the team to understand the risks and making the conversation about security part of our routine can help us enable this to stop happening.

This article described some basic concepts on security testing and how to use OWASP ZAP’s docker container to run dynamic scans against an application API. All the references mentioned are listed below, alongside other resources that might be useful on getting started.


You might also be interested in 

Automated Security Testing Using Zap Python API

About the Author

José Carréra is from Brazil, where he graduated in computer science in 2007 and completed his masters in 2009. Professionally, he has been working on quality related roles since 2006. Moved to the UK in 2015, where currently works as a Senior SDET at comparethemarket.com.