OWASP ZAP (Zed Attack Proxy) is an open source dynamic application security testing (DAST) tool. It is available here and has a website with documentation here. I recently encountered it when looking for open source security test tools to embed in a CI/CD pipeline (here). I was surprised by how versatile this tool is. In this blog post I’ll summarize several ways how you can use it.
I’ve used a small Spring Boot service to illustrate the different ways you can use OWASP ZAP. You can find it in DockerHub here and in GitHub here. To create a Docker network and start the application, do the following;
docker network create demo-network docker run --network demo-network --name spring-boot-demo -p 8080:8080 maartensmeets/spring-boot-demo
OWASP ZAP CLI can be run from a container (read here). You can for example execute a scan like listed in the command below. Mind that by default only High severity issues are displayed. That’s why there is ‘-l Low’ at the end.
docker run --network demo-network -i owasp/zap2docker-stable zap-cli quick-scan --spider --self-contained --recursive --start-options '-config api.disablekey=true' http://spring-boot-demo:8080/rest/demo/ -l Low
This can give you output like;
[INFO] Starting ZAP daemon [INFO] Running a quick scan for http://spring-boot-demo:8080/rest/demo/ [INFO] Issues found: 1 +---------------------------------------+--------+----------+-----------------------------------------+ | Alert | Risk | CWE ID | URL | +=======================================+========+==========+=========================================+ | X-Content-Type-Options Header Missing | Low | 16 | http://spring-boot-demo:8080/rest/demo/ | +---------------------------------------+--------+----------+-----------------------------------------+ [INFO] Shutting down ZAP daemon
Using a GUI
Webswing allows you to run OWASP ZAP from a container with a GUI which you can open in a browser. Read here.
docker run -u zap -p 8081:8080 -p 8090:8090 --network demo-network -i owasp/zap2docker-stable zap-webswing.sh
Now you can go to http://localhost:8081/zap to open the GUI.
You can perform an automated scan from the GUI to quickly scan a specific endpoint. This will yield results similar to the zap-cli example above.
You can also use port 8090 of the container as proxy. URLs which pass the proxy will be listed in the GUI and you can easily attack all detected endpoints.
You will most likely get a warning indicating the CA is not trusted by your browser. You can import the ZAP root CA certificate to permanently to avoid the warning in the future. Read the following here on how to do that.
Next you can open the service endpoint via the ZAP proxy
You can also see the request and response in the ZAP GUI.
As you can see, this gives more information than only a scan of a specific endpoint since OWASP ZAP can now look at the traffic between browser and service. Here it detects an additional header missing. It is also possible to set breakpoints and alter requests. In addition, there is scripting support available. See for example here.
Part of the CI/CD process
There are various ways in which you can embed an OWASP ZAP scan in your CI/CD process. Since it is a DAST scan, it requires a running application. Also ZAP itself needs to be running in order to execute scans. The specific method is highly dependent on your environment.
Depending on your environment you can spin up ZAP as a container or install ZAP yourself by for example using the Linux installer which you can find here.
Start and stop
Ideally, you want to start ZAP, execute a scan and clean-up. This in order not to have it claim resources while not in use (and saving you money, especially in a cloud environment).
You can use a plugin such as this one to start and stop a ZAP container or a local installation. If the plugin does not suffice, it is easy to script it yourself as part of your pipeline.
Once your application and ZAP are running, there are various ways to initiate a scan. You can access its API (directly, using the CLI or by using for example a plugin) and ask it to do scans of specific endpoints. Using a plugin is relatively easy.
You can embed a ZAP scan in a Selenium test so you can first proxy requests and than analyse the proxied traffic (passive) and attack those endpoints (active). See for example the following presentation here on how to set that up. This requires a bit more work.
Process ZAP results
If you want to integrate the results of the scan in for example SonarQube, you can use the following plugin here. You can also integrate it in Azure DevOps by transforming the result XML file to a format Azure DevOps understands (see here).
I created a docker-compose.yml file which starts ZAP and my test application here. Next from the pom.xml file (Maven, it is a Java application) I use a plugin during the build process to access ZAP using the API and initiate a scan. The result is published to Jenkins and imported in SonarQube (as you can see in the pipeline here). A setup such as this one is of course not viable for real-life use since the ZAP spin-up and spin-down are not part of it (I start everything at the same time when I do docker-compose up -d).
I was happily surprised by how many integration options OWASP ZAP has and the different ways you can run ZAP. It has a GUI, a CLI and a powerful API. In addition there are several plugins available to call ZAP from for example Maven builds. This makes it easy to embed it into any CI/CD pipeline to dynamically scan endpoints. The proxy option in combination with an automated GUI test is very powerful. It allows ZAP to first do a passive scan of traffic (identifying endpoints, analyzing requests/responses) and with the information obtained, to do an active attack. Such elaborate scans can take a while though, but they can provide a lot of information on potential vulnerabilities. In my opinion, there is no good reason not to embed OWASP ZAP in your software delivery process to make the world a little bit safer by performing automated security tests.