Automating Authenticated API vulnerability scanning with OWASP ZAP

Tanvir Ahmed
Dec 31, 2018 · 6 min read

Performing authenticated application vulnerability scanning can get quite complex for modern applications or APIs. The problem gets worse if you want to integrate with your CICD pipeline. Even commercial vulnerability scanners struggle with this problem. Over the years OWASP ZAP community has done an excellent job of extending ZAP’s features and functionalities. However, I must admit ZAP has a steep learning curve but once you get over that hurdle you will love ZAP. One of the best functionality in ZAP is it’s scripting capabilities. You can write your own scripts in python, JavaScript, ZEST or Ruby. In this post we will explore how we can handle complex authentication using this scripting functionality. This post is for intermediate users who already know how ZAP works and novice programming skill is required.

In this post, we will take the demo vulnerable application Hackazon. Hackazon provides vulnerable APIs which we will use for this demo. You can download the vulnerable docker image of the Hackazon application and the scripts we will use in this tutorial here. This post will focus on API testing but the scripting knowledge will be similar to web applications.

First, let’s analyse our target and take a look at how the authentication works for Hackazon API.

First, you have to make a usual Basic-Authorization request, and in response you will receive the token. Then just send this token in every request in Authorization header or as a request parameter Token.

Step 1: Authorization: Basic dGVzdF91c2VyOjEyMzQ1Ng== On every basic authorization request without _token parameter new token will be generated. You can have only one token, so if you use it in several places, do not call basic authorization requests, do it only once, and then use received token.

Step 2 (and consequent):

Authorization: Token af538baa9045a84c0e889f672baf83ff24

You can find more information about the REST API here: https://github.com/rapid7/hackazon/blob/master/REST.md

Fig : Client authentication flow with Hackazon API endpoint

ZAP will first do basic authenticate to the /api/auth endpoint. After the basic authentication hackazon app will send an authorization token in the JSON response body. ZAP script will extract the token and subsequent request to the endpoint will include this token as part of the request header. We will need another httpsender script to add this token to each subsequent requests.

Fig: Request containing Authorization header with the correct token.

To set up the vulnerability scan settings will take the following steps:

1. Create a ZAP context

2. Create a ZAP scan policy

3. Write custom ZAP script for authentication and proxy.

4. Automate testing using:

a. Python script

5. Review the scan results

Create a ZAP context

We will use ZAP context to configure the application’s profile. I included the context file (Hackazon_API_Context.context) file for this demo in the github repo above. The important sections of the context are structure, authentication, technology and user.

Fig: Create a new context

We will use script based authentication for this post. It should look like below after we finish writing our script:

Fig: ZAP authentication menu on the context section
Fig: Technology menu on the context section
Fig: Users menu on the context section

Create a ZAP Scan policy

In order to scan efficiently, we will tweak the scan profile. For example, we only want to do injection test and also we know that the database is MySQL and hence would like to test MySQL related SQL injection payloads only. This will increase the performance of the scan significantly and help with false positives.

Fig: Scan policy

ZAP custom script for authentication and proxy

ZAP provides authentication mechanism for basic use cases, for example: form based authentication, etc. But authentication is not one size fits all. Everyone tries to do it differently. For example in this Hackazon API case, you need to do basic authentication, obtain a token and pass this token on your request header on each request to access the authenticated resource. Hence we need to go through this painful process of writing custom authentication and httpsender scripts.

The authentication script will be tied with the context defined earlier. For example: you can pass authentication url, target urls, username or password field, etc from the context menu. For our case, we just need the authentication url.

N.B: You need to download Python engine from ZAP Marketplace to write python scripts it’s not included by default.

Similarly user credentials, api keys,etc can be passed to the script from users menu on the context screen.

This credentials can be obtained from the authentication scripts as shown below.

def getCredentialsParamsNames():

return jarray.array([“Username”, “Password”], java.lang.String);

username = quote(credentials.getParam(“Username”)).encode(‘utf-8’);

password = quote(credentials.getParam(“Password”)).encode(‘utf-8’);

Finally after you finish writing the authentication script it should look like below.

Fig: Authentication script

Authentication script does the first part which obtains the token. Now we need to use this token for each subsequent requests. Hence we use a global variable (hackazon_token) and pass this variable to http_sender script which intercepts all requests (including from Active scan, Spidering, etc) and add this token to those requests.

Fig: http_sender script

Automated testing using python script:

I included a python script which can automate the entire scanning process. I wont go through this as the script is pretty self explanatory.

Once the scan is completed you will see the following results:

ZAP output
HTML output

You can also include this scan in your CI pipeline. Unfortunately, the Official ZAP Jenkins plugin was giving me issues with the httpsender script. The httpsender script on the jenkins setup doesn't seem to change request headers as it does on the UI or python script.

I hope you found this tutorial useful. Few claps never hurt anybody 😊 <script>action(“clap”)</script>

Feel free to provide any comment or feedback.

Join our community Slack and read our weekly Faun topics ⬇

Faun

The Must-Read Publication for Aspiring Developers & DevOps Enthusiasts. Medium’s largest DevOps publication.

Tanvir Ahmed

Written by

Cyber mercenary | Sydney |https://www.linkedin.com/in/tanvirahmed11/

Faun

Faun

The Must-Read Publication for Aspiring Developers & DevOps Enthusiasts. Medium’s largest DevOps publication.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade