All Downloads are FREE. Search and download functionalities are using the official Maven repository.

br.com.softplan.security.zap.api.analysis.BaseAnalyzer Maven / Gradle / Ivy

package br.com.softplan.security.zap.api.analysis;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXParseException;

import br.com.softplan.security.zap.api.exception.ZapAnalysisTimeoutException;
import br.com.softplan.security.zap.api.exception.ZapClientException;
import br.com.softplan.security.zap.api.model.AnalysisInfo;
import br.com.softplan.security.zap.api.model.ScanType;
import br.com.softplan.security.zap.api.report.ZapReport;
import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse;
import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponseElement;
import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponseList;
import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi;
import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException;

/**
 * Base implementation of {@link Analyzer}.
 * 

* Responsible for the timeout logic and calls to the ZAP API. * * @author pdsec */ public abstract class BaseAnalyzer implements Analyzer { private static final Logger LOGGER = LoggerFactory.getLogger(BaseAnalyzer.class); private static final long SPIDER_STATUS_POLLING_INTERVAL_IN_SECONDS = 1; private static final long AJAX_SPIDER_STATUS_POLLING_INTERVAL_IN_SECONDS = 10; private static final long ACTIVE_SCAN_STATUS_POLLING_INTERVAL_IN_SECONDS = 5; private String apiKey; private ClientApi api; private long analysisTimeoutInMillis; private long analysisStartTime; private boolean spiderDidRun = false; public BaseAnalyzer(String apiKey, ClientApi api) { this.api = api; this.apiKey = apiKey; } protected void init(long analysisTimeoutInMillis) { this.analysisTimeoutInMillis = analysisTimeoutInMillis; this.analysisStartTime = System.currentTimeMillis(); } protected void runSpider(AnalysisInfo analysisInfo) { String targetUrl = analysisInfo.getTargetUrl(); LOGGER.info("{} : {}", ScanType.SPIDER, targetUrl); try { ApiResponse resp = api.spider.scan(apiKey, targetUrl, "", ""/*, ""*/); String scanId = ((ApiResponseElement) resp).getValue(); waitForScanToFinish(scanId, ScanType.SPIDER); spiderDidRun = true; } catch (ClientApiException e) { handleError("Error running Spider.", e); } } protected void runAjaxSpider(AnalysisInfo analysisInfo) { String targetUrl = analysisInfo.getTargetUrl(); LOGGER.info("{} : {}", ScanType.AJAX_SPIDER, targetUrl); try { ApiResponse resp = api.ajaxSpider.scan(apiKey, targetUrl, "false"); String scanId = ((ApiResponseElement) resp).getValue(); waitForScanToFinish(scanId, ScanType.AJAX_SPIDER); } catch (ClientApiException e) { handleError("Error running Ajax Spider.", e); } } @SuppressWarnings("restriction") protected void runActiveScan(AnalysisInfo analysisInfo) { String targetUrl = analysisInfo.getTargetUrl(); LOGGER.info("{} : {}", ScanType.ACTIVE_SCAN, targetUrl); try { ApiResponse resp = api.ascan.scan(apiKey, targetUrl, "True", "False", "", "", ""); String scanId = ((ApiResponseElement) resp).getValue(); waitForScanToFinish(scanId, ScanType.ACTIVE_SCAN); } catch (ClientApiException e) { // TODO: rever essa estratégia de tratamento String message = "Error running Active Scan."; if (e.getCause() instanceof SAXParseException || e.getCause() instanceof com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException || e.getMessage().contains("URL Not Found in the Scan Tree")) { message += " One possible cause to this problem is that ZAP crashes when you try to run the Active Scan without any prior navigation made on the target " + "(i.e. Spidering or proxied navigation were not done before on the Active Scan target)."; } handleError(message, e); } } protected ZapReport generateReport() { LOGGER.info("Retrieving reports and Spider results..."); ZapReport zapReport = null; try { byte[] htmlReport = api.core.htmlreport(apiKey); byte[] xmlReport = api.core.xmlreport(apiKey); List spiderResults = getAndLogSpiderResults(); zapReport = new ZapReport(htmlReport, xmlReport, spiderResults); LOGGER.info("Reports retrieved."); } catch (ClientApiException e) { handleError("Error retrieving reports.", e); } return zapReport; } private List getAndLogSpiderResults() { List urls = new ArrayList(); if (!spiderDidRun) { LOGGER.info("Spider did not run."); return urls; } try { ApiResponseList responseList = (ApiResponseList) api.spider.results(""); LOGGER.debug("Visited URLs by the Spider:"); for (ApiResponse response : responseList.getItems()) { String url = ((ApiResponseElement) response).getValue(); LOGGER.debug(" {}", url); urls.add(url); } } catch (ClientApiException e) { handleError("Error retrieving Spider results.", e); } return urls; } private void waitForScanToFinish(String scanId, ScanType scanType) { int progress = 0; final int maxProgress = 100; while (progress < maxProgress) { switch (scanType) { case SPIDER: progress = waitSpider(scanId, progress); break; case AJAX_SPIDER: progress = waitAjaxSpider(scanId, progress); break; case ACTIVE_SCAN: progress = waitActiveScan(scanId, progress); } LOGGER.info("{} progress : {}%", scanType, progress); } LOGGER.info("{} complete", scanType); } private int waitSpider(String scanId, int progress) { sleep(SPIDER_STATUS_POLLING_INTERVAL_IN_SECONDS); int newProgress = progress; try { newProgress = Integer.parseInt(((ApiResponseElement) api.spider.status(scanId)).getValue()); } catch (NumberFormatException | ClientApiException e) { handleError("Error retrieving Spider progress.", e); } if (scanTimeoutReached(scanId)) { try { api.spider.stop(apiKey, scanId); LOGGER.info("Spider STOPPED"); } catch (ClientApiException e) { handleError("Error stopping Active Scan.", e); } String message = "Analysis did not finish before the timeout (" + analysisTimeoutInMillis + " ms)."; LOGGER.error(message); throw new ZapAnalysisTimeoutException(message); } return newProgress; } private int waitAjaxSpider(String scanId, int progress) { sleep(AJAX_SPIDER_STATUS_POLLING_INTERVAL_IN_SECONDS); int newProgress = progress; try { newProgress = getAjaxSpiderProgress(); } catch (ClientApiException e) { handleError("Error retrieving Ajax Spider progress.", e); } if (scanTimeoutReached(scanId)) { try { api.ajaxSpider.stop(scanId); LOGGER.info("AJAX Spider STOPPED"); } catch (ClientApiException e) { handleError("Error stopping Active Scan.", e); } String message = "Analysis did not finish before the timeout (" + analysisTimeoutInMillis + " ms)."; LOGGER.error(message); throw new ZapAnalysisTimeoutException(message); } return newProgress; } private int waitActiveScan(String scanId, int progress) { sleep(ACTIVE_SCAN_STATUS_POLLING_INTERVAL_IN_SECONDS); int newProgress = progress; try { newProgress = Integer.parseInt(((ApiResponseElement) api.ascan.status(scanId)).getValue()); } catch (NumberFormatException | ClientApiException e) { handleError("Error retrieving Active Scan progress.", e); } if (scanTimeoutReached(scanId)) { try { api.ascan.stop(apiKey, scanId); LOGGER.info("Active Scan STOPPED"); } catch (ClientApiException e) { handleError("Error stopping Active Scan.", e); } String message = "Analysis did not finish before the timeout (" + analysisTimeoutInMillis + " ms)."; LOGGER.error(message); throw new ZapAnalysisTimeoutException(message); } return newProgress; } private void handleError(String message, Throwable cause) { LOGGER.error(message, cause); throw new ZapClientException(message, cause); } private boolean scanTimeoutReached(String scanId) { long elapsedTimeInMillis = System.currentTimeMillis() - analysisStartTime; return elapsedTimeInMillis >= analysisTimeoutInMillis; } private int getAjaxSpiderProgress() throws ClientApiException { String progress = ((ApiResponseElement) api.ajaxSpider.status()).getValue(); final int maxProgress = 100; return progress.equalsIgnoreCase("running") ? 0 : maxProgress; } private static void sleep(long seconds) { try { Thread.sleep(TimeUnit.SECONDS.toMillis(seconds)); } catch(InterruptedException e) { Thread.currentThread().interrupt(); LOGGER.error(e.getMessage(), e); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy