Automating Authenticated API vulnerability scanning with OWASP ZAP
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
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.
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.
We will use script based authentication for this post. It should look like below after we finish writing our script:
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.
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.
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.
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.
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:
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 ⬇