Starting ZAP programmatically in java - sample code please?

2,155 views
Skip to first unread message

gmaran23

unread,
May 26, 2017, 3:16:40 PM5/26/17
to OWASP ZAP Developer Group
I am trying to start ZAP programmatically in java, and I am running in to some problems. I have tried enough for a week, time to let go of my vanity and ask for help.

I have tried many combinations of starting a process in java, ZAP UI shows up and get's stuck on the splash screen. However once the caller program has terminated, the splash screen resumes and ZAP starts successfully. I thought a thread might be blocking operation, so I even tried opening ZAP in a separate thread, still the same issue.

So, what I normally do in python or .net, is to start ZAP programmatically, sleep for a while, then make a web request to http://zap:port and see if get a response. I keep polling till i get a response. After I get a response, then I start working with the ZAP APIs.

I am trying to do the same thing in java, the sample code is attached as well as I am pasting it inline here.

Four different ways to Open ZAP UI programmatically in the methods OpenZAP(); OpenZAP2(); OpenZAP3(); OpenZAP4();.
All of them produce the same result. 

In order to simulate polling the API after invoking a ZAP process, I just sleep for 50 seconds. What I notice is, ZAP starts up with the splash screen, plugins are being loaded (till the log line ..... INFO: loaded filter Replace HTTP response header using defined pattern.) and then the UI freezes, after the thread has completed sleeping for 50 seconds, and the calling process (in this case testfire.java) terminates, the ZAP UI splash screen resumes and ZAP starts.

I have been writing similar code in C#, and in python, ZAP 2.6 starts just fine. I am on windows. I am running the program through Right click --> Run As --. Java Application from eclipse.

What am I missing? Is there a sample code showing how to start ZAP progrmmatically in Java that I can try in my environment?

package TestingZAPStart;


import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;


public class testfire {


 
public static void main(String[] args) throws InterruptedException, IOException {


 
//OpenZAP();
 
//OpenZAP2();
 
OpenZAP3();
 
//OpenZAP4();
 
 
}
 
 
private static void OpenZAP() throws IOException, InterruptedException
 
{
 
String zapExecutableLocation = "C:\\Program Files\\OWASP\\Zed Attack Proxy\\ZAP.exe";
 
String zapWorkingDirectory = "C:\\Program Files\\OWASP\\Zed Attack Proxy";
 
Process p = Runtime.getRuntime().exec(zapExecutableLocation, null, new File(zapWorkingDirectory));
 p
.waitFor();
 
//CheckIfZAPHasStartedOrNot();
 
System.out.println("Going to sleep for some time to simulate polling to see if ZAP has started");
 
Thread.sleep(50000);
 
}
 
 
private static void OpenZAP2() throws IOException, InterruptedException
 
{
 
String zapExecutableLocation = "C:\\Program Files\\OWASP\\Zed Attack Proxy\\ZAP.bat";
 
String zapWorkingDirectory = "C:\\Program Files\\OWASP\\Zed Attack Proxy";
 
String[] command = { "CMD", "/C", zapExecutableLocation };
 
ProcessBuilder pb = new ProcessBuilder(command);
 pb
.directory(new File(zapWorkingDirectory).getAbsoluteFile());
 
Process p = pb.start();
 p
.waitFor();
 
//CheckIfZAPHasStartedOrNot();
 
System.out.println("Going to sleep for some time to simulate polling to see if ZAP has started");
 
Thread.sleep(50000);
 
}
 
 
private static void OpenZAP3() throws IOException, InterruptedException
 
{
 
String zapExecutableLocation = "C:\\Program Files\\OWASP\\Zed Attack Proxy\\ZAP.exe";
 
String zapWorkingDirectory = "C:\\Program Files\\OWASP\\Zed Attack Proxy";
 
ProcessBuilder pb = new ProcessBuilder(zapExecutableLocation);
 pb
.directory(new File(zapWorkingDirectory).getAbsoluteFile());
 
Process p = pb.start();
 p
.waitFor();
 
//CheckIfZAPHasStartedOrNot();
 
System.out.println("Going to sleep for some time to simulate polling to see if ZAP has started");
 
Thread.sleep(50000);
 
}
 
 
private static void OpenZAP4() throws InterruptedException
 
{
 
ZAPStarter zap = new ZAPStarter();
 
System.out.println("Created ZAPStarter");
 
Thread t = new Thread(zap);
 
System.out.println("Created Thread");
 t
.start();
 
System.out.println("Started Thread");
 
//CheckIfZAPHasStartedOrNot();
 
Thread.sleep(50000);
 
System.out.println("Slept for 50 s");
 
}
 
 
private static void CheckIfZAPHasStartedOrNot() throws IOException, InterruptedException {
 
String zapApiUrl = "http://localhost:7070";
 URL url
= new URL(zapApiUrl);
 
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
 connection
.setRequestMethod("GET");
 
int numberOfRetries = 0;


 
while (numberOfRetries <= 30) {
 
try {
 
BufferedReader in = new BufferedReader(new InputStreamReader(
 connection
.getInputStream()));
 
String inputLine;
 
StringBuffer response = new StringBuffer();


 
while ((inputLine = in.readLine()) != null) {
 response
.append(inputLine);
 
}
 
in.close();
 
System.out.println(response.toString());
 
 
System.out.println("Response received from the API endpoint. ZAP should be up by now");
 
break;
 
} catch (ConnectException e) {
 
System.out
 
.println("No response received from the API endpoint. Seems like ZAP has not started yet, let's keep polling");
 
if(numberOfRetries >= 30)
 
{
 
System.out.println("Tried " + numberOfRetries + " of times, couldn't get a response from the ZAP API endpoint");
 
}
 
continue;
 
} finally {
 
++numberOfRetries;
 
Thread.sleep(5000);
 
}
 
}
 
}
}






Starting ZAP...
INFO: Loading extensions
INFO: Installed add-ons: [[id=alertFilters, fileVersion=4], [id=ascanrules, fileVersion=26], [id=bruteforce, fileVersion=6], [id=coreLang, fileVersion=11], [id=diff, fileVersion=7], [id=directorylistv1, fileVersion=3], [id=fuzz, fileVersion=8, version=2.0.1], [id=gettingStarted, fileVersion=6], [id=help, fileVersion=7], [id=invoke, fileVersion=6], [id=jxbrowser, fileVersion=2], [id=jxbrowserwindows, fileVersion=1], [id=onlineMenu, fileVersion=5], [id=pscanrules, fileVersion=19], [id=quickstart, fileVersion=19], [id=replacer, fileVersion=2], [id=reveal, fileVersion=2], [id=saverawmessage, fileVersion=3], [id=scripts, fileVersion=18], [id=selenium, fileVersion=10, version=1.1.0], [id=spiderAjax, fileVersion=17], [id=tips, fileVersion=6], [id=webdriverwindows, fileVersion=2], [id=websocket, fileVersion=12], [id=zest, fileVersion=23], [id=ascanrulesBeta, fileVersion=21], [id=browserView, fileVersion=4], [id=highlighter, fileVersion=6], [id=httpsInfo, fileVersion=7], [id=jython, fileVersion=5], [id=plugnhack, fileVersion=9]]
INFO: Extensions loaded
INFO: loaded filter Change user agent to other browsers. 
INFO: loaded filter Detect insecure or potentially malicious content in HTTP responses.
INFO: loaded filter Detect and alert 'Set-cookie' attempt in HTTP response for modification.
INFO: loaded filter Avoid browser cache (strip off IfModifiedSince)
INFO: loaded filter Log cookies sent by browser.
INFO: loaded filter Log unique GET queries into file:filter\get.xls
INFO: loaded filter Log unique POST queries into file:  filter\post.xls
INFO: loaded filter Log request and response into file: filter\message.txt
INFO: loaded filter Replace HTTP request body using defined pattern.
INFO: loaded filter Replace HTTP request header using defined pattern.
INFO: loaded filter Replace HTTP response body using defined pattern.
INFO: loaded filter Replace HTTP response header using defined pattern.


testfire.java
ZAPStarter.java

kingthorin+owaspzap

unread,
May 26, 2017, 4:32:19 PM5/26/17
to OWASP ZAP Developer Group
This thread might help
https://groups.google.com/forum/m/#!topic/zaproxy-develop/2BAr4w9IwLk

Specifically ZapTools.java

gmaran23

unread,
May 27, 2017, 5:59:09 AM5/27/17
to OWASP ZAP Developer Group
kingthorin,

