-1

I am trying to use a script to scan a target and perform an active scan as a proof of concept. I have worked the implementation below and i can not get it to work i am not sure why it will not work? I have Zap2Docker running and can access it via the api, i can also access via the gui scanning the target from the gui works fine, however my script will not work over the api, see it below:

import org.zaproxy.clientapi.core.ApiResponse;
import org.zaproxy.clientapi.core.ApiResponseElement;
import org.zaproxy.clientapi.core.ApiResponseList;
import org.zaproxy.clientapi.core.ClientApi;

import java.util.List;

public class Spider {

    private static String ZAP_ADDRESS;// = "ZAPContainerIp";
    private static int ZAP_PORT;// = 8090;
    // Change to match the API key set in ZAP, or use NULL if the API key is disabled
    private static String ZAP_API_KEY;// = "change me";
    // The URL of the application to be tested
    private static String TARGET;// = "https://targetip.com";
    private static boolean scanComplete;

    public static void main(String[] args) {
        ZAP_ADDRESS = args[0];
        ZAP_PORT = Integer.parseInt(args[1]);
        ZAP_API_KEY = args[2];
        TARGET = args[3];
        ClientApi api = new ClientApi(ZAP_ADDRESS, ZAP_PORT, ZAP_API_KEY);

        try {
            // Start spidering
            System.out.println("Spidering target : " + TARGET);
            ApiResponse resp = api.spider.scan(TARGET, null, null, null, null);
            String scanID;
            int progress;

            // The scan returns a scan id to support concurrent scanning
            scanID = ((ApiResponseElement) resp).getValue();
            // Poll the status until it completes
            while (true) {
                Thread.sleep(1000);
                progress = Integer.parseInt(((ApiResponseElement) api.spider.status(scanID)).getValue());
                System.out.println("Spider progress : " + progress + "%");
                if (progress >= 100) {
                    scanComplete = true;
                    break;
                }
            }
            System.out.println("Spider completed");
            // If required post process the spider results
            List<ApiResponse> spiderResults = ((ApiResponseList) api.spider.results(scanID)).getItems();
            if (scanComplete) {
                ActiveScan activeScan = new ActiveScan();
                activeScan.attack(ZAP_ADDRESS, ZAP_PORT, ZAP_API_KEY, TARGET);
            }


        } catch (Exception e) {
            System.out.println("Exception : " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Scan:

import org.zaproxy.clientapi.core.ApiResponse;
import org.zaproxy.clientapi.core.ApiResponseElement;
import org.zaproxy.clientapi.core.ClientApi;

import java.lang.annotation.Target;
import java.nio.charset.StandardCharsets;

public class ActiveScan {

    private int zapPort;// = 8090;
    private String zapApiKey;// = null;
    private String zapAddress;// = "localhost";
    private String target;// = "https://targetip.com";

    public ActiveScan(int zapPort, String zapApiKey, String zapAddress, String target) {
        this.zapPort = zapPort;
        this.zapApiKey = zapApiKey;
        this.zapAddress = zapAddress;
        this.target = target;
    }

    public ActiveScan() {
    }

    public void attack(String zapAddress, int zapPort, String zapApiKey, String target){


        ClientApi api = new ClientApi(zapAddress, zapPort, zapApiKey);

        try {
            System.out.println("Active Scanning target : " + target);
            ApiResponse resp = api.ascan.scan(target, "True", "False", null, null, null);
            String scanid;
            int progress;

            // Scan returns a scan id to support concurrent scanning
            scanid = ((ApiResponseElement) resp).getValue();
            // Poll status until it completes
            while (true) {
                Thread.sleep(5000);
                progress =
                        Integer.parseInt(
                                ((ApiResponseElement) api.ascan.status(scanid)).getValue());
                System.out.println("Active Scan progress : " + progress + "%");
                if (progress >= 100) {
                    break;
                }
            }

            System.out.println("Active Scan complete");
            // Print vulnerabilities found by the scanning
            System.out.println("Alerts:");
            System.out.println(new String(api.core.xmlreport(), StandardCharsets.UTF_8));

        } catch (Exception e) {
            System.out.println("Exception : " + e.getMessage());
            e.printStackTrace();
        }
    }

}

When run i get the error:

java -jar WafTestSuite.jar "zapurl" "8090" "change-me-9203935709" "10.10.10.254:3000"; Spidering target : 10.10.8.254:3000
Exception : java.net.SocketException: Unexpected end of file from server
org.zaproxy.clientapi.core.ClientApiException: java.net.SocketException: Unexpected end of file from server
at org.zaproxy.clientapi.core.ClientApi.callApiDom(ClientApi.http://java:366)
at org.zaproxy.clientapi.core.ClientApi.callApi(ClientApi.http://java:350)
at org.zaproxy.clientapi.gen.Spider.scan(Spider.http://java:242)
at Spider.main(Spider.java:28)
Caused by: java.net.SocketException: Unexpected end of file from server
at sun.net.http://www.http.HttpClient.parseHTTPHeader(Unknown Source)
at sun.net.http://www.http.HttpClient.parseHTTP(Unknown Source)
at sun.net.http://www.http.HttpClient.parseHTTPHeader(Unknown Source)
at sun.net.http://www.http.HttpClient.parseHTTP(Unknown Source)
at sun.net.http://www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at sun.net.http://www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at java.net.HttpURLConnection.getResponseCode(Unknown Source)
at org.zaproxy.clientapi.core.ClientApi.getConnectionInputStream(ClientApi.http://java:399)
at org.zaproxy.clientapi.core.ClientApi.callApiDom(ClientApi.http://java:364)

I would appreciate any help, thanks.

docker dev
  • 91
  • 3
  • 10

2 Answers2

1

By default ZAP does not accept remote connections to the API. You need to enable them and set a suitable API key (or disable it). More details in this FAQ: https://www.zaproxy.org/faq/how-can-i-connect-to-zap-remotely/

Simon Bennetts
  • 5,479
  • 1
  • 14
  • 26
  • Thank you for taking the time to look at this, I have since tried this as i was trying to negate any possible issues, I have done both, configuring an API key and passing it, and disabling the API key and passing NULL, however i still receive the same error on both occasions – docker dev Apr 01 '20 at 14:46
  • In that case look in the zap.log file - that should give a more detailed message. – Simon Bennetts Apr 01 '20 at 15:41
  • Hi i can see you have a lot of experience, i will try to have a look at the log file, however from looking at the script can you see anything glaringly wrong, with the processes and the the calls to the API? the line:SocketException: Unexpected end of file from server seems confusing to me. Really appreciate your help Simon. Thanks – docker dev Apr 02 '20 at 12:53
  • Well, I am the ZAP project lead :P "Unexpected end of file" is nearly always a config issue - ZAP is silently rejecting your request because it thinks its not permitted. The easiest way to debug this is to look in the zap.log file - thats what I would do if this happened to me. – Simon Bennetts Apr 02 '20 at 13:53
  • Zap Royalty!, Thanks yes config error the endpoint was not configured to allow my access from my Ip. Pretty sure thats what solved the issue your help was much appreciated. Now just to make sure all other config is correct. If you do know of, say a check list of what needs to be configured at zap end to scan your QWASP juice shop that would be a god send? i.e authentication, session management? if not i will find may way i am sure. Thank you Simon. – docker dev Apr 03 '20 at 12:13
  • Ha - Juice Shop is actually a good example of the pain points you can hit with ZAP ;) I'm going to be covering it in a 3 hour ZAP automation tutorial as part of https://www.alldaydevops.com/spring-break Too much to go through here, but for authentication see https://github.com/zaproxy/community-scripts/blob/master/selenium/Selenium%20Juice%20Shop.js and https://github.com/zaproxy/community-scripts/blob/master/session/Juice%20Shop%20Session%20Management.js – Simon Bennetts Apr 03 '20 at 12:18
  • Perfect. I will tune in to that and have a look at the resources you mentioned. Thanks again Simon.Take care. – docker dev Apr 03 '20 at 13:14
0

This error message...

java -jar WafTestSuite.jar "zapurl" "8090" "change-me-9203935709" "10.10.10.254:3000"; Spidering target : 10.10.8.254:3000
Exception : java.net.SocketException: Unexpected end of file from server
org.zaproxy.clientapi.core.ClientApiException: java.net.SocketException: Unexpected end of file from server
at org.zaproxy.clientapi.core.ClientApi.callApiDom(ClientApi.http://java:366)

...implies that the remote server accepted and closed the connection without sending a response.

There can be many reasons behind this error and some of them are as follows:

  • Possibly the remote system is too busy to handle the request, so dropping the connection.
  • There may be missing/invalid header values in the request which causes an internal error and the server closes the connection instead of sending a HTTP error response normally as it should.
  • There may be a network delay and due to that the application randomly drops connections.

However, as per the configuration of proxy within your code block, it is pretty much evident that though you initialized ZAP_API_KEY as a String you haven't assigned any value. hence the error.

So essentially you code block to configure ZAP will be:

private static final String ZAP_ADDRESS = "localhost";
private static final int ZAP_PORT = 8080;
// Change to match the API key set in ZAP, or use NULL if the API key is disabled
private static final String ZAP_API_KEY = "abcdefghijklmnop123456789";
// The URL of the application to be tested
private static final String TARGET = "http://localhost:3000";

Why is an API key required by default?

As per the documentation since the availability of ZAP version 2.4.1 an API key by default needs to be configured in order to invoke API operations that make changes to ZAP. Additionally, with the availability of ZAP version 2.6.0 the API key is required by default in order to invoke any of the API operations. This security feature was implemented to prevent malicious sites from invoking the ZAP API. The API security options, including the API key, can be found in the API Options screen (ZAP Proxy Interface -> Tools -> Options -> API):

ZAP_API_key


Changing API Key

You can change the API key through the following different ways:

  • Generating a new API key by clicking on the Generate Random key button.
  • By setting the API key from the command line using:

    -config api.key=change-me-9203935709
    
  • Disable the API key from the command line using:

    -config api.disablekey=true
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352