Scaling Security Testing by OWASP ZAP API

Asaf Sahar
AppsFlyer Engineering
4 min readDec 12, 2021

My journey of learning about additional security vulnerabilities continues with Reflected Cross-Site Scripting (XSS). To see how this journey started, you can go to my first blog post here. To learn what XSS is, how to do automated tests using OWASP ZAP, and how to make your web applications more secure, continue reading.

There are several types of XSS, but I will focus on the easiest one to identify.

Reflected Cross Site Scripting

XSS is a web vulnerability that allows an attacker to inject malicious code (JavaScript) into HTML pages, which is then executed inside a victim’s browser.

Example

This vulnerability has an impact on the client side. Let’s say for example that we have a website with a search option in the homepage, and you are looking for the logo of your favorite soccer team. When you click on search, a request similar to this will be sent to the server:

https://www.example.com?search=realmadrid.png

The search text will appear in the query string parameter ‘search’ of the request, as in the diagram below.

The user will get HTML as a response, with information about their favorite soccer team.

Let’s say, however, that you aren’t a soccer fan, but someone with malicious intentions. In this case, you could try to enter the following script:

<script>alert(1)</script>

Now the search request that is sent to the server will look like this:

https://www.example.com?search=realmadrid.png”><script>alert(1)</script>

If this website is vulnerable to XSS, then the script that was entered through the search box will be part of the HTML that returns to the user. The browser will render it, and then a pop-up with the text ‘1’ will appear.

Once we understand that the website is vulnerable to XSS, we can achieve any of the following:

  • Steal users’ data
  • Hijack accounts
  • Change a site’s layout
  • Add a malicious trojan login panel.

Finding an Automated Solution

When I started to look for an automated solution for XSS, I found several solutions on GitHub that suggested doing an XSS scan. But they did not meet my expectations. The run time was too long and I even got some false positives.

After additional investigation, I discovered OWASP ZAP API. ZAP is one of the world’s most popular free security tools for helping you find security vulnerabilities in your applications. It has a desktop version for manual use, or an API that you can integrate with instead.

In one of my previous posts, I wrote about the automated Python package that I created to do security tests for IDOR and SSRF vulnerabilities.

Each quality team consumes that package and uses it to test their service endpoints (URLs) for security vulnerabilities. The package offers the ability to define an endpoint, by providing details such as the request method, GET or POST, the path of the request, the headers used, and more.

Security test package usage

I decided to integrate ZAP API into the security tests package, since it provided me the opportunity to run different vulnerabilities easily and enabled us to scale with the testing suites.

ZAP runs in a Docker container that uses an owasp-zap image. Each test case runs versus the same ZAP API instance, having a unique context for each scan that tells ZAP on which endpoint to run the scan and with which account details (username and password) to run requests.

For a POST request we need to provide ZAP the details of the request. I used the option to upload a swagger file to the ZAP using ‘zap.openapi.import_url’. For GET requests, I use the ZAP Spider scan, to automatically discover new resources (URLs) on a particular site.

In this image you can see how a quality engineer defines an endpoint for the test:

Example of test in Python using Pytest

Now for the best part. Additional vulnerability testing can be added simply by updating the ‘scan_types’ parameter with an additional vulnerability; for example, SQL Injection which will look like:

scan_types = [“XSS”, ”SQL Injection”] 

Using @pytest.mark.parametrize, I can run the same test case — but ZAP will check for a different vulnerability each time!

Note that you will also need to create the policy in the ZAP instance. This can be done using the ZAP addScanPolicy API method, or in your code.

Just think of how low of an effort is required from a quality team to create impressive security regression tests with a single test case definition.

High level design

Thank you for taking the time to read my post. I hope you will read my upcoming post as well, where I plan to cover SQL Injection vulnerabilities in more detail.

See you then!

--

--