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)
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.
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:
Import the API definition supplied
Identify the URLs to be scanned
Identify the Host app
Actively scan the API using a custom scan profile tuned for APIs
Apply default or custom configuration rules
Report any issues found to the command line
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
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 127.0.0.1(localhost) 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.
ZAP 2.9 Getting started guide
ZAP Docker documentation
OWASP Zap on docker hub
State of Software Security v11
State of Open Source Security Report 2020
ISTQB Foundation Level Syllabus
ISTQB Advanced Security Tester Syllabus
Software Testing, 2019 – Dr. Sanjay Kumar Singh and Dr. Amarjeet Singh
The Basics of Hacking and Penetration Testing: Ethical Hacking and Penetration Testing Made Easy – 2013 - Patrick Engebretson
Human and organizational factors in computer and information security: Pathways to vulnerabilities. Sara Kraemer, Pascale Carayon, John Clem
Continuous Security Testing: A Case Study on the Challenges of Integrating Dynamic Security Testing Tools in CI/CD, Remco v. Buijtenen and Thorsten Rangnau
List of the Top 20 Critical Security Controls by SANS