Security testing is the most important part of Software Development Life Cycle. The same paramount importance goes for API. A secure API is what the world wants and as a development team, it’s obliged to deliver a secure API which doesn’t have any loopholes in terms of security.

We use ZAP tool to evaluate the security status of our APIs.

This blog is specific for the APIs using the token based authentication and way to use the script based authentication for OWASP Zap tool.

ZAP tool download link

In OWASP tool we can add different types of scripts to perform/help the security scans as shown in the screenshot below:

Some of the important types of scripts which can help perform the security scans are as follows:

Authentication Script: Scripts that are invoked when authentication is performed for a Context.To be used, they need to be selected when configuring the Script-Based Authentication Method for a Context.
HTTP Sender Script: Scripts which run ‘inline’, can change every request and response and can be individually enabled.They are invoked for proxied requests and requests that originate from ZAP, for example from the active scanner or spiders.
Session: This allows you to set the session properties.

Context: Contexts are a way of relating a set of URLs together. You can define any contexts you like,but it is expected that a context will correspond to a web application.It is recommended that you define a new contexts for each web application that makes up the system you are testin and set them in scope as you test each one.

ZAP API: ZAP provides an Application Programming Interface (API) which allows you to interact with ZAP programmatically.
The API is available in JSON, HTML and XML formats. A simple web UI which allows you to or via the host and port ZAP is listening on, eg http://localhost:8080/.

The API provides access to most of the core ZAP features such as the active scanner and spider.

Step 1 : Create an Authentication Script to get the token and store it in global variable.

This is the Authentication script using which we can perform the initial call to the service gateway(to get the authentication token) to get the authentication token.

Once we add the script in the ZAP tool, save the token received from the service gateway in a global variable and use it in the subsequent API calls.


Authentication Script

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65
var HttpRequestHeader = Java.type("org.parosproxy.paros.network.HttpRequestHeader");

var HttpHeader = Java.type("org.parosproxy.paros.network.HttpHeader");

var URI = Java.type("org.apache.commons.httpclient.URI");

function authenticate(helper, paramsValues, credentials) {




 print("Authenticating via JavaScript script…");

 var authHelper = new OAuthAuthenticator(helper, paramsValues, credentials);

return authHelper.login();

}

function getRequiredParamsNames(){

 return ["apiurl","clientid","clientsecret","tenantid"];

}

function getOptionalParamsNames(){

 return [];

}




function getCredentialsParamsNames(){

 return ["username", "password"];

}

function OAuthAuthenticator(helper, paramsValues, credentials) {

this.helper = helper;

 this.loginApiUrl = paramsValues.get('apiurl');

 this.ClientId = paramsValues.get('clientid');

 this.ClientSecret = paramsValues.get('clientsecret');

 this.tenantId = paramsValues.get('tenantid');

 return this;

}

OAuthAuthenticator.prototype = {

 login: function () {

  

 var loginToken,

 requestBody = 'grant_type=' + encodeURIComponent('client_credentials') +

                '&client_id=' + encodeURIComponent(this.ClientId) +

                '&client_secret=' + encodeURIComponent(this.ClientSecret),

 response = this.doRequest(

 this.loginApiUrl,

 HttpRequestHeader.POST,

 requestBody

 ),

 parsedResponse = JSON.parse(response.getResponseBody().toString());

 if (parsedResponse.error == 'Unauthorized') {

 print('Authentication failure');

 }

 else {




 org.zaproxy.zap.extension.script.ScriptVars.setGlobalVar("logintoken",parsedResponse.access_token)

 org.zaproxy.zap.extension.script.ScriptVars.setGlobalVar("clientid",this.ClientId)

 org.zaproxy.zap.extension.script.ScriptVars.setGlobalVar("clientsecret",this.ClientSecret)

 org.zaproxy.zap.extension.script.ScriptVars.setGlobalVar("tenantid",this.tenantId)

 }

 return response;

 },

doRequest: function (url, requestMethod, requestBody) {

 var msg,

 requestUri = new URI(url, false);

 requestHeader = new HttpRequestHeader(requestMethod, requestUri, HttpHeader.HTTP10);

 requestHeader.setHeader("Authorization", "Basic "+this.param2);

msg = this.helper.prepareMessage();

 msg.setRequestHeader(requestHeader);

 msg.setRequestBody(requestBody);

 requestHeader.setContentLength(requestBody.length);

 this.helper.sendAndReceive(msg);

return msg;

 }

};