Thank you! I have been through that thread last week, and in my example, the method OpenZAP2(); has the code inspired by the code in ZapTools.java - https://02108124551050482571.googlegroups.com/attach/155be3e0f3c66fb7/ZapTools.java?part=0.5&view=1&vt=ANaJVrHkT8CdkcWpopekn1UZXC2-vpTu2qgUese3ozmXFGwSyKt1PoiBRUuZi-27OCadZsD5o-SoePFlkqum81qndf9_-B6zYv8XuGZs6LQGgbH3YHsrQbI 

Appreciate your response. If you have any other pointers let me know, I will keep trying from side as well. 

thc...@gmail.com

unread,
May 30, 2017, 9:49:08 AM5/30/17
to zaproxy...@googlegroups.com
Hi.

You need to ensure that the output is consumed, otherwise the process
might block.

If you are not interested in the output you can just redirect it to NUL,
e.g.:
proc.redirectErrorStream(true);
proc.redirectOutput(Redirect.to(new File("NUL")));

or, just add to the command:
> NUL


(Note: not tested in Windows, just Linux with /dev/null.)

Best regards.

thc...@gmail.com

unread,
May 30, 2017, 9:55:56 AM5/30/17
to zaproxy...@googlegroups.com
BTW, you can also close the input stream _after_ starting the process
(which has the same effect).

I'd suggest using the method ClientApi.waitForSuccessfulConnectionToZap
instead of checking ZAP's output, to ensure that it started (more
reliable that way).

Best regards.

gmaran23

unread,
Jun 13, 2017, 1:40:13 PM6/13/17
to OWASP ZAP Developer Group
@thc202 Thank you very much.

Indeed, you are correct. After I redirected the output, ZAP starts just fine. Also ClientApi.waitForSuccessfulConnectionToZap seems pretty neat and reliable. Two lines make all that difference.

private static void OpenZAP3() throws Exception
{
String zapExecutableLocation = "C:\\Program Files\\OWASP\\Zed Attack Proxy\\ZAP.exe";
String zapWorkingDirectory = "C:\\Program Files\\OWASP\\Zed Attack Proxy";
ProcessBuilder pb = new ProcessBuilder(zapExecutableLocation);
pb.directory(new File(zapWorkingDirectory).getAbsoluteFile());
pb.redirectErrorStream(true);
pb.redirectOutput(new File("OWASPZAPOutputStream.txt"));
System.out.println("Trying to invoke the ZAP executable");
Process p = pb.start();
//CheckIfZAPHasStartedOrNot();
System.out.println("Waiting for successful connection to ZAP");
waitForSuccessfulConnectionToZap(60000, 1000); // from ClientApi class of java client api
System.out.println("Seems like we can connect to ZAP APIs now");
}

AWS_SEC

unread,
Jul 19, 2017, 6:33:00 PM7/19/17
to OWASP ZAP Developer Group
@gmaran23,

Is this program to start zap when you run the code only or does it start ZAP and scan a URL on the background?

gmaran23

unread,
Jul 20, 2017, 8:29:29 AM7/20/17
to OWASP ZAP Developer Group
@aws_sec

This program is to start ZAP via a Java. The code in this thread does just that. 

After ZAP has started, if you are looking to scan a URL using the owasp zap java api client, please refer to SimpleExample.java file here - https://github.com/zaproxy/zap-api-java/blob/develop/subprojects/zap-clientapi/src/examples/java/org/zaproxy/clientapi/examples/SimpleExample.java

AWS_SEC

unread,
Jul 20, 2017, 11:46:06 AM7/20/17
to OWASP ZAP Developer Group
ok.. I got that. Just curious why do you want to run a java program to start instead of clicking a zap desktop icon?

gmaran23

unread,
Jul 21, 2017, 3:08:50 AM7/21/17
to OWASP ZAP Developer Group
Just for fun. Automate everything. ha ha!

Let's say you want to test a particular URL every X days. And you would like to schedule a batch job (its a background job, so no manual intervention of starting anything). That batch job would start zap, then initiate the scan for the target url, extract the scan results, and close zap. 

AWS_SEC

unread,
Jul 21, 2017, 4:36:02 PM7/21/17
to OWASP ZAP Developer Group
@gmaran23,

Great. I'm also working on similar stuff using Jenkins plugin for ZAP. Can you share once you complete the project?
Reply all
Reply to author
Forward
0 new messages