In the auth script, we can add/set the required parameters for the script to work fine. To make the script generic for the environment, we can have the parameters as follows:
apiurl: API URL through which we can get the authentication token.
clientid: Client Id required for the authentication API calls.
clientsecret: Client secret required for the authentication API calls.
tenantid: Tenant Id required for the subsequent API calls.

Regex pattern to indicate whether the authentication performed using the identifier from the response of the Auth API was successful.
The current identifier is “access_token”.

 

Step 2: Write an “HTTP sender” Script to include the token in the subsequent headers for the API calls.

The HTTP sender script interrupts the calls (while doing the spider scan or active scan) and edits the Request/Response headers to achieve the authentication.
The script uses the global variables saved using the Authentication script and adds the required header parts in the subsequent API calls.
As shown in the image below, we need to select the HTTP Authentication Session Management to make use of the HTTP Sender script.

Also, we need to enable the sender script, to add the token in the subsequent calls.


HTTP Sender Script

function sendingRequest(msg, initiator, helper) {

// Debugging can be done using println like this

print(‘sendingRequest called for url=’ + msg.getRequestHeader().getURI().toString());

var loginToken=org.zaproxy.zap.extension.script.ScriptVars.getGlobalVar(“logintoken”);

var clientId=org.zaproxy.zap.extension.script.ScriptVars.getGlobalVar(“clientid”);

var tenantId=org.zaproxy.zap.extension.script.ScriptVars.getGlobalVar(“tenantid”);

 

print(“clientId value: “+clientId);

//set http header

var httpRequestHeader = msg.getRequestHeader();

httpRequestHeader.setHeader(“Authorization”,”Bearer “+loginToken);

httpRequestHeader.setHeader(“X-Client-Id”,clientId);

httpRequestHeader.setHeader(“Raet-Scope-Tenant-Id”,tenantId);

msg.setRequestHeader(httpRequestHeader);

}

function responseReceived(msg, initiator, helper) {

// Debugging can be done using println like this

print(‘responseReceived called for url=’ + msg.getRequestHeader().getURI().toString())

}


 

Step 3: Create a Context, configuring the context with the above-created scripts:

Configure the context with the proper URLs as a Regex. As shown below:

 

Step 4: Using the ZAP API UI to achieve the above-mentioned step using the power-shell scripting:

As shown in the image below, the ZAP when configured to the local host gives us the UI Overview of what all actions we can perform by hitting the specific URLs with proper input values as query strings.

 

And the final URL forexample active scan will look like this:

 

One more example of using the Zap UI, we are enabling the HTTP Sender script using the above-mentioned method and converted into an Azure DevOps task in the pipeline:

Please note that we are parameterizing the values in the URL query string to add the environment-specific variable values.

 

Step 5: Failing the pipeline when the Security issues cross the threshold:

We can configure the threshold values in the OWASP Zap task available in the AzureDevops marketplace:

As shown in the below image, in the Configure Verification section in the task we can provide the threshold values:

When the pipeline executes and the threshold is crossed then we have the configuration to fail the pipeline as there is a breach of thresholds. These thresholds can be changed according to the requirements.

A ZAP report is generated after the scan is completed and this report gives a clear picture of what security concerns behold the API and the measures needed to rectify the same. A sample report is as shown below :

 

LEAVE A REPLY

Please enter your comment!
Please enter your name here

*