├── .travis.yml ├── .gitignore ├── zap-maven-plugin-core ├── README.md ├── src │ └── main │ │ └── java │ │ └── br │ │ └── com │ │ └── softplan │ │ └── security │ │ └── zap │ │ └── maven │ │ ├── StartZapMojo.java │ │ ├── AnalyzeMojo.java │ │ └── SeleniumAnalyzeMojo.java └── pom.xml ├── zap-utils ├── src │ └── main │ │ ├── java │ │ └── br │ │ │ └── com │ │ │ └── softplan │ │ │ └── security │ │ │ └── zap │ │ │ └── commons │ │ │ ├── authentication │ │ │ └── AuthenticationScripts.java │ │ │ ├── boot │ │ │ ├── ZapNilBoot.java │ │ │ ├── ZapBootFactory.java │ │ │ ├── Zap.java │ │ │ ├── ZapBoot.java │ │ │ ├── AbstractZapBoot.java │ │ │ ├── ZapLocalBoot.java │ │ │ └── ZapDockerBoot.java │ │ │ └── exception │ │ │ ├── ZapInitializationException.java │ │ │ └── ZapInitializationTimeoutException.java │ │ └── resources │ │ └── scripts │ │ └── cas-auth.js ├── README.md └── pom.xml └── zap-client-api ├── src ├── main │ └── java │ │ └── br │ │ └── com │ │ └── softplan │ │ └── security │ │ └── zap │ │ ├── api │ │ ├── model │ │ │ ├── AuthenticationType.java │ │ │ ├── AnalysisType.java │ │ │ ├── SeleniumDriver.java │ │ │ └── ScanType.java │ │ ├── authentication │ │ │ ├── AuthenticationHandler.java │ │ │ ├── AuthenticationHandlerFactory.java │ │ │ ├── SeleniumAuthenticationHandler.java │ │ │ ├── AuthenticationScript.java │ │ │ ├── FormAuthenticationHandler.java │ │ │ ├── HttpAuthenticationHandler.java │ │ │ ├── WebDriverFactory.java │ │ │ ├── CasAuthenticationHandler.java │ │ │ ├── AuthenticationScriptLoader.java │ │ │ └── AuthenticationInfoValidator.java │ │ ├── exception │ │ │ ├── ZapClientException.java │ │ │ ├── ZapAnalysisTimeoutException.java │ │ │ └── AuthenticationInfoValidationException.java │ │ ├── analysis │ │ │ ├── SpiderOnlyAnalyzer.java │ │ │ ├── Analyzer.java │ │ │ ├── ActiveScanOnlyAnalyzer.java │ │ │ ├── WithSpiderAnalyzer.java │ │ │ ├── SpiderAndAjaxSpiderOnlyAnalyzer.java │ │ │ ├── WithAjaxSpiderAnalyzer.java │ │ │ └── AnalyzerFactory.java │ │ ├── SessionManager.java │ │ ├── report │ │ │ ├── SpiderResultsReportBuilder.java │ │ │ ├── ZapReport.java │ │ │ └── ZapReportUtil.java │ │ ├── ZapClient.java │ │ └── ZapHelper.java │ │ └── zaproxy │ │ └── clientapi │ │ ├── core │ │ ├── ApiResponseFactory.java │ │ ├── ApiResponse.java │ │ ├── ClientApiException.java │ │ ├── ApiResponseElement.java │ │ ├── ApiResponseSet.java │ │ ├── ApiResponseList.java │ │ └── AlertsFile.java │ │ └── gen │ │ ├── Params.java │ │ ├── Reveal.java │ │ ├── SessionManagement.java │ │ ├── Break.java │ │ ├── Acsrf.java │ │ ├── ForcedUser.java │ │ ├── AjaxSpider.java │ │ ├── Selenium.java │ │ ├── ImportLogFiles.java │ │ ├── Script.java │ │ ├── Authentication.java │ │ ├── Pscan.java │ │ ├── Pnh.java │ │ ├── Users.java │ │ ├── HttpSessions.java │ │ └── Search.java └── test │ ├── resources │ ├── logback-test.xml │ └── zap.properties │ └── java │ └── br │ └── com │ └── softplan │ └── security │ └── zap │ └── api │ ├── util │ ├── BaseIT.java │ ├── SetupIT.java │ ├── LogbackTestAppender.java │ └── ZapProperties.java │ ├── authentication │ ├── NilAuthenticationHandler.java │ ├── AuthenticationHandlerFactoryTest.java │ ├── FormAuthenticationHandlerIT.java │ ├── CasAuthenticationHandlerIT.java │ ├── AuthenticationInfoValidatorTest.java │ └── AbstractAuthenticationHandlerIT.java │ ├── exception │ ├── ZapClientExceptionTest.java │ ├── ZapAnalysisTimeoutExceptionTest.java │ └── AuthenticationInfoValidationExceptionTest.java │ ├── ZapClientIT.java │ └── report │ ├── ZapReportTest.java │ └── ZapReportUtilTest.java └── pom.xml /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | jdk: 4 | - oraclejdk8 5 | - oraclejdk7 6 | - openjdk7 7 | 8 | before_install: 9 | - cd zap-maven-plugin-parent 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | .settings/ 3 | .classpath 4 | .project 5 | 6 | # Maven 7 | target/ 8 | 9 | # TestNG 10 | test-output/ 11 | 12 | # Local ZAP properties file 13 | zap-client-api/src/test/resources/local-zap.properties 14 | -------------------------------------------------------------------------------- /zap-maven-plugin-core/README.md: -------------------------------------------------------------------------------- 1 | # ZAP Maven Plugin Core 2 | 3 | This module contains the actual code related to Maven. All the information needed to use the plugin is presented [here](https://github.com/pdsoftplan/zap-maven-plugin). 4 | 5 | :zap: 6 | -------------------------------------------------------------------------------- /zap-utils/src/main/java/br/com/softplan/security/zap/commons/authentication/AuthenticationScripts.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.commons.authentication; 2 | 3 | public class AuthenticationScripts { 4 | 5 | public static final String RELATIVE_PATH = "/scripts/"; 6 | public static final String EXTENSION = ".js"; 7 | 8 | } 9 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/model/AuthenticationType.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.model; 2 | 3 | /** 4 | * Enumerates the possible types of authentication. 5 | * 6 | * @author pdsec 7 | */ 8 | public enum AuthenticationType { 9 | 10 | HTTP, 11 | FORM, 12 | CAS, 13 | SELENIUM; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/model/AnalysisType.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.model; 2 | 3 | /** 4 | * Enum to classify the types of possible analysis. 5 | * 6 | * @author pdsec 7 | */ 8 | public enum AnalysisType { 9 | 10 | WITH_SPIDER, 11 | WITH_AJAX_SPIDER, 12 | ACTIVE_SCAN_ONLY, 13 | SPIDER_ONLY, 14 | SPIDER_AND_AJAX_SPIDER_ONLY; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/model/SeleniumDriver.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.model; 2 | 3 | public enum SeleniumDriver { 4 | 5 | HTMLUNIT("HtmlUnit"), 6 | FIREFOX("Firefox"), 7 | PHANTOMJS("PhantomJS"); 8 | 9 | private String name; 10 | 11 | private SeleniumDriver(String name){ 12 | this.name = name; 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return name; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /zap-client-api/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | System.out 5 | 6 | %-4relative [%thread] %-5level %logger - %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /zap-utils/src/main/java/br/com/softplan/security/zap/commons/boot/ZapNilBoot.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.commons.boot; 2 | 3 | import br.com.softplan.security.zap.commons.ZapInfo; 4 | 5 | /** 6 | * Class to be used as the ZAP booter when ZAP is supposedly up and running. 7 | * 8 | * @author pdsec 9 | */ 10 | public class ZapNilBoot extends AbstractZapBoot { 11 | 12 | @Override 13 | public void startZap(ZapInfo zapInfo) {} 14 | 15 | @Override 16 | public void stopZap() {} 17 | 18 | } 19 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/model/ScanType.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.model; 2 | 3 | /** 4 | * Enumumerates the possible types of scans. 5 | * 6 | * @author pdsec 7 | */ 8 | public enum ScanType { 9 | 10 | SPIDER("Spider"), 11 | AJAX_SPIDER("AJAX Spider"), 12 | ACTIVE_SCAN("Active Scan"); 13 | 14 | private final String name; 15 | 16 | private ScanType(String name) { 17 | this.name = name; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return this.name; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /zap-client-api/src/test/resources/zap.properties: -------------------------------------------------------------------------------- 1 | zap.host=localhost 2 | zap.port=8080 3 | zap.path=C:\\ZAP 4 | zap.initializationTimeout=120000 5 | 6 | # -daemon Run ZAP as a daemon, with no GUI. 7 | # -config api.disablekey=true Disable the need to pass ZAP an API key to use its API. 8 | # -config api.incerrordetails=true Report error details through the API. 9 | # -config proxy.ip=0.0.0.0 Enables remote connection with ZAP. 10 | zap.options=-daemon -config api.disablekey=true -config api.incerrordetails=true -config proxy.ip=0.0.0.0 11 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/authentication/AuthenticationHandler.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.authentication; 2 | 3 | /** 4 | * The implementations of this interface should be able to handle ZAP's 5 | * authentication to ensure the scans will be authenticated. 6 | * 7 | * @author pdsec 8 | */ 9 | public interface AuthenticationHandler { 10 | 11 | /** 12 | * Handles all the necessary configuration and procedures to 13 | * make sure ZAP's scan will be authenticated. 14 | * 15 | * @param targetUrl the URL of the target application. 16 | */ 17 | void handleAuthentication(String targetUrl); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/exception/ZapClientException.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.exception; 2 | 3 | /** 4 | * General runtime exception for the ZAP Client API. 5 | * 6 | * @author pdsec 7 | */ 8 | public class ZapClientException extends RuntimeException { 9 | 10 | private static final long serialVersionUID = -4867749606526224619L; 11 | 12 | public ZapClientException(String message) { 13 | super(message); 14 | } 15 | 16 | public ZapClientException(Throwable e) { 17 | super(e); 18 | } 19 | 20 | public ZapClientException(String message, Throwable e) { 21 | super(message, e); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/exception/ZapAnalysisTimeoutException.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.exception; 2 | 3 | /** 4 | * This will be thrown if the analysis timeout expires. 5 | * 6 | * @author pdsec 7 | */ 8 | public class ZapAnalysisTimeoutException extends RuntimeException { 9 | 10 | private static final long serialVersionUID = -8195267976688210143L; 11 | 12 | public ZapAnalysisTimeoutException(String message) { 13 | super(message); 14 | } 15 | 16 | public ZapAnalysisTimeoutException(Throwable e) { 17 | super(e); 18 | } 19 | 20 | public ZapAnalysisTimeoutException(String message, Throwable e) { 21 | super(message, e); 22 | } 23 | } -------------------------------------------------------------------------------- /zap-utils/src/main/java/br/com/softplan/security/zap/commons/exception/ZapInitializationException.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.commons.exception; 2 | 3 | /** 4 | * Exception thrown when ZAP initialization fails. 5 | * 6 | * @author pdsec 7 | */ 8 | public class ZapInitializationException extends RuntimeException { 9 | 10 | private static final long serialVersionUID = -2305184594319127381L; 11 | 12 | public ZapInitializationException(String message) { 13 | super(message); 14 | } 15 | 16 | public ZapInitializationException(Throwable e) { 17 | super(e); 18 | } 19 | 20 | public ZapInitializationException(String message, Throwable e) { 21 | super(message, e); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/analysis/SpiderOnlyAnalyzer.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.analysis; 2 | 3 | import br.com.softplan.security.zap.api.model.AnalysisInfo; 4 | import br.com.softplan.security.zap.api.report.ZapReport; 5 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 6 | 7 | public class SpiderOnlyAnalyzer extends BaseAnalyzer { 8 | 9 | public SpiderOnlyAnalyzer(String apiKey, ClientApi api) { 10 | super(apiKey, api); 11 | } 12 | 13 | public ZapReport analyze(AnalysisInfo analysisInfo) { 14 | init(analysisInfo.getAnalysisTimeoutInMillis()); 15 | 16 | runSpider(analysisInfo); 17 | 18 | return generateReport(); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /zap-utils/README.md: -------------------------------------------------------------------------------- 1 | # ZAP Utils 2 | 3 | This module is responsible for the automatic initialization of ZAP (via local installation or Docker). 4 | 5 | To start ZAP, simply create a `ZapInfo` instance through its builder and call `Zap.startZap(zapInfo)`: 6 | 7 | ```java 8 | // This will make ZAP start from a local installation 9 | ZapInfo zapInfo = ZapInfo.builder().buildToRunZap(8080, "C:\\ZAP"); 10 | 11 | // This would make ZAP start via Docker; there are many other options that can be set using ZapInfo's builder 12 | // ZapInfo zapInfo = ZapInfo.builder().buildToRunZapWithDocker(8080); 13 | 14 | // This starts ZAP 15 | Zap.startZap(zapInfo); 16 | 17 | // And this kills it 18 | Zap.stopZap(); 19 | 20 | ``` 21 | 22 | :zap: 23 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/analysis/Analyzer.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.analysis; 2 | 3 | import br.com.softplan.security.zap.api.model.AnalysisInfo; 4 | import br.com.softplan.security.zap.api.report.ZapReport; 5 | 6 | /** 7 | * Implementations of this class represent different kinds of analysis that can be executed on ZAP. 8 | * 9 | * @author pdsec 10 | */ 11 | public interface Analyzer { 12 | 13 | /** 14 | * Runs an analysis of the given target and generates the report. 15 | * 16 | * @param analysisInfo the information about the analysis to be executed. 17 | * @return the report of the analysis. 18 | */ 19 | ZapReport analyze(AnalysisInfo analysisInfo); 20 | } 21 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/analysis/ActiveScanOnlyAnalyzer.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.analysis; 2 | 3 | import br.com.softplan.security.zap.api.model.AnalysisInfo; 4 | import br.com.softplan.security.zap.api.report.ZapReport; 5 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 6 | 7 | public class ActiveScanOnlyAnalyzer extends BaseAnalyzer { 8 | 9 | public ActiveScanOnlyAnalyzer(String apiKey, ClientApi api) { 10 | super(apiKey, api); 11 | } 12 | 13 | public ZapReport analyze(AnalysisInfo analysisInfo) { 14 | init(analysisInfo.getAnalysisTimeoutInMillis()); 15 | 16 | runActiveScan(analysisInfo); 17 | 18 | return generateReport(); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /zap-utils/src/main/java/br/com/softplan/security/zap/commons/boot/ZapBootFactory.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.commons.boot; 2 | 3 | import br.com.softplan.security.zap.commons.ZapInfo; 4 | 5 | /** 6 | * Factory to create the correct {@link ZapBoot} implementation 7 | * based on the given {@link ZapInfo} instance. 8 | * 9 | * @author pdsec 10 | */ 11 | public final class ZapBootFactory { 12 | 13 | static ZapBoot makeZapBoot(ZapInfo zapInfo) { 14 | if (zapInfo.shouldRunWithDocker()) { 15 | return new ZapDockerBoot(); 16 | } 17 | if (zapInfo.getPath() != null && !zapInfo.getPath().isEmpty()) { 18 | return new ZapLocalBoot(); 19 | } 20 | return new ZapNilBoot(); 21 | } 22 | 23 | private ZapBootFactory() {} 24 | 25 | } 26 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/analysis/WithSpiderAnalyzer.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.analysis; 2 | 3 | import br.com.softplan.security.zap.api.model.AnalysisInfo; 4 | import br.com.softplan.security.zap.api.report.ZapReport; 5 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 6 | 7 | public class WithSpiderAnalyzer extends BaseAnalyzer { 8 | 9 | public WithSpiderAnalyzer(String apiKey, ClientApi api) { 10 | super(apiKey, api); 11 | } 12 | 13 | public ZapReport analyze(AnalysisInfo analysisInfo) { 14 | init(analysisInfo.getAnalysisTimeoutInMillis()); 15 | 16 | runSpider(analysisInfo); 17 | runActiveScan(analysisInfo); 18 | 19 | return generateReport(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /zap-utils/src/main/java/br/com/softplan/security/zap/commons/exception/ZapInitializationTimeoutException.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.commons.exception; 2 | 3 | /** 4 | * This exception should be thrown if ZAP is not started before the specified timeout. 5 | * 6 | * @author pdsec 7 | */ 8 | public class ZapInitializationTimeoutException extends RuntimeException { 9 | 10 | private static final long serialVersionUID = -5283245793671447701L; 11 | 12 | public ZapInitializationTimeoutException(String message) { 13 | super(message); 14 | } 15 | 16 | public ZapInitializationTimeoutException(Throwable e) { 17 | super(e); 18 | } 19 | 20 | public ZapInitializationTimeoutException(String message, Throwable e) { 21 | super(message, e); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/exception/AuthenticationInfoValidationException.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.exception; 2 | 3 | /** 4 | * Exception that will be thrown in case authentication info provided is not valid. 5 | * 6 | * @author pdsec 7 | */ 8 | public class AuthenticationInfoValidationException extends RuntimeException { 9 | 10 | private static final long serialVersionUID = -2619404350476128144L; 11 | 12 | public AuthenticationInfoValidationException(String message) { 13 | super(message); 14 | } 15 | 16 | public AuthenticationInfoValidationException(Throwable e) { 17 | super(e); 18 | } 19 | 20 | public AuthenticationInfoValidationException(String message, Throwable e) { 21 | super(message, e); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/analysis/SpiderAndAjaxSpiderOnlyAnalyzer.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.analysis; 2 | 3 | import br.com.softplan.security.zap.api.model.AnalysisInfo; 4 | import br.com.softplan.security.zap.api.report.ZapReport; 5 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 6 | 7 | public class SpiderAndAjaxSpiderOnlyAnalyzer extends BaseAnalyzer { 8 | 9 | public SpiderAndAjaxSpiderOnlyAnalyzer(String apiKey, ClientApi api) { 10 | super(apiKey, api); 11 | } 12 | 13 | public ZapReport analyze(AnalysisInfo analysisInfo) { 14 | init(analysisInfo.getAnalysisTimeoutInMillis()); 15 | 16 | runSpider(analysisInfo); 17 | runAjaxSpider(analysisInfo); 18 | 19 | return generateReport(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/analysis/WithAjaxSpiderAnalyzer.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.analysis; 2 | 3 | import br.com.softplan.security.zap.api.model.AnalysisInfo; 4 | import br.com.softplan.security.zap.api.report.ZapReport; 5 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 6 | 7 | public class WithAjaxSpiderAnalyzer extends BaseAnalyzer { 8 | 9 | public WithAjaxSpiderAnalyzer(String apiKey, ClientApi api) { 10 | super(apiKey, api); 11 | } 12 | 13 | public ZapReport analyze(AnalysisInfo analysisInfo) { 14 | init(analysisInfo.getAnalysisTimeoutInMillis()); 15 | 16 | runSpider(analysisInfo); 17 | runAjaxSpider(analysisInfo); 18 | runActiveScan(analysisInfo); 19 | 20 | return generateReport(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /zap-client-api/src/test/java/br/com/softplan/security/zap/api/util/BaseIT.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.util; 2 | 3 | import org.testng.annotations.BeforeClass; 4 | 5 | import br.com.softplan.security.zap.api.ZapClient; 6 | import br.com.softplan.security.zap.commons.ZapInfo; 7 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 8 | 9 | /** 10 | * Base class for integration tests. 11 | * 12 | * @author pdsec 13 | */ 14 | public class BaseIT { 15 | 16 | protected ZapInfo zapInfo; 17 | protected ZapClient zapClient; 18 | protected ClientApi api; 19 | 20 | @BeforeClass 21 | public void init() { 22 | zapInfo = ZapInfo.builder().buildToUseRunningZap(ZapProperties.getHost(), ZapProperties.getPort()); 23 | zapClient = new ZapClient(zapInfo); 24 | api = new ClientApi(zapInfo.getHost(), zapInfo.getPort()); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /zap-client-api/src/test/java/br/com/softplan/security/zap/api/authentication/NilAuthenticationHandler.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.authentication; 2 | 3 | import br.com.softplan.security.zap.api.model.AuthenticationInfo; 4 | import br.com.softplan.security.zap.commons.ZapInfo; 5 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 6 | 7 | /** 8 | * Simple extension of {@code AbstractAuthenticationHandler} to test its functionalities. 9 | * 10 | * @see AbstractAuthenticationHandler 11 | * @author pdsec 12 | */ 13 | public class NilAuthenticationHandler extends AbstractAuthenticationHandler { 14 | 15 | protected NilAuthenticationHandler(ClientApi api, ZapInfo zapInfo, AuthenticationInfo authenticationInfo) { 16 | super(api, zapInfo, authenticationInfo); 17 | } 18 | 19 | @Override 20 | public void setupAuthentication(String targetUrl) {} 21 | 22 | } 23 | -------------------------------------------------------------------------------- /zap-utils/src/main/java/br/com/softplan/security/zap/commons/boot/Zap.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.commons.boot; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import br.com.softplan.security.zap.commons.ZapInfo; 7 | 8 | /** 9 | * Utility class to help with ZAP related tasks (start and stop ZAP, run ZAP Docker image). 10 | * 11 | * @author pdsec 12 | */ 13 | public final class Zap { 14 | 15 | private static final Logger LOGGER = LoggerFactory.getLogger(Zap.class); 16 | 17 | private static ZapBoot zap; 18 | 19 | public static void startZap(ZapInfo zapInfo) { 20 | zap = ZapBootFactory.makeZapBoot(zapInfo); 21 | LOGGER.debug("ZAP will be started by: [{}].", zap.getClass().getSimpleName()); 22 | 23 | zap.startZap(zapInfo); 24 | } 25 | 26 | public static void stopZap() { 27 | if (zap != null) { 28 | zap.stopZap(); 29 | } 30 | } 31 | 32 | private Zap() {} 33 | 34 | } 35 | -------------------------------------------------------------------------------- /zap-utils/src/main/java/br/com/softplan/security/zap/commons/boot/ZapBoot.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.commons.boot; 2 | 3 | import br.com.softplan.security.zap.commons.ZapInfo; 4 | 5 | /** 6 | * This interface should be implemented by any class capable 7 | * of starting and stopping ZAP, no matter how. 8 | * 9 | * @author pdsec 10 | */ 11 | public interface ZapBoot { 12 | 13 | /** 14 | * Starts ZAP. 15 | *

16 | * It should throw {@link br.com.softplan.security.zap.commons.exception.ZapInitializationTimeoutException ZapInitializationTimeoutException} 17 | * in case ZAP is not started before a timeout, defined by {@code zapInfo.initializationTimeout} 18 | * (the default value is {@code 120000}). 19 | * 20 | * @param zapInfo an object with all the information needed to start ZAP. 21 | */ 22 | void startZap(ZapInfo zapInfo); 23 | 24 | /** 25 | * Stops ZAP. 26 | */ 27 | void stopZap(); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/analysis/AnalyzerFactory.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.analysis; 2 | 3 | import br.com.softplan.security.zap.api.model.AnalysisInfo; 4 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 5 | 6 | /** 7 | * Factory to create the correct {@link Analyzer} implementation based on the given {@link AnalysisInfo} instance. 8 | * 9 | * @author pdsec 10 | */ 11 | public final class AnalyzerFactory { 12 | 13 | public static Analyzer makeAnalyzer(String apiKey, ClientApi api, AnalysisInfo analysisInfo) { 14 | switch (analysisInfo.getAnalysisType()) { 15 | case WITH_SPIDER: return new WithSpiderAnalyzer(apiKey, api); 16 | case WITH_AJAX_SPIDER: return new WithAjaxSpiderAnalyzer(apiKey, api); 17 | case ACTIVE_SCAN_ONLY: return new ActiveScanOnlyAnalyzer(apiKey, api); 18 | case SPIDER_ONLY: return new SpiderOnlyAnalyzer(apiKey, api); 19 | case SPIDER_AND_AJAX_SPIDER_ONLY: return new SpiderAndAjaxSpiderOnlyAnalyzer(apiKey, api); 20 | default: return null; 21 | } 22 | } 23 | 24 | private AnalyzerFactory() {} 25 | 26 | } 27 | -------------------------------------------------------------------------------- /zap-maven-plugin-core/src/main/java/br/com/softplan/security/zap/maven/StartZapMojo.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.maven; 2 | 3 | import org.apache.maven.plugin.MojoExecutionException; 4 | import org.apache.maven.plugin.MojoFailureException; 5 | import org.apache.maven.plugins.annotations.Mojo; 6 | 7 | import br.com.softplan.security.zap.commons.boot.Zap; 8 | 9 | /** 10 | * Starts ZAP. 11 | *

12 | * Normally this goal will be used along with the {@code seleniumAnalyze} goal. 13 | *

14 | * The usual configuration is to use {@code startZap} in the pre-integration-test, 15 | * to make sure ZAP is running during the tests. If the tests are correctly configured, 16 | * they will use ZAP's proxy to run the tests. The goal {@code seleniumAnalyze} can then 17 | * be configured to run in the phase post-integration-test to run a ZAP analysis 18 | * without a Spider (using the navigation done by the tests). 19 | * 20 | * @author pdsec 21 | */ 22 | @Mojo(name="startZap") 23 | public class StartZapMojo extends ZapMojo { 24 | 25 | @Override 26 | public void doExecute() throws MojoExecutionException, MojoFailureException { 27 | Zap.startZap(buildZapInfo()); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /zap-client-api/src/test/java/br/com/softplan/security/zap/api/exception/ZapClientExceptionTest.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.exception; 2 | 3 | import static org.testng.Assert.assertEquals; 4 | 5 | import org.testng.annotations.Test; 6 | 7 | public class ZapClientExceptionTest { 8 | 9 | @Test 10 | public void testMessageConstructor() { 11 | String message = "message"; 12 | try { 13 | throw new ZapClientException(message); 14 | } catch (ZapClientException e) { 15 | assertEquals(e.getMessage(), message); 16 | } 17 | } 18 | 19 | @Test 20 | public void testThrowableConstructor() { 21 | Throwable throwable = new NullPointerException("test"); 22 | try { 23 | throw new ZapClientException(throwable); 24 | } catch (ZapClientException e) { 25 | assertEquals(e.getCause(), throwable); 26 | } 27 | } 28 | 29 | @Test 30 | public void testMessageAndThrowableConstructor() { 31 | String message = "message"; 32 | Throwable throwable = new NullPointerException("test"); 33 | try { 34 | throw new ZapClientException(message, throwable); 35 | } catch (ZapClientException e) { 36 | assertEquals(e.getMessage(), message); 37 | assertEquals(e.getCause(), throwable); 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/core/ApiResponseFactory.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.zaproxy.clientapi.core; 2 | 3 | import org.w3c.dom.NamedNodeMap; 4 | import org.w3c.dom.Node; 5 | 6 | public final class ApiResponseFactory { 7 | 8 | private ApiResponseFactory() { 9 | } 10 | 11 | public static ApiResponse getResponse(Node node) throws ClientApiException { 12 | if (node == null) { 13 | throw new ClientApiException("Null node"); 14 | } 15 | Node typeNode = node.getAttributes().getNamedItem("type"); 16 | if (typeNode != null) { 17 | String type = typeNode.getNodeValue(); 18 | if ("list".equals(type)) { 19 | return new ApiResponseList(node); 20 | } 21 | if ("set".equals(type)) { 22 | return new ApiResponseSet(node); 23 | } 24 | if ("exception".equals(type)) { 25 | NamedNodeMap atts = node.getAttributes(); 26 | 27 | String code = atts.getNamedItem("code").getNodeValue(); 28 | String detail = null; 29 | if (atts.getNamedItem("detail") != null) { 30 | detail = atts.getNamedItem("detail").getNodeValue(); 31 | } 32 | throw new ClientApiException(node.getTextContent(), code, detail); 33 | } 34 | } 35 | return new ApiResponseElement(node); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /zap-client-api/src/test/java/br/com/softplan/security/zap/api/exception/ZapAnalysisTimeoutExceptionTest.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.exception; 2 | 3 | import static org.testng.Assert.assertEquals; 4 | 5 | import org.testng.annotations.Test; 6 | 7 | public class ZapAnalysisTimeoutExceptionTest { 8 | 9 | @Test 10 | public void testMessageConstructor() { 11 | String message = "message"; 12 | try { 13 | throw new ZapAnalysisTimeoutException(message); 14 | } catch (ZapAnalysisTimeoutException e) { 15 | assertEquals(e.getMessage(), message); 16 | } 17 | } 18 | 19 | @Test 20 | public void testThrowableConstructor() { 21 | Throwable throwable = new NullPointerException("test"); 22 | try { 23 | throw new ZapAnalysisTimeoutException(throwable); 24 | } catch (ZapAnalysisTimeoutException e) { 25 | assertEquals(e.getCause(), throwable); 26 | } 27 | } 28 | 29 | @Test 30 | public void testMessageAndThrowableConstructor() { 31 | String message = "message"; 32 | Throwable throwable = new NullPointerException("test"); 33 | try { 34 | throw new ZapAnalysisTimeoutException(message, throwable); 35 | } catch (ZapAnalysisTimeoutException e) { 36 | assertEquals(e.getMessage(), message); 37 | assertEquals(e.getCause(), throwable); 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/core/ApiResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Zed Attack Proxy (ZAP) and its related class files. 3 | * 4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package br.com.softplan.security.zap.zaproxy.clientapi.core; 19 | 20 | 21 | public abstract class ApiResponse { 22 | 23 | private String name = null; 24 | 25 | public ApiResponse(String name) { 26 | super(); 27 | this.name = name; 28 | } 29 | 30 | public String getName() { 31 | return name; 32 | } 33 | 34 | public void setName(String name) { 35 | this.name = name; 36 | } 37 | 38 | public abstract String toString(int indent); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/authentication/AuthenticationHandlerFactory.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.authentication; 2 | 3 | import br.com.softplan.security.zap.api.model.AuthenticationInfo; 4 | import br.com.softplan.security.zap.commons.ZapInfo; 5 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 6 | 7 | /** 8 | * Factory to create the correct {@link AuthenticationHandler} based on the given {@link AuthenticationInfo} instance. 9 | * 10 | * @author pdsec 11 | */ 12 | public final class AuthenticationHandlerFactory { 13 | 14 | public static AuthenticationHandler makeHandler(ClientApi api, ZapInfo zapInfo, AuthenticationInfo authenticationInfo) { 15 | if (authenticationInfo == null) { 16 | return null; 17 | } 18 | 19 | switch (authenticationInfo.getType()) { 20 | case FORM: return new FormAuthenticationHandler(api, zapInfo, authenticationInfo); 21 | case CAS: return new CasAuthenticationHandler(api, zapInfo, authenticationInfo); 22 | case SELENIUM: return new SeleniumAuthenticationHandler(api, zapInfo, authenticationInfo); 23 | case HTTP: return new HttpAuthenticationHandler(api, zapInfo, authenticationInfo); 24 | default: return null; 25 | } 26 | } 27 | 28 | private AuthenticationHandlerFactory() {} 29 | 30 | } 31 | -------------------------------------------------------------------------------- /zap-client-api/src/test/java/br/com/softplan/security/zap/api/exception/AuthenticationInfoValidationExceptionTest.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.exception; 2 | 3 | import static org.testng.Assert.assertEquals; 4 | 5 | import org.testng.annotations.Test; 6 | 7 | public class AuthenticationInfoValidationExceptionTest { 8 | 9 | @Test 10 | public void testMessageConstructor() { 11 | String message = "message"; 12 | try { 13 | throw new AuthenticationInfoValidationException(message); 14 | } catch (AuthenticationInfoValidationException e) { 15 | assertEquals(e.getMessage(), message); 16 | } 17 | } 18 | 19 | @Test 20 | public void testThrowableConstructor() { 21 | Throwable throwable = new NullPointerException("test"); 22 | try { 23 | throw new AuthenticationInfoValidationException(throwable); 24 | } catch (AuthenticationInfoValidationException e) { 25 | assertEquals(e.getCause(), throwable); 26 | } 27 | } 28 | 29 | @Test 30 | public void testMessageAndThrowableConstructor() { 31 | String message = "message"; 32 | Throwable throwable = new NullPointerException("test"); 33 | try { 34 | throw new AuthenticationInfoValidationException(message, throwable); 35 | } catch (AuthenticationInfoValidationException e) { 36 | assertEquals(e.getMessage(), message); 37 | assertEquals(e.getCause(), throwable); 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /zap-client-api/src/test/java/br/com/softplan/security/zap/api/authentication/AuthenticationHandlerFactoryTest.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.authentication; 2 | 3 | import static org.testng.Assert.*; 4 | 5 | import org.testng.annotations.Test; 6 | 7 | import br.com.softplan.security.zap.api.model.AuthenticationInfo; 8 | import br.com.softplan.security.zap.commons.ZapInfo; 9 | 10 | public class AuthenticationHandlerFactoryTest { 11 | 12 | @Test 13 | public void testCasHandlerCreation() { 14 | ZapInfo zapInfo = ZapInfo.builder().buildToUseRunningZap("localhost", 8080); 15 | 16 | AuthenticationInfo authInfo = AuthenticationInfo.builder() 17 | .buildCasAuthenticationInfo("loginUrl", "username", "password", "protectedPages"); 18 | 19 | AuthenticationHandler handler = AuthenticationHandlerFactory.makeHandler(null, zapInfo, authInfo); 20 | assertTrue(handler instanceof CasAuthenticationHandler); 21 | } 22 | 23 | @Test 24 | public void testFormHandlerCreation() { 25 | ZapInfo zapInfo = ZapInfo.builder().buildToUseRunningZap("localhost", 8080); 26 | 27 | AuthenticationInfo authInfo = AuthenticationInfo.builder() 28 | .buildFormAuthenticationInfo("loginUrl", "username", "password");; 29 | 30 | AuthenticationHandler handler = AuthenticationHandlerFactory.makeHandler(null, zapInfo, authInfo); 31 | assertTrue(handler instanceof FormAuthenticationHandler); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/SessionManager.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import br.com.softplan.security.zap.api.exception.ZapClientException; 7 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 8 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 9 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 10 | 11 | /** 12 | * Class to manage ZAP sessions. 13 | * 14 | * @author pdsec 15 | */ 16 | public class SessionManager { 17 | 18 | private static final Logger LOGGER = LoggerFactory.getLogger(SessionManager.class); 19 | 20 | private static final String SESSION_PREFIX = "zap-session-"; 21 | 22 | private int sessionId; 23 | 24 | public void createNewSession(ClientApi api, String apiKey) { 25 | createNewSession(api, apiKey, true); 26 | } 27 | 28 | public void createNewSession(ClientApi api, String apiKey, boolean overwrite) { 29 | LOGGER.debug("Creating a new ZAP session."); 30 | 31 | try { 32 | ApiResponse response = api.core.newSession(apiKey, SESSION_PREFIX + sessionId++, Boolean.toString(overwrite)); 33 | ZapHelper.validateResponse(response, "Create a new ZAP session."); 34 | } catch (ClientApiException e) { 35 | LOGGER.error("Error creating a new ZAP session.", e); 36 | throw new ZapClientException(e); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /zap-client-api/src/test/java/br/com/softplan/security/zap/api/util/SetupIT.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.util; 2 | 3 | import java.io.IOException; 4 | 5 | import org.apache.commons.configuration.ConfigurationException; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.testng.annotations.AfterSuite; 9 | import org.testng.annotations.BeforeSuite; 10 | 11 | import br.com.softplan.security.zap.commons.ZapInfo; 12 | import br.com.softplan.security.zap.commons.boot.Zap; 13 | 14 | /** 15 | * Class responsible for starting ZAP before the integration tests 16 | * and stopping it after the tests are finished. 17 | * 18 | * @author pdsec 19 | */ 20 | public class SetupIT { 21 | 22 | private static final Logger LOGGER = LoggerFactory.getLogger(SetupIT.class); 23 | 24 | @BeforeSuite 25 | public void setUp() throws IOException, ConfigurationException { 26 | ZapInfo zapHostInfo = new ZapInfo.Builder() 27 | .host (ZapProperties.getHost()) 28 | .port (ZapProperties.getPort()) 29 | .path (ZapProperties.getPath()) 30 | .options(ZapProperties.getOptions()) 31 | .initializationTimeoutInMillis(ZapProperties.getInitializationTimeout()) 32 | .build(); 33 | 34 | LOGGER.info("Starting ZAP before integration tests."); 35 | Zap.startZap(zapHostInfo); 36 | } 37 | 38 | @AfterSuite 39 | public void tearUp() { 40 | LOGGER.info("Stopping ZAP after integration tests."); 41 | Zap.stopZap(); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /zap-client-api/src/test/java/br/com/softplan/security/zap/api/ZapClientIT.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api; 2 | 3 | import static org.testng.Assert.assertFalse; 4 | import static org.testng.Assert.assertTrue; 5 | 6 | import java.io.File; 7 | 8 | import org.testng.annotations.Test; 9 | 10 | import br.com.softplan.security.zap.api.exception.ZapClientException; 11 | import br.com.softplan.security.zap.api.model.AnalysisInfo; 12 | import br.com.softplan.security.zap.api.report.ZapReport; 13 | import br.com.softplan.security.zap.api.report.ZapReportUtil; 14 | import br.com.softplan.security.zap.api.util.BaseIT; 15 | 16 | public class ZapClientIT extends BaseIT { 17 | 18 | private static final String TARGET_404_URL = "http://server17:8180/404"; 19 | private static final String WRONG_TARGET_URL = "http://blabla.blablabla"; 20 | 21 | @Test 22 | public void shouldGenerateAndSaveTheReports() { 23 | ZapReport zapReport = zapClient.analyze(AnalysisInfo.builder().targetUrl(TARGET_404_URL).build()); 24 | File zapReportFile = ZapReportUtil.saveHtmlReport(zapReport); 25 | 26 | assertTrue(zapReportFile.exists()); 27 | assertFalse(zapReport.getHtmlReportAsString().isEmpty()); 28 | assertFalse(zapReport.getXmlReportAsString().isEmpty()); 29 | } 30 | 31 | @Test(expectedExceptions = ZapClientException.class) 32 | public void shouldFailInCasoOfAnInvalidTargetUrl() { 33 | zapClient.analyze(AnalysisInfo.builder().targetUrl(WRONG_TARGET_URL).build()); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /zap-client-api/src/test/java/br/com/softplan/security/zap/api/authentication/FormAuthenticationHandlerIT.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.authentication; 2 | 3 | import static br.com.softplan.security.zap.api.authentication.AbstractAuthenticationHandler.*; 4 | import static org.testng.Assert.*; 5 | 6 | import org.testng.annotations.Test; 7 | 8 | import br.com.softplan.security.zap.api.model.AuthenticationInfo; 9 | import br.com.softplan.security.zap.api.util.BaseIT; 10 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponseSet; 11 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 12 | 13 | public class FormAuthenticationHandlerIT extends BaseIT { 14 | 15 | @Test 16 | public void handleAuthenticationTest() throws ClientApiException { 17 | AuthenticationInfo authenticationInfo = AuthenticationInfo.builder() 18 | .buildFormAuthenticationInfo("http://app:8080/login", "username", "password"); 19 | 20 | String targetUrl = "targetUrl"; 21 | FormAuthenticationHandler formHandler = new FormAuthenticationHandler(api, zapInfo, authenticationInfo); 22 | formHandler.handleAuthentication(targetUrl); 23 | 24 | ApiResponseSet response = (ApiResponseSet) api.authentication.getAuthenticationMethod(ZAP_DEFAULT_CONTEXT_ID); 25 | assertEquals(response.getAttribute("loginUrl"), authenticationInfo.getLoginUrl()); 26 | assertEquals(response.getAttribute("loginRequestData"), authenticationInfo.getLoginRequestData()); 27 | assertEquals(response.getAttribute("methodName"), "formBasedAuthentication"); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /zap-client-api/src/test/java/br/com/softplan/security/zap/api/util/LogbackTestAppender.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import ch.qos.logback.classic.Level; 8 | import ch.qos.logback.classic.spi.ILoggingEvent; 9 | import ch.qos.logback.core.AppenderBase; 10 | 11 | /** 12 | * Utility class to provide testing capabilities related to logs 13 | * (e.g. to check if a warning message was logged). 14 | * 15 | * @author pdsec 16 | */ 17 | public class LogbackTestAppender extends AppenderBase { 18 | 19 | private final List log = new ArrayList<>(); 20 | 21 | public LogbackTestAppender() { 22 | setName(getClass().getSimpleName()); 23 | } 24 | 25 | @Override 26 | protected void append(ILoggingEvent eventObject) { 27 | doAppend(eventObject); 28 | } 29 | 30 | @Override 31 | public synchronized void doAppend(ILoggingEvent eventObject) { 32 | log.add(eventObject); 33 | } 34 | 35 | public List getLog() { 36 | return Collections.unmodifiableList(log); 37 | } 38 | 39 | public boolean hasError() { 40 | return hasLevel(Level.ERROR); 41 | } 42 | 43 | public boolean hasWarn() { 44 | return hasLevel(Level.WARN); 45 | } 46 | 47 | public boolean hasLevel(Level level) { 48 | for (ILoggingEvent loggingEvent : log) { 49 | if (loggingEvent.getLevel().equals(level)) { 50 | return true; 51 | } 52 | } 53 | return false; 54 | } 55 | 56 | public void clearLog() { 57 | log.clear(); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /zap-maven-plugin-core/src/main/java/br/com/softplan/security/zap/maven/AnalyzeMojo.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.maven; 2 | 3 | import org.apache.maven.plugin.MojoExecutionException; 4 | import org.apache.maven.plugin.MojoFailureException; 5 | import org.apache.maven.plugins.annotations.Mojo; 6 | 7 | import br.com.softplan.security.zap.api.ZapClient; 8 | import br.com.softplan.security.zap.api.model.AnalysisInfo; 9 | import br.com.softplan.security.zap.api.model.AuthenticationInfo; 10 | import br.com.softplan.security.zap.api.report.ZapReport; 11 | import br.com.softplan.security.zap.commons.ZapInfo; 12 | import br.com.softplan.security.zap.commons.boot.Zap; 13 | 14 | /** 15 | * Goal to execute a full analysis with ZAP. 16 | *

17 | * It will run the default Spider, and optionally the AJAX Spider, proceed with the Active Scan and generate the reports. 18 | * 19 | * @author pdsec 20 | */ 21 | @Mojo(name="analyze") 22 | public class AnalyzeMojo extends ZapMojo { 23 | 24 | @Override 25 | public void doExecute() throws MojoExecutionException, MojoFailureException { 26 | getLog().info("Starting ZAP analysis at target: " + getTargetUrl()); 27 | 28 | ZapInfo zapInfo = buildZapInfo(); 29 | AuthenticationInfo authenticationInfo = buildAuthenticationInfo(); 30 | AnalysisInfo analysisInfo = buildAnalysisInfo(); 31 | 32 | ZapClient zapClient = new ZapClient(zapInfo, authenticationInfo); 33 | try { 34 | Zap.startZap(zapInfo); 35 | ZapReport zapReport = zapClient.analyze(analysisInfo); 36 | saveReport(zapReport); 37 | } finally { 38 | Zap.stopZap(); 39 | } 40 | 41 | getLog().info("ZAP analysis finished."); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/core/ClientApiException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Zed Attack Proxy (ZAP) and its related class files. 3 | * 4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 5 | * 6 | * Copyright 2012 The Zed Attack Proxy Team 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | package br.com.softplan.security.zap.zaproxy.clientapi.core; 21 | 22 | 23 | public class ClientApiException extends Exception { 24 | 25 | private static final long serialVersionUID = 1L; 26 | 27 | private final String code; 28 | private final String detail; 29 | 30 | public ClientApiException(Exception e) { 31 | super(e); 32 | this.code = null; 33 | this.detail = null; 34 | } 35 | 36 | public ClientApiException(String s) { 37 | super(s); 38 | this.code = null; 39 | this.detail = null; 40 | } 41 | 42 | public ClientApiException(String message, String code, String detail) { 43 | super(message); 44 | this.code = code; 45 | this.detail = detail; 46 | } 47 | 48 | public String getCode() { 49 | return code; 50 | } 51 | 52 | public String getDetail() { 53 | return detail; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /zap-client-api/src/test/java/br/com/softplan/security/zap/api/authentication/CasAuthenticationHandlerIT.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.authentication; 2 | 3 | import static br.com.softplan.security.zap.api.authentication.AbstractAuthenticationHandler.*; 4 | import static org.testng.Assert.*; 5 | 6 | import org.testng.annotations.Test; 7 | 8 | import br.com.softplan.security.zap.api.model.AuthenticationInfo; 9 | import br.com.softplan.security.zap.api.util.BaseIT; 10 | import br.com.softplan.security.zap.api.util.ZapProperties; 11 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponseSet; 12 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 13 | 14 | public class CasAuthenticationHandlerIT extends BaseIT { 15 | 16 | @Test 17 | public void handleAuthenticationTest() throws ClientApiException { 18 | AuthenticationInfo authenticationInfo = AuthenticationInfo.builder() 19 | .buildCasAuthenticationInfo("http://app:8080/login", "username", "password", "protectedPage1", "protectedPage2"); 20 | 21 | String targetUrl = "http://" + ZapProperties.getHost() + ":" + ZapProperties.getPort(); 22 | CasAuthenticationHandler casHandler = new CasAuthenticationHandler(api, zapInfo, authenticationInfo); 23 | casHandler.handleAuthentication(targetUrl); 24 | 25 | ApiResponseSet response = (ApiResponseSet) api.authentication.getAuthenticationMethod(ZAP_DEFAULT_CONTEXT_ID); 26 | assertEquals(response.getAttribute("loginUrl"), authenticationInfo.getLoginUrl()); 27 | assertEquals(response.getAttribute("protectedPages"), authenticationInfo.getProtectedPagesSeparatedByComma()); 28 | assertEquals(response.getAttribute("methodName"), "scriptBasedAuthentication"); 29 | assertEquals(response.getAttribute("scriptName"), "cas-auth"); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/Params.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class Params { 35 | 36 | private ClientApi api = null; 37 | 38 | public Params(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | /** 43 | * Shows the parameters for the specified site, or for all sites if the site is not specified 44 | */ 45 | public ApiResponse params(String site) throws ClientApiException { 46 | Map map = null; 47 | map = new HashMap(); 48 | map.put("site", site); 49 | return api.callApi("params", "view", "params", map); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /zap-maven-plugin-core/src/main/java/br/com/softplan/security/zap/maven/SeleniumAnalyzeMojo.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.maven; 2 | 3 | import org.apache.maven.plugin.MojoExecutionException; 4 | import org.apache.maven.plugin.MojoFailureException; 5 | import org.apache.maven.plugins.annotations.Mojo; 6 | 7 | import br.com.softplan.security.zap.api.ZapClient; 8 | import br.com.softplan.security.zap.api.model.AnalysisInfo; 9 | import br.com.softplan.security.zap.api.model.AnalysisType; 10 | import br.com.softplan.security.zap.api.model.AuthenticationInfo; 11 | import br.com.softplan.security.zap.api.report.ZapReport; 12 | import br.com.softplan.security.zap.commons.ZapInfo; 13 | import br.com.softplan.security.zap.commons.boot.Zap; 14 | 15 | /** 16 | * Run ZAP's Active Scan and generates the reports. No Spider is executed. 17 | * This scan assumes that integration tests ran using ZAP as a proxy, so the Active Scan 18 | * is able to use the navigation done during the tests for the scan. 19 | *

20 | * Normally this goal will be executed in the phase post-integration-test, while the 21 | * goal {@code startZap} will run in the phase pre-integration-test, to make sure 22 | * ZAP is running during the tests. 23 | * 24 | * @author pdsec 25 | */ 26 | @Mojo(name="seleniumAnalyze") 27 | public class SeleniumAnalyzeMojo extends ZapMojo { 28 | 29 | @Override 30 | public void doExecute() throws MojoExecutionException, MojoFailureException { 31 | getLog().info("Starting ZAP analysis at target: " + super.getTargetUrl()); 32 | 33 | ZapInfo zapInfo = buildZapInfo(); 34 | AuthenticationInfo authenticationInfo = buildAuthenticationInfo(); 35 | AnalysisInfo analysisInfo = buildAnalysisInfo(AnalysisType.ACTIVE_SCAN_ONLY); 36 | 37 | ZapClient zapClient = new ZapClient(zapInfo, authenticationInfo); 38 | try { 39 | ZapReport zapReport = zapClient.analyze(analysisInfo); 40 | saveReport(zapReport); 41 | } finally { 42 | Zap.stopZap(); 43 | } 44 | 45 | getLog().info("ZAP analysis finished."); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/core/ApiResponseElement.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Zed Attack Proxy (ZAP) and its related class files. 3 | * 4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package br.com.softplan.security.zap.zaproxy.clientapi.core; 19 | 20 | import org.w3c.dom.Node; 21 | 22 | public class ApiResponseElement extends ApiResponse { 23 | 24 | public static ApiResponseElement OK = new ApiResponseElement("Result", "OK"); 25 | public static ApiResponseElement FAIL = new ApiResponseElement("Result", "FAIL"); 26 | 27 | private String value = null; 28 | 29 | public ApiResponseElement(String name) { 30 | super(name); 31 | } 32 | 33 | public ApiResponseElement(String name, String value) { 34 | super(name); 35 | this.value = value; 36 | } 37 | 38 | public ApiResponseElement(Node node, ApiResponse template) { 39 | super(node.getNodeName()); 40 | this.value = node.getTextContent(); 41 | 42 | } 43 | 44 | public ApiResponseElement(Node node) { 45 | super(node.getNodeName()); 46 | this.value = node.getTextContent(); 47 | } 48 | 49 | public String getValue() { 50 | return value; 51 | } 52 | 53 | @Override 54 | public String toString(int indent) { 55 | StringBuilder sb = new StringBuilder(); 56 | for (int i=0 ; i < indent; i++) { 57 | sb.append("\t"); 58 | } 59 | sb.append("ApiResponseElement "); 60 | sb.append(this.getName()); 61 | sb.append(" = " ); 62 | sb.append(this.getValue()); 63 | sb.append("\n"); 64 | return sb.toString(); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /zap-client-api/src/test/java/br/com/softplan/security/zap/api/report/ZapReportTest.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.report; 2 | 3 | import static org.testng.Assert.assertEquals; 4 | import static org.testng.Assert.assertTrue; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | 9 | import org.testng.annotations.BeforeMethod; 10 | import org.testng.annotations.Test; 11 | 12 | public class ZapReportTest { 13 | 14 | private static final String HTML_REPORT_CONTENT = "htmlReport"; 15 | private static final String XML_REPORT_CONTENT = "xmlReport"; 16 | private static final String[] SPIDER_RESULTS = {"url1", "url2"}; 17 | 18 | public ZapReport zapReport; 19 | 20 | @BeforeMethod 21 | public void setUp() { 22 | zapReport = new ZapReport(HTML_REPORT_CONTENT.getBytes(), XML_REPORT_CONTENT.getBytes(), new ArrayList(Arrays.asList(SPIDER_RESULTS))); 23 | } 24 | 25 | @Test 26 | public void testReportContents() { 27 | assertEquals(zapReport.getHtmlReport(), HTML_REPORT_CONTENT.getBytes()); 28 | assertEquals(zapReport.getXmlReport(), XML_REPORT_CONTENT.getBytes()); 29 | assertEquals(zapReport.getHtmlReportAsString(), HTML_REPORT_CONTENT); 30 | assertEquals(zapReport.getXmlReportAsString(), XML_REPORT_CONTENT); 31 | 32 | assertTrue(zapReport.getSpiderResults().contains("url1")); 33 | assertTrue(zapReport.getSpiderResults().contains("url2")); 34 | assertTrue(zapReport.getHtmlSpiderResultsAsString().contains("url1")); 35 | assertTrue(zapReport.getHtmlSpiderResultsAsString().contains("url2")); 36 | assertTrue(zapReport.getXmlSpiderResultsAsString().contains("url2")); 37 | assertTrue(zapReport.getXmlSpiderResultsAsString().contains("url2")); 38 | } 39 | 40 | @Test 41 | public void testByteAndStringReportsEquality() { 42 | assertEquals(new String(zapReport.getXmlReport()), zapReport.getXmlReportAsString()); 43 | assertEquals(new String(zapReport.getHtmlReport()), zapReport.getHtmlReportAsString()); 44 | assertEquals(new String(zapReport.getHtmlSpiderResults()), zapReport.getHtmlSpiderResultsAsString()); 45 | assertEquals(new String(zapReport.getXmlSpiderResults()), zapReport.getXmlSpiderResultsAsString()); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/report/SpiderResultsReportBuilder.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.report; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Class that builds the HTML and XML reports with the Spider results. 7 | * 8 | * @author pdsec 9 | */ 10 | public final class SpiderResultsReportBuilder { 11 | 12 | private static final String TITLE = "ZAP Spider Results"; 13 | private static final String HEADER = "Visited URLs"; 14 | 15 | public static String buildHtmlReport(List urls) { 16 | StringBuilder builder = new StringBuilder(); 17 | builder.append("\n"); 18 | 19 | builder.append(" \n"); 20 | builder.append(" \n"); 21 | builder.append(" ").append(TITLE).append("\n"); 22 | builder.append(" \n"); 23 | 24 | builder.append(" \n"); 25 | builder.append("

").append(TITLE).append("

\n"); 26 | 27 | builder.append(" \n"); 28 | builder.append(" \n"); 29 | builder.append(" \n"); 31 | 32 | for (String url : urls) { 33 | builder.append(" \n"); 35 | } 36 | 37 | builder.append("
") 30 | .append(HEADER).append("
") 34 | .append(url).append("
\n"); 38 | builder.append(" \n"); 39 | builder.append("\n"); 40 | 41 | return builder.toString(); 42 | } 43 | 44 | public static String buildXmlReport(List urls) { 45 | StringBuilder builder = new StringBuilder("\n"); 46 | 47 | builder.append("\n"); 48 | for (String url : urls) { 49 | builder.append(" ").append(url).append("\n"); 50 | } 51 | builder.append("\n"); 52 | 53 | return builder.toString(); 54 | } 55 | 56 | private SpiderResultsReportBuilder() {} 57 | 58 | } 59 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/Reveal.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class Reveal { 35 | 36 | private ClientApi api = null; 37 | 38 | public Reveal(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | /** 43 | * This component is optional and therefore the API will only work if it is installed 44 | */ 45 | public ApiResponse reveal() throws ClientApiException { 46 | Map map = null; 47 | return api.callApi("reveal", "view", "reveal", map); 48 | } 49 | 50 | /** 51 | * This component is optional and therefore the API will only work if it is installed 52 | */ 53 | public ApiResponse setReveal(String apikey, String reveal) throws ClientApiException { 54 | Map map = null; 55 | map = new HashMap(); 56 | if (apikey != null) { 57 | map.put("apikey", apikey); 58 | } 59 | map.put("reveal", reveal); 60 | return api.callApi("reveal", "action", "setReveal", map); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/authentication/SeleniumAuthenticationHandler.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.authentication; 2 | 3 | import org.openqa.selenium.By; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import br.com.softplan.security.zap.api.model.AuthenticationInfo; 10 | import br.com.softplan.security.zap.commons.ZapInfo; 11 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 12 | 13 | /** 14 | * Class to handle authentication via Selenium. 15 | *

16 | * This will try to mimic the regular authentication process with Selenium. 17 | * It is particularly useful for more complex cases where it's easier to 18 | * just open the browser and perform the authentication. 19 | * 20 | * @author pdsec 21 | */ 22 | public class SeleniumAuthenticationHandler extends AbstractAuthenticationHandler { 23 | 24 | private static final Logger LOGGER = LoggerFactory.getLogger(SeleniumAuthenticationHandler.class); 25 | 26 | protected SeleniumAuthenticationHandler(ClientApi api, ZapInfo zapInfo, AuthenticationInfo authenticationInfo) { 27 | super(api, zapInfo, authenticationInfo); 28 | } 29 | 30 | @Override 31 | protected void setupAuthentication(String targetUrl) { 32 | addHttpSessionTokens(targetUrl); 33 | triggerAuthenticationViaWebDriver(); 34 | setHttpSessionAsActive(targetUrl); 35 | } 36 | 37 | private void triggerAuthenticationViaWebDriver() { 38 | AuthenticationInfo authenticationInfo = getAuthenticationInfo(); 39 | LOGGER.info("--- Performing authentication via Selenium ({}) ---", authenticationInfo.getSeleniumDriver()); 40 | 41 | WebDriver driver = WebDriverFactory.makeWebDriver(getZapInfo(), authenticationInfo); 42 | driver.get(authenticationInfo.getLoginUrl()); 43 | 44 | WebElement usernameField = driver.findElement(By.id(authenticationInfo.getUsernameParameter())); 45 | usernameField.sendKeys(authenticationInfo.getUsername()); 46 | 47 | WebElement passwordField = driver.findElement(By.id(authenticationInfo.getPasswordParameter())); 48 | passwordField.sendKeys(authenticationInfo.getPassword()); 49 | 50 | passwordField.submit(); 51 | 52 | driver.quit(); 53 | LOGGER.info("--- Finished performing authentication via Selenium ---\n"); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/report/ZapReport.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.report; 2 | 3 | import java.nio.charset.StandardCharsets; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | /** 8 | * Class that encapsulates the results of a ZAP analysis. 9 | *

10 | * Reports are available in XML and HTML formats. 11 | * 12 | * @author pdsec 13 | */ 14 | public class ZapReport { 15 | 16 | private byte[] htmlReport; 17 | private byte[] xmlReport; 18 | 19 | private List spiderResults; 20 | private String htmlSpiderResults; 21 | private String xmlSpiderResults; 22 | 23 | /** 24 | * Creates a new {@code ZapReport} instance based on the ZAP reports and the Spider results. 25 | * 26 | * @param htmlReport byte representation of the HTML Report. 27 | * @param xmlReport byte representation of the XML Report. 28 | * @param spiderResults the list with the URLs visited by the Spider. 29 | */ 30 | public ZapReport(byte[] htmlReport, byte[] xmlReport, List spiderResults) { 31 | this.htmlReport = htmlReport; 32 | this.xmlReport = xmlReport; 33 | this.spiderResults = spiderResults; 34 | 35 | buildSpiderResultsReports(spiderResults); 36 | } 37 | 38 | private void buildSpiderResultsReports(List spiderResults) { 39 | this.htmlSpiderResults = SpiderResultsReportBuilder.buildHtmlReport(spiderResults); 40 | this.xmlSpiderResults = SpiderResultsReportBuilder.buildXmlReport(spiderResults); 41 | } 42 | 43 | public String getHtmlReportAsString() { 44 | return new String(this.htmlReport, StandardCharsets.UTF_8); 45 | } 46 | 47 | public byte[] getHtmlReport() { 48 | return this.htmlReport; 49 | } 50 | 51 | public String getXmlReportAsString() { 52 | return new String(this.xmlReport, StandardCharsets.UTF_8); 53 | } 54 | 55 | public byte[] getXmlReport() { 56 | return this.xmlReport; 57 | } 58 | 59 | public List getSpiderResults() { 60 | return Collections.unmodifiableList(spiderResults); 61 | } 62 | 63 | public String getHtmlSpiderResultsAsString() { 64 | return htmlSpiderResults; 65 | } 66 | 67 | public byte[] getHtmlSpiderResults() { 68 | return htmlSpiderResults.getBytes(StandardCharsets.UTF_8); 69 | } 70 | 71 | public String getXmlSpiderResultsAsString() { 72 | return xmlSpiderResults; 73 | } 74 | 75 | public byte[] getXmlSpiderResults() { 76 | return xmlSpiderResults.getBytes(); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /zap-utils/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | br.com.softplan.security.zap 7 | zap-maven-plugin-parent 8 | 1.2.2-0-SNAPSHOT 9 | ../zap-maven-plugin-parent 10 | 11 | 12 | zap-utils 13 | 14 | ZAP Utils 15 | Utils module responsible for ZAP automatic initialization 16 | https://github.com/pdsoftplan/zap-maven-plugin 17 | 2015 18 | 19 | Softplan 20 | https://www.softplan.com.br 21 | 22 | 23 | 24 | 25 | Apache License, Version 2.0 26 | http://www.apache.org/licenses/LICENSE-2.0.txt 27 | repo 28 | 29 | 30 | 31 | 32 | 33 | tfcporciuncula 34 | Thiago Porciúncula 35 | thiago.porciuncula@softplan.com.br 36 | Softplan 37 | 38 | 39 | fabio.resner 40 | Fábio Resner 41 | fabio.resner@softplan.com.br 42 | Softplan 43 | 44 | 45 | 46 | 47 | scm:git:git@github.com:pdsoftplan/zap-maven-plugin.git 48 | scm:git:git@github.com:pdsoftplan/zap-maven-plugin.git 49 | https://github.com/pdsoftplan/zap-maven-plugin 50 | 51 | 52 | 53 | GitHub 54 | https://github.com/pdsoftplan/zap-maven-plugin/issues 55 | 56 | 57 | Travis 58 | https://travis-ci.org/pdsoftplan/zap-maven-plugin 59 | 60 | 61 | 62 | 63 | org.slf4j 64 | slf4j-api 65 | 66 | 67 | org.apache.commons 68 | commons-lang3 69 | 70 | 71 | commons-io 72 | commons-io 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/authentication/AuthenticationScript.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.authentication; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.UnsupportedEncodingException; 8 | import java.net.URISyntaxException; 9 | 10 | import org.apache.commons.io.IOUtils; 11 | 12 | import br.com.softplan.security.zap.commons.authentication.AuthenticationScripts; 13 | import br.com.softplan.security.zap.commons.boot.ZapDockerBoot; 14 | 15 | public class AuthenticationScript { 16 | 17 | private String name; 18 | private String description; 19 | private String fileName; 20 | private String relativePath; 21 | private String path; 22 | 23 | private File scriptTempFile; 24 | 25 | public AuthenticationScript(String name, String description) { 26 | this.name = name; 27 | this.description = description; 28 | this.fileName = name + AuthenticationScripts.EXTENSION; 29 | this.relativePath = AuthenticationScripts.RELATIVE_PATH + fileName; 30 | 31 | this.path = AuthenticationScript.class.getResource(relativePath).getPath(); 32 | } 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public String getDescription() { 39 | return description; 40 | } 41 | 42 | public String getFileName() { 43 | return fileName; 44 | } 45 | 46 | public String getRelativePath() { 47 | return relativePath; 48 | } 49 | 50 | public String getPath(boolean isZapRunningOnDocker) throws IOException, URISyntaxException { 51 | if (isZapRunningOnDocker) { 52 | return ZapDockerBoot.CAS_AUTH_SCRIPT_DEFAULT_DOCKER_PATH + fileName; 53 | } 54 | if (scriptFileIsNotAccessible()) { 55 | return getCasAuthScriptTempFile().getAbsolutePath(); 56 | } 57 | return path; 58 | } 59 | 60 | private boolean scriptFileIsNotAccessible() throws UnsupportedEncodingException { 61 | return !new File(path).exists(); 62 | } 63 | 64 | private File getCasAuthScriptTempFile() throws IOException { 65 | if (scriptTempFile == null) { 66 | scriptTempFile = createCasAuthScriptTempFile(); 67 | } 68 | return scriptTempFile; 69 | } 70 | 71 | private File createCasAuthScriptTempFile() throws IOException { 72 | File tempFile = File.createTempFile(name, AuthenticationScripts.EXTENSION); 73 | tempFile.deleteOnExit(); 74 | 75 | InputStream casAuthScriptInputStream = AuthenticationScript.class.getResourceAsStream(relativePath); 76 | try (FileOutputStream fileOutputStream = new FileOutputStream(tempFile)) { 77 | IOUtils.copy(casAuthScriptInputStream, fileOutputStream); 78 | } 79 | return tempFile; 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/authentication/FormAuthenticationHandler.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.authentication; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.net.URLEncoder; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import br.com.softplan.security.zap.api.ZapHelper; 10 | import br.com.softplan.security.zap.api.exception.ZapClientException; 11 | import br.com.softplan.security.zap.api.model.AuthenticationInfo; 12 | import br.com.softplan.security.zap.commons.ZapInfo; 13 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 14 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 15 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 16 | 17 | /** 18 | * Class to handle form based authentication via ZAP. 19 | * 20 | * @author pdsec 21 | */ 22 | public class FormAuthenticationHandler extends AbstractAuthenticationHandler { 23 | 24 | private static final Logger LOGGER = LoggerFactory.getLogger(FormAuthenticationHandler.class); 25 | 26 | private static final String FORM_AUTHENTICATION_TYPE = "formBasedAuthentication"; 27 | 28 | private static final String LOGIN_URL_PARAM = "loginUrl"; 29 | private static final String LOGIN_REQUEST_DATA_PARAM = "loginRequestData"; 30 | 31 | protected FormAuthenticationHandler(ClientApi api, ZapInfo zapInfo, AuthenticationInfo authenticationInfo) { 32 | super(api, zapInfo, authenticationInfo); 33 | } 34 | 35 | @Override 36 | protected void setupAuthentication(String targetUrl) { 37 | setFormAuthenticationMethod(); 38 | createAndEnableUser(); 39 | setupUserCredentials(); 40 | enableForcedUserMode(); 41 | } 42 | 43 | private void setFormAuthenticationMethod() { 44 | try { 45 | String encodedLoginUrl = URLEncoder.encode(getAuthenticationInfo().getLoginUrl(), UTF_8); 46 | String encodedLoginRequestData = URLEncoder.encode(getAuthenticationInfo().getFullLoginRequestData(), UTF_8); 47 | String authParams = LOGIN_URL_PARAM + "=" + encodedLoginUrl + 48 | "&" + LOGIN_REQUEST_DATA_PARAM + "=" + encodedLoginRequestData; 49 | 50 | LOGGER.debug("Setting form authentication method with params: {}", authParams); 51 | ApiResponse response = getApi().authentication.setAuthenticationMethod( 52 | getApiKey(), ZAP_DEFAULT_CONTEXT_ID, FORM_AUTHENTICATION_TYPE, authParams); 53 | ZapHelper.validateResponse(response, "Set form authentication method."); 54 | } catch (ClientApiException | UnsupportedEncodingException e) { 55 | LOGGER.error("Error setting up form authentication method.", e); 56 | throw new ZapClientException(e); 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/authentication/HttpAuthenticationHandler.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.authentication; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.net.URLEncoder; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import br.com.softplan.security.zap.api.ZapHelper; 10 | import br.com.softplan.security.zap.api.exception.ZapClientException; 11 | import br.com.softplan.security.zap.api.model.AuthenticationInfo; 12 | import br.com.softplan.security.zap.commons.ZapInfo; 13 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 14 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 15 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 16 | 17 | /** 18 | * Class to handle HTTP based authentication via ZAP. 19 | * 20 | * @author pdsec 21 | */ 22 | public class HttpAuthenticationHandler extends AbstractAuthenticationHandler { 23 | 24 | private static final Logger LOGGER = LoggerFactory.getLogger(HttpAuthenticationHandler.class); 25 | 26 | private static final String HTTP_AUTHENTICATION_TYPE = "httpAuthentication"; 27 | 28 | private static final String HOSTNAME_PARAM = "hostname"; 29 | private static final String REALM_PARAM = "realm"; 30 | private static final String PORT_PARAM = "port"; 31 | 32 | protected HttpAuthenticationHandler(ClientApi api, ZapInfo zapInfo, AuthenticationInfo authenticationInfo) { 33 | super(api, zapInfo, authenticationInfo); 34 | } 35 | 36 | @Override 37 | protected void setupAuthentication(String targetUrl) { 38 | setHttpAuthenticationMethod(); 39 | createAndEnableUser(); 40 | setupUserCredentials(); 41 | enableForcedUserMode(); 42 | } 43 | 44 | private void setHttpAuthenticationMethod() { 45 | try { 46 | String encodedHostname = URLEncoder.encode(getAuthenticationInfo().getHostname(), UTF_8); 47 | String encodedRealm = URLEncoder.encode(getAuthenticationInfo().getRealm(), UTF_8); 48 | String authParams = HOSTNAME_PARAM + "=" + encodedHostname + 49 | "&" + REALM_PARAM + "=" + encodedRealm + 50 | "&" + PORT_PARAM + "=" + getAuthenticationInfo().getPortAsString(); 51 | 52 | LOGGER.debug("Setting HTTP authentication method with params: {}", authParams); 53 | ApiResponse response = getApi().authentication.setAuthenticationMethod( 54 | getApiKey(), ZAP_DEFAULT_CONTEXT_ID, HTTP_AUTHENTICATION_TYPE, authParams); 55 | ZapHelper.validateResponse(response, "Set HTTP authentication method."); 56 | } catch (ClientApiException | UnsupportedEncodingException e) { 57 | LOGGER.error("Error setting up HTTP authentication method.", e); 58 | throw new ZapClientException(e); 59 | } 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/core/ApiResponseSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Zed Attack Proxy (ZAP) and its related class files. 3 | * 4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package br.com.softplan.security.zap.zaproxy.clientapi.core; 19 | 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | import java.util.Map.Entry; 23 | 24 | import org.w3c.dom.Node; 25 | 26 | public class ApiResponseSet extends ApiResponse { 27 | 28 | private String[] attributes = null; 29 | private Map values = null; 30 | 31 | public ApiResponseSet(String name, String[] attributes) { 32 | super(name); 33 | this.attributes = attributes; 34 | } 35 | 36 | public ApiResponseSet(String name, Map values) { 37 | super(name); 38 | this.values = values; 39 | } 40 | 41 | public ApiResponseSet(Node node) throws ClientApiException { 42 | super(node.getNodeName()); 43 | Node child = node.getFirstChild(); 44 | this.values = new HashMap(); 45 | while (child != null) { 46 | ApiResponseElement elem = (ApiResponseElement) ApiResponseFactory.getResponse(child); 47 | values.put(elem.getName(), elem.getValue()); 48 | child = child.getNextSibling(); 49 | } 50 | } 51 | 52 | public String[] getAttributes() { 53 | return attributes; 54 | } 55 | 56 | public String getAttribute(String name) { 57 | return this.values.get(name); 58 | } 59 | 60 | @Override 61 | public String toString(int indent) { 62 | StringBuilder sb = new StringBuilder(); 63 | for (int i=0 ; i < indent; i++) { 64 | sb.append("\t"); 65 | } 66 | sb.append("ApiResponseSet "); 67 | sb.append(this.getName()); 68 | sb.append(" : [\n"); 69 | for (Entry val : values.entrySet()) { 70 | for (int i=0 ; i < indent+1; i++) { 71 | sb.append("\t"); 72 | } 73 | sb.append(val.getKey()); 74 | sb.append(" = "); 75 | sb.append(val.getValue()); 76 | sb.append("\n"); 77 | } 78 | for (int i=0 ; i < indent; i++) { 79 | sb.append("\t"); 80 | } 81 | sb.append("]\n"); 82 | return sb.toString(); 83 | } 84 | 85 | 86 | } 87 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/ZapClient.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import br.com.softplan.security.zap.api.analysis.Analyzer; 7 | import br.com.softplan.security.zap.api.analysis.AnalyzerFactory; 8 | import br.com.softplan.security.zap.api.authentication.AuthenticationHandler; 9 | import br.com.softplan.security.zap.api.authentication.AuthenticationHandlerFactory; 10 | import br.com.softplan.security.zap.api.model.AnalysisInfo; 11 | import br.com.softplan.security.zap.api.model.AuthenticationInfo; 12 | import br.com.softplan.security.zap.api.report.ZapReport; 13 | import br.com.softplan.security.zap.commons.ZapInfo; 14 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 15 | 16 | /** 17 | * The main client for starting a ZAP analysis. 18 | * 19 | * @author pdsec 20 | */ 21 | public class ZapClient { 22 | 23 | private String apiKey; 24 | private ClientApi api; 25 | 26 | private AuthenticationHandler authenticationHandler; 27 | private SessionManager sessionManager; 28 | 29 | private static final Logger LOGGER = LoggerFactory.getLogger(ZapClient.class); 30 | 31 | /** 32 | * Constructs the client providing information about ZAP. 33 | * 34 | * @param zapInfo required information about the ZAP instance. 35 | */ 36 | public ZapClient(ZapInfo zapInfo) { 37 | this.apiKey = zapInfo.getApiKey(); 38 | this.api = new ClientApi(zapInfo.getHost(), zapInfo.getPort()); 39 | this.sessionManager = new SessionManager(); 40 | } 41 | 42 | /** 43 | * Constructs the client providing information about ZAP and the authentication to be done. 44 | * 45 | * @param zapInfo required information about the ZAP instance. 46 | * @param authenticationInfo information about the authentication to be done. 47 | */ 48 | public ZapClient(ZapInfo zapInfo, AuthenticationInfo authenticationInfo) { 49 | this(zapInfo); 50 | this.authenticationHandler = AuthenticationHandlerFactory.makeHandler(api, zapInfo, authenticationInfo); 51 | } 52 | 53 | public ZapReport analyze(AnalysisInfo analysisInfo) { 54 | if (analysisInfo.shouldStartNewSession()) { 55 | sessionManager.createNewSession(api, apiKey); 56 | } 57 | 58 | ZapHelper.includeInContext(api, apiKey, analysisInfo); 59 | ZapHelper.setTechnologiesInContext(api, apiKey, analysisInfo); 60 | 61 | if (authenticationHandler != null) { 62 | authenticationHandler.handleAuthentication(analysisInfo.getTargetUrl()); 63 | } 64 | 65 | LOGGER.info("--- Starting analysis ---"); 66 | 67 | Analyzer analyzer = AnalyzerFactory.makeAnalyzer(apiKey, api, analysisInfo); 68 | ZapReport zapReport = analyzer.analyze(analysisInfo); 69 | 70 | LOGGER.info("--- Finished analysis ---\n"); 71 | 72 | return zapReport; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/SessionManagement.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class SessionManagement { 35 | 36 | private ClientApi api = null; 37 | 38 | public SessionManagement(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | public ApiResponse getSupportedSessionManagementMethods() throws ClientApiException { 43 | Map map = null; 44 | return api.callApi("sessionManagement", "view", "getSupportedSessionManagementMethods", map); 45 | } 46 | 47 | public ApiResponse getSessionManagementMethodConfigParams(String methodname) throws ClientApiException { 48 | Map map = null; 49 | map = new HashMap(); 50 | map.put("methodName", methodname); 51 | return api.callApi("sessionManagement", "view", "getSessionManagementMethodConfigParams", map); 52 | } 53 | 54 | public ApiResponse getSessionManagementMethod(String contextid) throws ClientApiException { 55 | Map map = null; 56 | map = new HashMap(); 57 | map.put("contextId", contextid); 58 | return api.callApi("sessionManagement", "view", "getSessionManagementMethod", map); 59 | } 60 | 61 | public ApiResponse setSessionManagementMethod(String apikey, String contextid, String methodname, String methodconfigparams) throws ClientApiException { 62 | Map map = null; 63 | map = new HashMap(); 64 | if (apikey != null) { 65 | map.put("apikey", apikey); 66 | } 67 | map.put("contextId", contextid); 68 | map.put("methodName", methodname); 69 | map.put("methodConfigParams", methodconfigparams); 70 | return api.callApi("sessionManagement", "action", "setSessionManagementMethod", map); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/authentication/WebDriverFactory.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.authentication; 2 | 3 | import org.openqa.selenium.Proxy; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.firefox.FirefoxDriver; 6 | import org.openqa.selenium.firefox.FirefoxProfile; 7 | import org.openqa.selenium.htmlunit.HtmlUnitDriver; 8 | import org.openqa.selenium.phantomjs.PhantomJSDriver; 9 | import org.openqa.selenium.remote.DesiredCapabilities; 10 | 11 | import br.com.softplan.security.zap.api.model.AuthenticationInfo; 12 | import br.com.softplan.security.zap.commons.ZapInfo; 13 | 14 | public final class WebDriverFactory { 15 | 16 | private static final int FIREFOX_MANUAL_PROXY_CONFIGURATION_OPTION = 1; 17 | 18 | public static WebDriver makeWebDriver(ZapInfo zapInfo, AuthenticationInfo authenticationInfo) { 19 | String host = zapInfo.getHost(); 20 | int port = zapInfo.getPort(); 21 | 22 | switch (authenticationInfo.getSeleniumDriver()) { 23 | case HTMLUNIT: return makeHtmlUnitDriver(host, port); 24 | case FIREFOX: return makeFirefoxDriver(host, port); 25 | // case CHROME: return makeChromeDriver(host, port); 26 | case PHANTOMJS: return makePhantomJSDriver(host, port); 27 | default: return makeFirefoxDriver(host, port); 28 | } 29 | } 30 | 31 | public static HtmlUnitDriver makeHtmlUnitDriver(String host, int port) { 32 | HtmlUnitDriver driver = new HtmlUnitDriver(); 33 | driver.setProxy(host, port); 34 | return driver; 35 | } 36 | 37 | public static FirefoxDriver makeFirefoxDriver(String host, int port) { 38 | FirefoxProfile profile = new FirefoxProfile(); 39 | profile.setPreference("network.proxy.type", FIREFOX_MANUAL_PROXY_CONFIGURATION_OPTION); 40 | profile.setPreference("network.proxy.share_proxy_settings", true); 41 | profile.setPreference("network.proxy.no_proxies_on", ""); 42 | profile.setPreference("network.proxy.http", host); 43 | profile.setPreference("network.proxy.http_port", port); 44 | 45 | return new FirefoxDriver(profile); 46 | } 47 | 48 | // Chrome support was dropped due to ChromeDriver being incompatible with the RemoteDriver version that PhantomJSDriver uses 49 | // public static ChromeDriver makeChromeDriver(String host, int port) { 50 | // DesiredCapabilities capabilities = DesiredCapabilities.chrome(); 51 | // capabilities.setCapability("proxy", createProxy(host, port)); 52 | // 53 | // return new ChromeDriver(capabilities); 54 | // } 55 | 56 | private static WebDriver makePhantomJSDriver(String host, int port) { 57 | DesiredCapabilities capabilities = DesiredCapabilities.phantomjs(); 58 | capabilities.setCapability("proxy", createProxy(host, port)); 59 | 60 | return new PhantomJSDriver(capabilities); 61 | } 62 | 63 | private static Proxy createProxy(String host, int port) { 64 | Proxy proxy = new Proxy(); 65 | proxy.setHttpProxy(host + ":" + port); 66 | return proxy; 67 | } 68 | 69 | private WebDriverFactory() {} 70 | 71 | } 72 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/Break.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class Break { 35 | 36 | private ClientApi api = null; 37 | 38 | public Break(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | public ApiResponse brk(String apikey, String type, String scope, String state) throws ClientApiException { 43 | Map map = null; 44 | map = new HashMap(); 45 | if (apikey != null) { 46 | map.put("apikey", apikey); 47 | } 48 | map.put("type", type); 49 | map.put("scope", scope); 50 | map.put("state", state); 51 | return api.callApi("break", "action", "break", map); 52 | } 53 | 54 | public ApiResponse addHttpBreakpoint(String apikey, String string, String location, String match, String inverse, String ignorecase) throws ClientApiException { 55 | Map map = null; 56 | map = new HashMap(); 57 | if (apikey != null) { 58 | map.put("apikey", apikey); 59 | } 60 | map.put("string", string); 61 | map.put("location", location); 62 | map.put("match", match); 63 | map.put("inverse", inverse); 64 | map.put("ignorecase", ignorecase); 65 | return api.callApi("break", "action", "addHttpBreakpoint", map); 66 | } 67 | 68 | public ApiResponse removeHttpBreakpoint(String apikey, String string, String location, String match, String inverse, String ignorecase) throws ClientApiException { 69 | Map map = null; 70 | map = new HashMap(); 71 | if (apikey != null) { 72 | map.put("apikey", apikey); 73 | } 74 | map.put("string", string); 75 | map.put("location", location); 76 | map.put("match", match); 77 | map.put("inverse", inverse); 78 | map.put("ignorecase", ignorecase); 79 | return api.callApi("break", "action", "removeHttpBreakpoint", map); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/Acsrf.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class Acsrf { 35 | 36 | private ClientApi api = null; 37 | 38 | public Acsrf(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | /** 43 | * Lists the names of all anti CSRF tokens 44 | */ 45 | public ApiResponse optionTokensNames() throws ClientApiException { 46 | Map map = null; 47 | return api.callApi("acsrf", "view", "optionTokensNames", map); 48 | } 49 | 50 | /** 51 | * Adds an anti CSRF token with the given name, enabled by default 52 | */ 53 | public ApiResponse addOptionToken(String apikey, String string) throws ClientApiException { 54 | Map map = null; 55 | map = new HashMap(); 56 | if (apikey != null) { 57 | map.put("apikey", apikey); 58 | } 59 | map.put("String", string); 60 | return api.callApi("acsrf", "action", "addOptionToken", map); 61 | } 62 | 63 | /** 64 | * Removes the anti CSRF token with the given name 65 | */ 66 | public ApiResponse removeOptionToken(String apikey, String string) throws ClientApiException { 67 | Map map = null; 68 | map = new HashMap(); 69 | if (apikey != null) { 70 | map.put("apikey", apikey); 71 | } 72 | map.put("String", string); 73 | return api.callApi("acsrf", "action", "removeOptionToken", map); 74 | } 75 | 76 | /** 77 | * Generate a form for testing lack of anti CSRF tokens - typically invoked via ZAP 78 | */ 79 | public byte[] genForm(String apikey, String hrefid) throws ClientApiException { 80 | Map map = null; 81 | map = new HashMap(); 82 | if (apikey != null) { 83 | map.put("apikey", apikey); 84 | } 85 | map.put("hrefId", hrefid); 86 | return api.callApiOther("acsrf", "other", "genForm", map); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/ForcedUser.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class ForcedUser { 35 | 36 | private ClientApi api = null; 37 | 38 | public ForcedUser(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | /** 43 | * Returns 'true' if 'forced user' mode is enabled, 'false' otherwise 44 | */ 45 | public ApiResponse isForcedUserModeEnabled() throws ClientApiException { 46 | Map map = null; 47 | return api.callApi("forcedUser", "view", "isForcedUserModeEnabled", map); 48 | } 49 | 50 | /** 51 | * Gets the user (ID) set as 'forced user' for the given context (ID) 52 | */ 53 | public ApiResponse getForcedUser(String contextid) throws ClientApiException { 54 | Map map = null; 55 | map = new HashMap(); 56 | map.put("contextId", contextid); 57 | return api.callApi("forcedUser", "view", "getForcedUser", map); 58 | } 59 | 60 | /** 61 | * Sets the user (ID) that should be used in 'forced user' mode for the given context (ID) 62 | */ 63 | public ApiResponse setForcedUser(String apikey, String contextid, String userid) throws ClientApiException { 64 | Map map = null; 65 | map = new HashMap(); 66 | if (apikey != null) { 67 | map.put("apikey", apikey); 68 | } 69 | map.put("contextId", contextid); 70 | map.put("userId", userid); 71 | return api.callApi("forcedUser", "action", "setForcedUser", map); 72 | } 73 | 74 | /** 75 | * Sets if 'forced user' mode should be enabled or not 76 | */ 77 | public ApiResponse setForcedUserModeEnabled(String apikey, boolean bool) throws ClientApiException { 78 | Map map = null; 79 | map = new HashMap(); 80 | if (apikey != null) { 81 | map.put("apikey", apikey); 82 | } 83 | map.put("boolean", Boolean.toString(bool)); 84 | return api.callApi("forcedUser", "action", "setForcedUserModeEnabled", map); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /zap-utils/src/main/java/br/com/softplan/security/zap/commons/boot/AbstractZapBoot.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.commons.boot; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.net.ConnectException; 6 | import java.net.HttpURLConnection; 7 | import java.net.URL; 8 | 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import br.com.softplan.security.zap.commons.exception.ZapInitializationTimeoutException; 13 | 14 | /** 15 | * Base implementation for {@link ZapBoot}, responsible for the timeout logic. 16 | * 17 | * @author pdsec 18 | */ 19 | public abstract class AbstractZapBoot implements ZapBoot { 20 | 21 | private static final Logger LOGGER = LoggerFactory.getLogger(AbstractZapBoot.class); 22 | 23 | private static final String HEAD = "HEAD"; 24 | 25 | static final long ZAP_INITIALIZATION_POLLING_INTERVAL_IN_MILLIS = 5 * 1000; 26 | 27 | static final String DEFAULT_ZAP_OPTIONS = "-daemon -config api.disablekey=true -config api.incerrordetails=true -config proxy.ip=0.0.0.0"; 28 | 29 | // If ZAP is automatically started, its log will be stored in [current working directory]/target/zap-reports, along with the generated reports 30 | static final String DEFAULT_ZAP_LOG_PATH = System.getProperty("user.dir") + File.separator + "target" + File.separator + "zap-reports"; 31 | static final String DEFAULT_ZAP_LOG_FILE_NAME = "zap.log"; 32 | 33 | static boolean isZapRunning(int port) { 34 | return isZapRunning("localhost", port); 35 | } 36 | 37 | static boolean isZapRunning(String host, int port) { 38 | return getResponseFromZap(host, port) == HttpURLConnection.HTTP_OK; 39 | } 40 | 41 | static int getResponseFromZap(String host, int port) { 42 | if (host == null) { 43 | return -1; 44 | } 45 | 46 | String url = "http://" + host + ":" + port; 47 | 48 | int responseCode = -1; 49 | try { 50 | HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); 51 | conn.setRequestMethod(HEAD); 52 | responseCode = conn.getResponseCode(); 53 | } catch (ConnectException e) { 54 | LOGGER.debug("ZAP could not be reached at {}:{}.", host, port); 55 | } catch (IOException e) { 56 | LOGGER.error("Error trying to get a response from ZAP.", e); 57 | } 58 | return responseCode; 59 | } 60 | 61 | static void waitForZapInitialization(int port, long timeoutInMillis) { 62 | waitForZapInitialization("localhost", port, timeoutInMillis); 63 | } 64 | 65 | static void waitForZapInitialization(String host, int port, long timeoutInMillis) { 66 | long startUpTime = System.currentTimeMillis(); 67 | do { 68 | if (System.currentTimeMillis() - startUpTime > timeoutInMillis) { 69 | String message = "ZAP did not start before the timeout (" + timeoutInMillis + " ms)."; 70 | LOGGER.error(message); 71 | throw new ZapInitializationTimeoutException(message); 72 | } 73 | 74 | sleep(ZAP_INITIALIZATION_POLLING_INTERVAL_IN_MILLIS); 75 | LOGGER.info("Checking if ZAP has started at {}:{}...", host, port); 76 | } while (!isZapRunning(host, port)); 77 | 78 | LOGGER.info("ZAP has started!"); 79 | } 80 | 81 | private static void sleep(long millis) { 82 | try { 83 | Thread.sleep(millis); 84 | } catch(InterruptedException e) { 85 | Thread.currentThread().interrupt(); 86 | LOGGER.error(e.getMessage(), e); 87 | } 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/AjaxSpider.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class AjaxSpider { 35 | 36 | private ClientApi api = null; 37 | 38 | public AjaxSpider(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | /** 43 | * This component is optional and therefore the API will only work if it is installed 44 | */ 45 | public ApiResponse status() throws ClientApiException { 46 | Map map = null; 47 | return api.callApi("ajaxSpider", "view", "status", map); 48 | } 49 | 50 | /** 51 | * This component is optional and therefore the API will only work if it is installed 52 | */ 53 | public ApiResponse results(String start, String count) throws ClientApiException { 54 | Map map = null; 55 | map = new HashMap(); 56 | map.put("start", start); 57 | map.put("count", count); 58 | return api.callApi("ajaxSpider", "view", "results", map); 59 | } 60 | 61 | /** 62 | * This component is optional and therefore the API will only work if it is installed 63 | */ 64 | public ApiResponse numberOfResults() throws ClientApiException { 65 | Map map = null; 66 | return api.callApi("ajaxSpider", "view", "numberOfResults", map); 67 | } 68 | 69 | /** 70 | * This component is optional and therefore the API will only work if it is installed 71 | */ 72 | public ApiResponse scan(String apikey, String url, String inscope) throws ClientApiException { 73 | Map map = null; 74 | map = new HashMap(); 75 | if (apikey != null) { 76 | map.put("apikey", apikey); 77 | } 78 | map.put("url", url); 79 | map.put("inScope", inscope); 80 | return api.callApi("ajaxSpider", "action", "scan", map); 81 | } 82 | 83 | /** 84 | * This component is optional and therefore the API will only work if it is installed 85 | */ 86 | public ApiResponse stop(String apikey) throws ClientApiException { 87 | Map map = null; 88 | map = new HashMap(); 89 | if (apikey != null) { 90 | map.put("apikey", apikey); 91 | } 92 | return api.callApi("ajaxSpider", "action", "stop", map); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/authentication/CasAuthenticationHandler.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.authentication; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.net.URLEncoder; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import br.com.softplan.security.zap.api.ZapHelper; 10 | import br.com.softplan.security.zap.api.exception.ZapClientException; 11 | import br.com.softplan.security.zap.api.model.AuthenticationInfo; 12 | import br.com.softplan.security.zap.commons.ZapInfo; 13 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 14 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 15 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 16 | 17 | /** 18 | * Class to handle CAS authentication via ZAP. 19 | * 20 | * @author pdsec 21 | */ 22 | public class CasAuthenticationHandler extends AbstractAuthenticationHandler { 23 | 24 | private static final Logger LOGGER = LoggerFactory.getLogger(CasAuthenticationHandler.class); 25 | 26 | public static final String SCRIPT_NAME = "cas-auth"; 27 | private static final String SCRIPT_DESCRIPTION = "CAS authentication script"; 28 | 29 | private static final String SCRIPT_AUTHENTICATION_TYPE = "scriptBasedAuthentication"; 30 | 31 | private static final String SCRIPT_NAME_PARAM = "scriptName"; 32 | private static final String LOGIN_PAGE_PARAM = "loginUrl"; 33 | private static final String PROTECTED_PAGES_PARAM = "protectedPages"; 34 | private static final String EXTRA_POST_DATA_PARAM = "extraPostData"; 35 | 36 | private AuthenticationScriptLoader scriptLoader; 37 | 38 | protected CasAuthenticationHandler(ClientApi api, ZapInfo zapInfo, AuthenticationInfo authenticationInfo) { 39 | super(api, zapInfo, authenticationInfo); 40 | 41 | this.scriptLoader = new AuthenticationScriptLoader(api, zapInfo, SCRIPT_NAME, SCRIPT_DESCRIPTION); 42 | } 43 | 44 | @Override 45 | protected void setupAuthentication(String targetUrl) { 46 | scriptLoader.loadScript(); 47 | 48 | setScriptAuthenticationMethod(); 49 | createAndEnableUser(); 50 | setupUserCredentials(); 51 | enableForcedUserMode(); 52 | } 53 | 54 | private void setScriptAuthenticationMethod() { 55 | try { 56 | String encodedScriptName = URLEncoder.encode(SCRIPT_NAME, UTF_8); 57 | String encodedLoginUrl = URLEncoder.encode(getAuthenticationInfo().getLoginUrl(), UTF_8); 58 | String encodedProtectedPages = URLEncoder.encode(getAuthenticationInfo().getProtectedPagesSeparatedByComma(), UTF_8); 59 | String authParams = SCRIPT_NAME_PARAM + "=" + encodedScriptName + 60 | "&" + LOGIN_PAGE_PARAM + "=" + encodedLoginUrl + 61 | "&" + PROTECTED_PAGES_PARAM + "=" + encodedProtectedPages; 62 | 63 | String extraPostData = getAuthenticationInfo().getExtraPostData(); 64 | if (extraPostData != null) { 65 | String encodedExtraPostData = URLEncoder.encode(extraPostData, UTF_8); 66 | authParams += "&" + EXTRA_POST_DATA_PARAM + "=" + encodedExtraPostData; 67 | } 68 | 69 | LOGGER.debug("Setting script authentication method with params: {}", authParams); 70 | ApiResponse response = getApi().authentication.setAuthenticationMethod( 71 | getApiKey(), ZAP_DEFAULT_CONTEXT_ID, SCRIPT_AUTHENTICATION_TYPE, authParams); 72 | ZapHelper.validateResponse(response, "Set script authentication method"); 73 | } catch (ClientApiException | UnsupportedEncodingException e) { 74 | LOGGER.error("Error setting up script authentication method.", e); 75 | throw new ZapClientException(e); 76 | } 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/core/ApiResponseList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Zed Attack Proxy (ZAP) and its related class files. 3 | * 4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package br.com.softplan.security.zap.zaproxy.clientapi.core; 19 | 20 | import java.lang.reflect.Constructor; 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | 24 | import org.w3c.dom.Node; 25 | 26 | public class ApiResponseList extends ApiResponse { 27 | 28 | private List list = null; 29 | 30 | public ApiResponseList(String name) { 31 | super(name); 32 | this.list = new ArrayList(); 33 | } 34 | 35 | public ApiResponseList(Node node) 36 | throws ClientApiException { 37 | this(node.getNodeName()); 38 | Node child = node.getFirstChild(); 39 | while (child != null) { 40 | this.addItem(ApiResponseFactory.getResponse(child)); 41 | child = child.getNextSibling(); 42 | } 43 | } 44 | 45 | public ApiResponseList(Node node, ApiResponseList template) 46 | throws ClientApiException { 47 | super(node.getNodeName()); 48 | try { 49 | this.list = new ArrayList(); 50 | Class clazz = template.getItemsClass(); 51 | if (clazz != null) { 52 | 53 | Node child = node.getFirstChild(); 54 | while (child != null) { 55 | Constructor cons = clazz.getConstructor(Node.class, ApiResponse.class); 56 | this.addItem(cons.newInstance(child, template.list.get(0))); 57 | child = child.getNextSibling(); 58 | } 59 | } 60 | } catch (Exception e) { 61 | throw new ClientApiException(e); 62 | } 63 | } 64 | 65 | public ApiResponseList(String name, ApiResponse[] array) { 66 | super(name); 67 | this.list = new ArrayList(); 68 | for (ApiResponse resp: array) { 69 | list.add(resp); 70 | } 71 | } 72 | 73 | public ApiResponseList(String name, List list) { 74 | super(name); 75 | this.list = list; 76 | } 77 | 78 | public void addItem(ApiResponse item) { 79 | this.list.add(item); 80 | } 81 | 82 | public List getItems() { 83 | return this.list; 84 | } 85 | 86 | public Class getItemsClass() { 87 | if (this.list == null || this.list.size() == 0) { 88 | return null; 89 | } 90 | return this.list.get(0).getClass(); 91 | } 92 | 93 | @Override 94 | public String toString(int indent) { 95 | StringBuilder sb = new StringBuilder(); 96 | for (int i=0 ; i < indent; i++) { 97 | sb.append("\t"); 98 | } 99 | sb.append("ApiResponseList "); 100 | sb.append(this.getName()); 101 | sb.append(" : [\n"); 102 | for (ApiResponse resp: this.list) { 103 | sb.append(resp.toString(indent+1)); 104 | } 105 | for (int i=0 ; i < indent; i++) { 106 | sb.append("\t"); 107 | } 108 | sb.append("]\n"); 109 | return sb.toString(); 110 | } 111 | 112 | 113 | } 114 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/authentication/AuthenticationScriptLoader.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.authentication; 2 | 3 | import java.io.IOException; 4 | import java.net.URISyntaxException; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import br.com.softplan.security.zap.api.ZapHelper; 10 | import br.com.softplan.security.zap.api.exception.ZapClientException; 11 | import br.com.softplan.security.zap.commons.ZapInfo; 12 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 13 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponseElement; 14 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponseList; 15 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponseSet; 16 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 17 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 18 | 19 | public class AuthenticationScriptLoader { 20 | 21 | private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticationScriptLoader.class); 22 | 23 | private static final String JAVASCRIPT_ENGINE_IDENTIFIER = "ECMAScript"; 24 | private static final String ZAP_SCRIPT_TYPE = "authentication"; 25 | 26 | private ClientApi api; 27 | private String apiKey; 28 | private final boolean isZapRunningOnDocker; 29 | 30 | private AuthenticationScript script; 31 | 32 | public AuthenticationScriptLoader(ClientApi api, ZapInfo zapInfo, String scriptName, String scriptDescription) { 33 | this.api = api; 34 | this.apiKey = zapInfo.getApiKey(); 35 | this.isZapRunningOnDocker = zapInfo.shouldRunWithDocker(); 36 | this.script = new AuthenticationScript(scriptName, scriptDescription); 37 | } 38 | 39 | public void loadScript() { 40 | try { 41 | clearPreviouslyLoadedCasAuthScript(); 42 | 43 | String scriptEngine = pickAvailableJavaScriptEngine(); 44 | String scriptPath = script.getPath(isZapRunningOnDocker); 45 | 46 | LOGGER.debug("Loading authentication script from file: {}.", scriptPath); 47 | ApiResponse response = api.script.load( 48 | apiKey, script.getName(), ZAP_SCRIPT_TYPE, scriptEngine, scriptPath, script.getDescription()); 49 | ZapHelper.validateResponse(response, "Load authentication script"); 50 | 51 | } catch (ClientApiException | IOException | URISyntaxException e) { 52 | LOGGER.error("Error loading authentication script.", e); 53 | throw new ZapClientException(e); 54 | } 55 | } 56 | 57 | private void clearPreviouslyLoadedCasAuthScript() { 58 | try { 59 | ApiResponseList listScriptsResponse = (ApiResponseList) api.script.listScripts(); 60 | for (ApiResponse currentScript : listScriptsResponse.getItems()) { 61 | if (((ApiResponseSet) currentScript).getAttribute("name").equals(script.getName())) { 62 | ApiResponse response = api.script.remove(apiKey, script.getName()); 63 | ZapHelper.validateResponse(response, "Clear previously loaded authentication script"); 64 | } 65 | } 66 | } catch (ClientApiException e) { 67 | LOGGER.error("Error clearing previously loaded authentication script.", e); 68 | throw new ZapClientException(e); 69 | } 70 | } 71 | 72 | private String pickAvailableJavaScriptEngine() throws ClientApiException { 73 | ApiResponseList response = (ApiResponseList) api.script.listEngines(); 74 | for (ApiResponse engine : response.getItems()) { 75 | String engineName = ((ApiResponseElement) engine).getValue(); 76 | if (isJavaScriptEngine(engineName)) { 77 | return engineName; 78 | } 79 | } 80 | throw new ZapClientException("Could not find a JavaScript engine within ZAP."); 81 | } 82 | 83 | private boolean isJavaScriptEngine(String engineName) { 84 | return engineName.contains(JAVASCRIPT_ENGINE_IDENTIFIER); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/Selenium.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class Selenium { 35 | 36 | private ClientApi api = null; 37 | 38 | public Selenium(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | /** 43 | * This component is optional and therefore the API will only work if it is installed 44 | */ 45 | public ApiResponse optionChromeDriverPath() throws ClientApiException { 46 | Map map = null; 47 | return api.callApi("selenium", "view", "optionChromeDriverPath", map); 48 | } 49 | 50 | /** 51 | * This component is optional and therefore the API will only work if it is installed 52 | */ 53 | public ApiResponse optionIeDriverPath() throws ClientApiException { 54 | Map map = null; 55 | return api.callApi("selenium", "view", "optionIeDriverPath", map); 56 | } 57 | 58 | /** 59 | * This component is optional and therefore the API will only work if it is installed 60 | */ 61 | public ApiResponse optionPhantomJsBinaryPath() throws ClientApiException { 62 | Map map = null; 63 | return api.callApi("selenium", "view", "optionPhantomJsBinaryPath", map); 64 | } 65 | 66 | /** 67 | * This component is optional and therefore the API will only work if it is installed 68 | */ 69 | public ApiResponse setOptionChromeDriverPath(String apikey, String string) throws ClientApiException { 70 | Map map = null; 71 | map = new HashMap(); 72 | if (apikey != null) { 73 | map.put("apikey", apikey); 74 | } 75 | map.put("String", string); 76 | return api.callApi("selenium", "action", "setOptionChromeDriverPath", map); 77 | } 78 | 79 | /** 80 | * This component is optional and therefore the API will only work if it is installed 81 | */ 82 | public ApiResponse setOptionIeDriverPath(String apikey, String string) throws ClientApiException { 83 | Map map = null; 84 | map = new HashMap(); 85 | if (apikey != null) { 86 | map.put("apikey", apikey); 87 | } 88 | map.put("String", string); 89 | return api.callApi("selenium", "action", "setOptionIeDriverPath", map); 90 | } 91 | 92 | /** 93 | * This component is optional and therefore the API will only work if it is installed 94 | */ 95 | public ApiResponse setOptionPhantomJsBinaryPath(String apikey, String string) throws ClientApiException { 96 | Map map = null; 97 | map = new HashMap(); 98 | if (apikey != null) { 99 | map.put("apikey", apikey); 100 | } 101 | map.put("String", string); 102 | return api.callApi("selenium", "action", "setOptionPhantomJsBinaryPath", map); 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/ImportLogFiles.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class ImportLogFiles { 35 | 36 | private ClientApi api = null; 37 | 38 | public ImportLogFiles(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | /** 43 | * This component is optional and therefore the API will only work if it is installed 44 | */ 45 | public ApiResponse ImportZAPLogFromFile(String filepath) throws ClientApiException { 46 | Map map = null; 47 | map = new HashMap(); 48 | map.put("FilePath", filepath); 49 | return api.callApi("importLogFiles", "view", "ImportZAPLogFromFile", map); 50 | } 51 | 52 | /** 53 | * This component is optional and therefore the API will only work if it is installed 54 | */ 55 | public ApiResponse ImportModSecurityLogFromFile(String filepath) throws ClientApiException { 56 | Map map = null; 57 | map = new HashMap(); 58 | map.put("FilePath", filepath); 59 | return api.callApi("importLogFiles", "view", "ImportModSecurityLogFromFile", map); 60 | } 61 | 62 | /** 63 | * This component is optional and therefore the API will only work if it is installed 64 | */ 65 | public ApiResponse ImportZAPHttpRequestResponsePair(String httprequest, String httpresponse) throws ClientApiException { 66 | Map map = null; 67 | map = new HashMap(); 68 | map.put("HTTPRequest", httprequest); 69 | map.put("HTTPResponse", httpresponse); 70 | return api.callApi("importLogFiles", "view", "ImportZAPHttpRequestResponsePair", map); 71 | } 72 | 73 | /** 74 | * This component is optional and therefore the API will only work if it is installed 75 | */ 76 | public ApiResponse PostModSecurityAuditEvent(String apikey, String auditeventstring) throws ClientApiException { 77 | Map map = null; 78 | map = new HashMap(); 79 | if (apikey != null) { 80 | map.put("apikey", apikey); 81 | } 82 | map.put("AuditEventString", auditeventstring); 83 | return api.callApi("importLogFiles", "action", "PostModSecurityAuditEvent", map); 84 | } 85 | 86 | /** 87 | * This component is optional and therefore the API will only work if it is installed 88 | */ 89 | public byte[] OtherPostModSecurityAuditEvent(String apikey, String auditeventstring) throws ClientApiException { 90 | Map map = null; 91 | map = new HashMap(); 92 | if (apikey != null) { 93 | map.put("apikey", apikey); 94 | } 95 | map.put("AuditEventString", auditeventstring); 96 | return api.callApiOther("importLogFiles", "other", "OtherPostModSecurityAuditEvent", map); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /zap-client-api/src/test/java/br/com/softplan/security/zap/api/util/ZapProperties.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.util; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | 6 | import org.apache.commons.configuration.Configuration; 7 | import org.apache.commons.configuration.ConfigurationException; 8 | import org.apache.commons.configuration.PropertiesConfiguration; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | /** 13 | * Class responsible for loading the properties from the zap.properties file, 14 | * with the properties needed to start ZAP for the integration tests. 15 | * 16 | * @author pdsec 17 | */ 18 | public class ZapProperties { 19 | 20 | private static final Logger LOGGER = LoggerFactory.getLogger(ZapProperties.class); 21 | 22 | private static final String ZAP_PROPERTIES_FILE_PATH = "/zap.properties"; 23 | private static final String LOCAL_ZAP_PROPERTIES_FILE_PATH = "/local-zap.properties"; 24 | 25 | private static final String ZAP_HOST_PROPERTY = "zap.host"; 26 | private static final String ZAP_PORT_PROPERTY = "zap.port"; 27 | private static final String ZAP_PATH_PROPERTY = "zap.path"; 28 | private static final String ZAP_OPTIONS_PROPERTY = "zap.options"; 29 | private static final String ZAP_INITIALIZATION_TIMEOUT_PROPERTY = "zap.initializationTimeout"; 30 | 31 | private static PropertiesConfiguration properties; 32 | 33 | private static String host; 34 | 35 | private static Integer port; 36 | 37 | private static String path; 38 | 39 | private static Long initializationTimeout; 40 | 41 | private static String options; 42 | 43 | private static Configuration getProperties() { 44 | if (properties == null) { 45 | loadProperties(); 46 | } 47 | return properties; 48 | } 49 | 50 | private static void loadProperties() { 51 | LOGGER.info("Loading ZAP properties files."); 52 | properties = new PropertiesConfiguration(); 53 | 54 | try ( 55 | InputStream localZapPropertiesStream = ZapProperties.class.getResourceAsStream(LOCAL_ZAP_PROPERTIES_FILE_PATH); 56 | InputStream zapPropertiesStream = ZapProperties.class.getResourceAsStream(ZAP_PROPERTIES_FILE_PATH); 57 | ) { 58 | if (localZapPropertiesStream != null) { 59 | LOGGER.info("Loading 'local-zap.properties' file."); 60 | properties.load(localZapPropertiesStream); 61 | } 62 | 63 | LOGGER.info("Loading 'zap.properties' file."); 64 | properties.load(zapPropertiesStream); 65 | } catch (IOException | ConfigurationException e) { 66 | LOGGER.error("Error loading ZAP properties files.", e); 67 | } 68 | } 69 | 70 | public static String getHost() { 71 | if (host == null) { 72 | host = getProperties().getString(ZAP_HOST_PROPERTY); 73 | LOGGER.info("Loaded '{}' value: {}", ZAP_HOST_PROPERTY, host); 74 | } 75 | return host; 76 | } 77 | 78 | public static int getPort() { 79 | if (port == null) { 80 | port = getProperties().getInt(ZAP_PORT_PROPERTY); 81 | LOGGER.info("Loaded '{}' value: {}", ZAP_PORT_PROPERTY, port); 82 | } 83 | return port; 84 | } 85 | 86 | public static String getPath() { 87 | if (path == null) { 88 | path = getProperties().getString(ZAP_PATH_PROPERTY); 89 | LOGGER.info("Loaded '{}' value: {}", ZAP_PATH_PROPERTY, path); 90 | } 91 | return path; 92 | } 93 | 94 | public static Long getInitializationTimeout() { 95 | if (initializationTimeout == null) { 96 | initializationTimeout = getProperties().getLong(ZAP_INITIALIZATION_TIMEOUT_PROPERTY); 97 | LOGGER.info("Loaded '{}' value: {}", ZAP_INITIALIZATION_TIMEOUT_PROPERTY, initializationTimeout); 98 | } 99 | return initializationTimeout; 100 | } 101 | 102 | public static String getOptions() { 103 | if (options == null) { 104 | options = getProperties().getString(ZAP_OPTIONS_PROPERTY); 105 | LOGGER.info("Loaded '{}' value: {}", ZAP_OPTIONS_PROPERTY, options); 106 | } 107 | return options; 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /zap-maven-plugin-core/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | br.com.softplan.security.zap 7 | zap-maven-plugin-parent 8 | 1.2.2-0-SNAPSHOT 9 | ../zap-maven-plugin-parent 10 | 11 | 12 | zap-maven-plugin 13 | maven-plugin 14 | 15 | ZAP Maven Plugin 16 | OWASP Zed Attack Proxy (ZAP) Maven plugin 17 | https://github.com/pdsoftplan/zap-maven-plugin 18 | 2015 19 | 20 | Softplan 21 | https://www.softplan.com.br 22 | 23 | 24 | 25 | 26 | Apache License, Version 2.0 27 | http://www.apache.org/licenses/LICENSE-2.0.txt 28 | repo 29 | 30 | 31 | 32 | 33 | 34 | tfcporciuncula 35 | Thiago Porciúncula 36 | thiago.porciuncula@softplan.com.br 37 | Softplan 38 | 39 | 40 | fabio.resner 41 | Fábio Resner 42 | fabio.resner@softplan.com.br 43 | Softplan 44 | 45 | 46 | 47 | 48 | scm:git:git@github.com:pdsoftplan/zap-maven-plugin.git 49 | scm:git:git@github.com:pdsoftplan/zap-maven-plugin.git 50 | https://github.com/pdsoftplan/zap-maven-plugin 51 | 52 | 53 | 54 | GitHub 55 | https://github.com/pdsoftplan/zap-maven-plugin/issues 56 | 57 | 58 | Travis 59 | https://travis-ci.org/pdsoftplan/zap-maven-plugin 60 | 61 | 62 | 63 | 64 | br.com.softplan.security.zap 65 | zap-client-api 66 | 67 | 68 | org.apache.maven 69 | maven-plugin-api 70 | 71 | 72 | org.apache.maven.plugin-tools 73 | maven-plugin-annotations 74 | provided 75 | 76 | 77 | 78 | 79 | 80 | 81 | org.apache.maven.plugins 82 | maven-plugin-plugin 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | org.eclipse.m2e 91 | lifecycle-mapping 92 | 1.0.0 93 | 94 | 95 | 96 | 97 | 98 | org.apache.maven.plugins 99 | maven-plugin-plugin 100 | [${maven.plugin.plugin.version},) 101 | descriptor 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/ZapHelper.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api; 2 | 3 | import java.util.Arrays; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import br.com.softplan.security.zap.api.exception.ZapClientException; 9 | import br.com.softplan.security.zap.api.model.AnalysisInfo; 10 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 11 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponseElement; 12 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 13 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 14 | 15 | /** 16 | * Helper to be used by classes that make calls to the ZAP API. 17 | * 18 | * @author pdsec 19 | */ 20 | public class ZapHelper { 21 | 22 | private static final Logger LOGGER = LoggerFactory.getLogger(ZapHelper.class); 23 | 24 | private static final String ZAP_SUCCESS_RESPONSE = "OK"; 25 | private static final String ZAP_DEFAULT_CONTEXT_NAME = "Default Context"; 26 | 27 | public static String extractResponse(ApiResponse response) { 28 | return ((ApiResponseElement) response).getValue(); 29 | } 30 | 31 | public static void validateResponse(ApiResponse response, String operationDescription) { 32 | String responseValue = extractResponse(response); 33 | if (!responseValue.equals(ZAP_SUCCESS_RESPONSE)) { 34 | String message = "ZAP API did not respond '" + ZAP_SUCCESS_RESPONSE + "' during the following operation: " 35 | + operationDescription + ". Actual response: " + responseValue; 36 | LOGGER.error(message); 37 | throw new ZapClientException(message); 38 | } 39 | } 40 | 41 | public static void includeInContext(ClientApi api, String apiKey, AnalysisInfo analysisInfo) { 42 | String[] context = analysisInfo.getContext(); 43 | LOGGER.debug("Including target '{}' in context.", Arrays.toString(context)); 44 | 45 | try { 46 | for (String contextUrl : context) { 47 | if (isContextUrlRelative(contextUrl)) { 48 | contextUrl = resolveContextUrl(contextUrl, analysisInfo); 49 | } 50 | ApiResponse response = api.context.includeInContext(apiKey, ZAP_DEFAULT_CONTEXT_NAME, "\\Q" + contextUrl + "\\E.*"); 51 | validateResponse(response, "Include target in context."); 52 | } 53 | } catch (ClientApiException e) { 54 | LOGGER.error("Error including target in context.", e); 55 | throw new ZapClientException(e); 56 | } 57 | } 58 | 59 | private static boolean isContextUrlRelative(String contextUrl) { 60 | return !contextUrl.startsWith("http"); 61 | } 62 | 63 | private static String resolveContextUrl(String contextUrl, AnalysisInfo analysisInfo) { 64 | String activeScanStartingPointUrl = analysisInfo.getActiveScanStartingPointUrl(); 65 | if (activeScanStartingPointUrl.endsWith("/")) { 66 | activeScanStartingPointUrl = activeScanStartingPointUrl.substring(0, activeScanStartingPointUrl.length()-1); 67 | } 68 | if (contextUrl.startsWith("/")) { 69 | contextUrl = contextUrl.substring(1); 70 | } 71 | return activeScanStartingPointUrl + "/" + contextUrl; 72 | } 73 | 74 | public static void setTechnologiesInContext(ClientApi api, String apiKey, AnalysisInfo analysisInfo) { 75 | String technologies = analysisInfo.getTechnologiesSeparatedByComma(); 76 | if (technologies == null) { 77 | return; 78 | } 79 | LOGGER.debug("Setting technologies in context: {}.", technologies); 80 | 81 | try { 82 | ApiResponse responseFromExcludingTechnologies = api.context.excludeAllContextTechnologies(apiKey, ZAP_DEFAULT_CONTEXT_NAME); 83 | validateResponse(responseFromExcludingTechnologies, "Exclude all context technologies."); 84 | 85 | ApiResponse responseFromIncludingTechnologies = api.context.includeContextTechnologies(apiKey, ZAP_DEFAULT_CONTEXT_NAME, technologies); 86 | validateResponse(responseFromIncludingTechnologies, "Exclude all context technologies."); 87 | } catch (ClientApiException e) { 88 | LOGGER.error("Error setting technologies in context.", e); 89 | throw new ZapClientException(e); 90 | } 91 | } 92 | 93 | private ZapHelper() {} 94 | 95 | } 96 | -------------------------------------------------------------------------------- /zap-client-api/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | br.com.softplan.security.zap 7 | zap-maven-plugin-parent 8 | 1.2.2-0-SNAPSHOT 9 | ../zap-maven-plugin-parent 10 | 11 | 12 | zap-client-api 13 | 14 | ZAP Client API 15 | Java client API for the OWASP Zed Attack Proxy (ZAP), built on top of the official ZAP Java API 16 | https://github.com/pdsoftplan/zap-maven-plugin 17 | 2015 18 | 19 | Softplan 20 | https://www.softplan.com.br 21 | 22 | 23 | 24 | 25 | Apache License, Version 2.0 26 | http://www.apache.org/licenses/LICENSE-2.0.txt 27 | repo 28 | 29 | 30 | 31 | 32 | 33 | tfcporciuncula 34 | Thiago Porciúncula 35 | thiago.porciuncula@softplan.com.br 36 | Softplan 37 | 38 | 39 | fabio.resner 40 | Fábio Resner 41 | fabio.resner@softplan.com.br 42 | Softplan 43 | 44 | 45 | 46 | 47 | scm:git:git@github.com:pdsoftplan/zap-maven-plugin.git 48 | scm:git:git@github.com:pdsoftplan/zap-maven-plugin.git 49 | https://github.com/pdsoftplan/zap-maven-plugin 50 | 51 | 52 | 53 | GitHub 54 | https://github.com/pdsoftplan/zap-maven-plugin/issues 55 | 56 | 57 | Travis 58 | https://travis-ci.org/pdsoftplan/zap-maven-plugin 59 | 60 | 61 | 62 | true 63 | 64 | 65 | 66 | 67 | 68 | runIT 69 | 70 | false 71 | 72 | 73 | 74 | 75 | 76 | disable-java8-doclint 77 | 78 | [1.8,) 79 | 80 | 81 | -Xdoclint:none 82 | 83 | 84 | 85 | 86 | 87 | 88 | org.jopendocument 89 | jdom 90 | 91 | 92 | org.seleniumhq.selenium 93 | selenium-java 94 | 95 | 96 | com.github.detro 97 | phantomjsdriver 98 | 99 | 100 | br.com.softplan.security.zap 101 | zap-utils 102 | 103 | 104 | org.slf4j 105 | slf4j-api 106 | 107 | 108 | org.testng 109 | testng 110 | test 111 | 112 | 113 | ch.qos.logback 114 | logback-classic 115 | test 116 | 117 | 118 | commons-configuration 119 | commons-configuration 120 | test 121 | 122 | 123 | 124 | 125 | 126 | 127 | org.apache.maven.plugins 128 | maven-failsafe-plugin 129 | 130 | ${integrationTests.skipTests} 131 | 132 | 133 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /zap-client-api/src/test/java/br/com/softplan/security/zap/api/report/ZapReportUtilTest.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.report; 2 | 3 | import static org.testng.Assert.*; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.nio.charset.StandardCharsets; 8 | import java.nio.file.Files; 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | 12 | import org.testng.annotations.BeforeMethod; 13 | import org.testng.annotations.Test; 14 | 15 | public class ZapReportUtilTest { 16 | 17 | private static final String TEST_DIR = System.getProperty("user.dir") + File.separator + "test"; 18 | private ZapReport zapReport; 19 | 20 | private byte[] fakeReportBytes = {1, 2, 3, 4}; 21 | private String[] fakeSpiderResults = {"url1", "url2"}; 22 | 23 | @BeforeMethod 24 | public void setUp() { 25 | zapReport = new ZapReport(fakeReportBytes, fakeReportBytes, new ArrayList(Arrays.asList(fakeSpiderResults))); 26 | } 27 | 28 | @Test 29 | public void saveHtmlReportTest() throws IOException { 30 | File report = ZapReportUtil.saveHtmlReport(zapReport, TEST_DIR); 31 | 32 | assertTrue(report.isFile()); 33 | assertEquals(report.getName(), "zapReport.html"); 34 | assertEquals(Files.readAllBytes(report.toPath()), fakeReportBytes); 35 | 36 | report.delete(); 37 | } 38 | 39 | @Test 40 | public void saveHtmlReportInDefaultLocationTest() throws IOException { 41 | File report = ZapReportUtil.saveHtmlReport(zapReport); 42 | 43 | assertTrue(report.isFile()); 44 | assertEquals(report.getName(), "zapReport.html"); 45 | assertEquals(Files.readAllBytes(report.toPath()), fakeReportBytes); 46 | 47 | report.delete(); 48 | } 49 | 50 | @Test 51 | public void saveXmlReportTest() throws IOException { 52 | File report = ZapReportUtil.saveXmlReport(zapReport, TEST_DIR); 53 | 54 | assertTrue(report.isFile()); 55 | assertEquals(report.getName(), "zapReport.xml"); 56 | assertEquals(Files.readAllBytes(report.toPath()), fakeReportBytes); 57 | 58 | report.delete(); 59 | } 60 | 61 | @Test 62 | public void saveXmlReportInDefaultLocationTest() throws IOException { 63 | File report = ZapReportUtil.saveXmlReport(zapReport); 64 | 65 | assertTrue(report.isFile()); 66 | assertEquals(report.getName(), "zapReport.xml"); 67 | assertEquals(Files.readAllBytes(report.toPath()), fakeReportBytes); 68 | 69 | report.delete(); 70 | } 71 | 72 | @Test 73 | public void saveHtmlSpiderResultsTest() throws IOException { 74 | File report = ZapReportUtil.saveHtmlSpiderResults(zapReport, TEST_DIR); 75 | 76 | assertTrue(report.isFile()); 77 | assertEquals(report.getName(), "zapSpiderResults.html"); 78 | String content = new String(Files.readAllBytes(report.toPath()), StandardCharsets.UTF_8); 79 | assertTrue(content.contains("")); 80 | assertTrue(content.contains("url1")); 81 | assertTrue(content.contains("url2")); 82 | 83 | report.delete(); 84 | } 85 | 86 | @Test 87 | public void saveHtmlSpiderResultsInDefaultLocationTest() throws IOException { 88 | File report = ZapReportUtil.saveHtmlSpiderResults(zapReport); 89 | 90 | assertTrue(report.isFile()); 91 | assertEquals(report.getName(), "zapSpiderResults.html"); 92 | String content = new String(Files.readAllBytes(report.toPath()), StandardCharsets.UTF_8); 93 | assertTrue(content.contains("")); 94 | assertTrue(content.contains("url1")); 95 | assertTrue(content.contains("url2")); 96 | 97 | report.delete(); 98 | } 99 | 100 | @Test 101 | public void saveXmlSpiderResultsTest() throws IOException { 102 | File report = ZapReportUtil.saveXmlSpiderResults(zapReport, TEST_DIR); 103 | 104 | assertTrue(report.isFile()); 105 | assertEquals(report.getName(), "zapSpiderResults.xml"); 106 | String content = new String(Files.readAllBytes(report.toPath()), StandardCharsets.UTF_8); 107 | assertTrue(content.contains("url1")); 108 | assertTrue(content.contains("url2")); 109 | 110 | report.delete(); 111 | } 112 | 113 | @Test 114 | public void saveXmlSpiderResultsInDefaultLocationTest() throws IOException { 115 | File report = ZapReportUtil.saveXmlSpiderResults(zapReport); 116 | 117 | assertTrue(report.isFile()); 118 | assertEquals(report.getName(), "zapSpiderResults.xml"); 119 | String content = new String(Files.readAllBytes(report.toPath()), StandardCharsets.UTF_8); 120 | assertTrue(content.contains("url1")); 121 | assertTrue(content.contains("url2")); 122 | report.delete(); 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/Script.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class Script { 35 | 36 | private ClientApi api = null; 37 | 38 | public Script(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | /** 43 | * Lists the script engines available 44 | */ 45 | public ApiResponse listEngines() throws ClientApiException { 46 | Map map = null; 47 | return api.callApi("script", "view", "listEngines", map); 48 | } 49 | 50 | /** 51 | * Lists the scripts available, with its engine, name, description, type and error state. 52 | */ 53 | public ApiResponse listScripts() throws ClientApiException { 54 | Map map = null; 55 | return api.callApi("script", "view", "listScripts", map); 56 | } 57 | 58 | /** 59 | * Enables the script with the given name 60 | */ 61 | public ApiResponse enable(String apikey, String scriptname) throws ClientApiException { 62 | Map map = null; 63 | map = new HashMap(); 64 | if (apikey != null) { 65 | map.put("apikey", apikey); 66 | } 67 | map.put("scriptName", scriptname); 68 | return api.callApi("script", "action", "enable", map); 69 | } 70 | 71 | /** 72 | * Disables the script with the given name 73 | */ 74 | public ApiResponse disable(String apikey, String scriptname) throws ClientApiException { 75 | Map map = null; 76 | map = new HashMap(); 77 | if (apikey != null) { 78 | map.put("apikey", apikey); 79 | } 80 | map.put("scriptName", scriptname); 81 | return api.callApi("script", "action", "disable", map); 82 | } 83 | 84 | /** 85 | * Loads a script into ZAP from the given local file, with the given name, type and engine, optionally with a description 86 | */ 87 | public ApiResponse load(String apikey, String scriptname, String scripttype, String scriptengine, String filename, String scriptdescription) throws ClientApiException { 88 | Map map = null; 89 | map = new HashMap(); 90 | if (apikey != null) { 91 | map.put("apikey", apikey); 92 | } 93 | map.put("scriptName", scriptname); 94 | map.put("scriptType", scripttype); 95 | map.put("scriptEngine", scriptengine); 96 | map.put("fileName", filename); 97 | map.put("scriptDescription", scriptdescription); 98 | return api.callApi("script", "action", "load", map); 99 | } 100 | 101 | /** 102 | * Removes the script with the given name 103 | */ 104 | public ApiResponse remove(String apikey, String scriptname) throws ClientApiException { 105 | Map map = null; 106 | map = new HashMap(); 107 | if (apikey != null) { 108 | map.put("apikey", apikey); 109 | } 110 | map.put("scriptName", scriptname); 111 | return api.callApi("script", "action", "remove", map); 112 | } 113 | 114 | /** 115 | * Runs the stand alone script with the give name 116 | */ 117 | public ApiResponse runStandAloneScript(String apikey, String scriptname) throws ClientApiException { 118 | Map map = null; 119 | map = new HashMap(); 120 | if (apikey != null) { 121 | map.put("apikey", apikey); 122 | } 123 | map.put("scriptName", scriptname); 124 | return api.callApi("script", "action", "runStandAloneScript", map); 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/Authentication.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class Authentication { 35 | 36 | private ClientApi api = null; 37 | 38 | public Authentication(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | public ApiResponse getSupportedAuthenticationMethods() throws ClientApiException { 43 | Map map = null; 44 | return api.callApi("authentication", "view", "getSupportedAuthenticationMethods", map); 45 | } 46 | 47 | public ApiResponse getAuthenticationMethodConfigParams(String authmethodname) throws ClientApiException { 48 | Map map = null; 49 | map = new HashMap(); 50 | map.put("authMethodName", authmethodname); 51 | return api.callApi("authentication", "view", "getAuthenticationMethodConfigParams", map); 52 | } 53 | 54 | public ApiResponse getAuthenticationMethod(String contextid) throws ClientApiException { 55 | Map map = null; 56 | map = new HashMap(); 57 | map.put("contextId", contextid); 58 | return api.callApi("authentication", "view", "getAuthenticationMethod", map); 59 | } 60 | 61 | public ApiResponse getLoggedInIndicator(String contextid) throws ClientApiException { 62 | Map map = null; 63 | map = new HashMap(); 64 | map.put("contextId", contextid); 65 | return api.callApi("authentication", "view", "getLoggedInIndicator", map); 66 | } 67 | 68 | public ApiResponse getLoggedOutIndicator(String contextid) throws ClientApiException { 69 | Map map = null; 70 | map = new HashMap(); 71 | map.put("contextId", contextid); 72 | return api.callApi("authentication", "view", "getLoggedOutIndicator", map); 73 | } 74 | 75 | public ApiResponse setAuthenticationMethod(String apikey, String contextid, String authmethodname, String authmethodconfigparams) throws ClientApiException { 76 | Map map = null; 77 | map = new HashMap(); 78 | if (apikey != null) { 79 | map.put("apikey", apikey); 80 | } 81 | map.put("contextId", contextid); 82 | map.put("authMethodName", authmethodname); 83 | map.put("authMethodConfigParams", authmethodconfigparams); 84 | return api.callApi("authentication", "action", "setAuthenticationMethod", map); 85 | } 86 | 87 | public ApiResponse setLoggedInIndicator(String apikey, String contextid, String loggedinindicatorregex) throws ClientApiException { 88 | Map map = null; 89 | map = new HashMap(); 90 | if (apikey != null) { 91 | map.put("apikey", apikey); 92 | } 93 | map.put("contextId", contextid); 94 | map.put("loggedInIndicatorRegex", loggedinindicatorregex); 95 | return api.callApi("authentication", "action", "setLoggedInIndicator", map); 96 | } 97 | 98 | public ApiResponse setLoggedOutIndicator(String apikey, String contextid, String loggedoutindicatorregex) throws ClientApiException { 99 | Map map = null; 100 | map = new HashMap(); 101 | if (apikey != null) { 102 | map.put("apikey", apikey); 103 | } 104 | map.put("contextId", contextid); 105 | map.put("loggedOutIndicatorRegex", loggedoutindicatorregex); 106 | return api.callApi("authentication", "action", "setLoggedOutIndicator", map); 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /zap-utils/src/main/java/br/com/softplan/security/zap/commons/boot/ZapLocalBoot.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.commons.boot; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.nio.file.Files; 6 | import java.nio.file.Path; 7 | import java.nio.file.Paths; 8 | 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import br.com.softplan.security.zap.commons.ZapInfo; 13 | import br.com.softplan.security.zap.commons.exception.ZapInitializationException; 14 | 15 | /** 16 | * Class responsible to start and stop ZAP locally. 17 | *

18 | * ZAP must be installed locally for this to work. 19 | *

20 | * This will normally be used when ZAP's {@code zapInfo.path} was provided and {@code shouldRunWithDocker} is false. 21 | * 22 | * @author pdsec 23 | */ 24 | public class ZapLocalBoot extends AbstractZapBoot { 25 | 26 | private static final Logger LOGGER = LoggerFactory.getLogger(ZapLocalBoot.class); 27 | 28 | private static Process zap; 29 | 30 | @Override 31 | public void startZap(ZapInfo zapInfo) { 32 | int port = zapInfo.getPort(); 33 | 34 | if (isZapRunning(port)) { 35 | LOGGER.info("ZAP is already up and running! No attempts will be made to start ZAP."); 36 | return; 37 | } 38 | 39 | try { 40 | start(zapInfo); 41 | waitForZapInitialization(port, zapInfo.getInitializationTimeoutInMillis()); 42 | } catch (IOException e) { 43 | LOGGER.error("Error starting ZAP.", e); 44 | } 45 | } 46 | 47 | @Override 48 | public void stopZap() { 49 | if (zap != null) { 50 | LOGGER.info("Stopping ZAP."); 51 | zap.destroy(); 52 | } 53 | } 54 | 55 | private static void start(ZapInfo zapInfo) throws IOException { 56 | String startCommand = buildStartCommand(zapInfo); 57 | ProcessBuilder processBuilder = new ProcessBuilder(startCommand.split(" +")); 58 | processBuilder.directory(getZapWorkingDirectory(zapInfo)); 59 | 60 | Files.createDirectories(Paths.get(DEFAULT_ZAP_LOG_PATH)); 61 | processBuilder.redirectOutput(new File(DEFAULT_ZAP_LOG_PATH, DEFAULT_ZAP_LOG_FILE_NAME)); 62 | 63 | LOGGER.info("Starting ZAP with command: {}", startCommand); 64 | zap = processBuilder.start(); 65 | } 66 | 67 | private static String buildStartCommand(ZapInfo zapInfo) { 68 | StringBuilder startCommand = new StringBuilder(); 69 | 70 | startCommand.append("java").append(" "); 71 | startCommand.append(zapInfo.getJmvOptions()).append(" "); 72 | startCommand.append("-jar").append(" "); 73 | 74 | try { 75 | String zapJarName = retrieveZapJarName(zapInfo.getPath()); 76 | startCommand.append(zapJarName).append(" "); 77 | } catch (IOException e) { 78 | LOGGER.error("Error retrieving ZAP's JAR file."); 79 | } 80 | 81 | String options = zapInfo.getOptions(); 82 | startCommand.append(options != null ? options : DEFAULT_ZAP_OPTIONS); 83 | startCommand.append(" -port ").append(zapInfo.getPort()); 84 | 85 | return startCommand.toString(); 86 | } 87 | 88 | private static String retrieveZapJarName(String path) throws IOException { 89 | Path zapPath = Paths.get(path); 90 | if (isJarFile(zapPath)) { 91 | String filename = zapPath.getFileName().toString(); 92 | LOGGER.debug("ZapPath points to the Jar file {}", filename); 93 | return filename; 94 | } 95 | 96 | LOGGER.debug("ZapPath points to the folder {}", zapPath.getFileName().toString()); 97 | 98 | for (Path p : Files.newDirectoryStream(zapPath)) { 99 | if (isJarFile(p)) { 100 | String filename = p.getFileName().toString(); 101 | LOGGER.debug("Chosen Zap Jar file {}", filename); 102 | return filename; 103 | } 104 | } 105 | 106 | throw new ZapInitializationException("ZAP's JAR file was not found."); 107 | } 108 | 109 | private static boolean isJarFile(Path path) { 110 | if (path == null) { 111 | return false; 112 | } 113 | 114 | if (!Files.isRegularFile(path)) { 115 | return false; 116 | } 117 | 118 | Path fileName = path.getFileName(); 119 | 120 | if (fileName == null) { 121 | return false; 122 | } 123 | 124 | if (fileName.toString().endsWith(".jar")) { 125 | return true; 126 | } 127 | 128 | return false; 129 | } 130 | 131 | private static File getZapWorkingDirectory(ZapInfo zapInfo) { 132 | String fullPath = zapInfo.getPath(); 133 | File dir = new File(fullPath); 134 | if (dir.isDirectory()) { 135 | return dir; 136 | } 137 | 138 | if (dir.isFile()) { 139 | return dir.getParentFile(); 140 | } 141 | 142 | return new File(System.getProperty("user.dir")); 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /zap-utils/src/main/java/br/com/softplan/security/zap/commons/boot/ZapDockerBoot.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.commons.boot; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.nio.file.Files; 8 | import java.nio.file.Paths; 9 | 10 | import org.apache.commons.io.IOUtils; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | import br.com.softplan.security.zap.commons.ZapInfo; 15 | import br.com.softplan.security.zap.commons.authentication.AuthenticationScripts; 16 | 17 | /** 18 | * Class responsible to start and stop ZAP by running ZAP's Docker image. 19 | *

20 | * Docker must be installed locally for this to work. 21 | *

22 | * This will be used when {@code zapInfo.shouldRunWithDocker} is {@code true}. 23 | * 24 | * @author pdsec 25 | */ 26 | public class ZapDockerBoot extends AbstractZapBoot { 27 | 28 | private static final Logger LOGGER = LoggerFactory.getLogger(ZapDockerBoot.class); 29 | 30 | private static final String DEFAULT_DOCKER_COMMAND = "docker run --rm"; 31 | private static final String ZAP_IMAGE_OPTION = " -i owasp/zap2docker-stable zap.sh "; 32 | 33 | public static final String CAS_AUTH_SCRIPT_DEFAULT_DOCKER_PATH = "/zap/scripts/"; 34 | private static final String CAS_AUTH_SCRIPT_FILE_NAME = "cas-auth.js"; 35 | 36 | private static Process zap; 37 | 38 | @Override 39 | public void startZap(ZapInfo zapInfo) { 40 | int port = zapInfo.getPort(); 41 | 42 | if (isZapRunning(port)) { 43 | LOGGER.info("ZAP is already up and running! No attempts will be made to start ZAP."); 44 | return; 45 | } 46 | 47 | try { 48 | copyCasAuthScriptFileToMappedFolder(); 49 | startZap(zapInfo.getPath(), buildStartCommand(zapInfo)); 50 | waitForZapInitialization(port, zapInfo.getInitializationTimeoutInMillis()); 51 | } catch (IOException e) { 52 | LOGGER.error("Error starting ZAP.", e); 53 | } 54 | } 55 | 56 | private static void copyCasAuthScriptFileToMappedFolder() { 57 | new File(CAS_AUTH_SCRIPT_DEFAULT_DOCKER_PATH).mkdirs(); 58 | 59 | File scriptFile = new File(CAS_AUTH_SCRIPT_DEFAULT_DOCKER_PATH, CAS_AUTH_SCRIPT_FILE_NAME); 60 | 61 | InputStream casAuthScriptInputStream = ZapDockerBoot.class.getResourceAsStream(AuthenticationScripts.RELATIVE_PATH + CAS_AUTH_SCRIPT_FILE_NAME); 62 | try (FileOutputStream fileOutputStream = new FileOutputStream(scriptFile)) { 63 | IOUtils.copy(casAuthScriptInputStream, fileOutputStream); 64 | } catch (IOException e) { 65 | LOGGER.error("Error while trying to create the script file for CAS authentication in " + CAS_AUTH_SCRIPT_DEFAULT_DOCKER_PATH + ". " 66 | + "The analysis will continue but CAS authentication will work only if the script file can be accessed by ZAP's Docker image " 67 | + "(a default volume is created in " + CAS_AUTH_SCRIPT_DEFAULT_DOCKER_PATH + ").", e); 68 | } 69 | } 70 | 71 | @Override 72 | public void stopZap() { 73 | if (zap != null) { 74 | LOGGER.info("Stopping ZAP."); 75 | zap.destroy(); 76 | } 77 | } 78 | 79 | private static String buildStartCommand(ZapInfo zapInfo) { 80 | StringBuilder startCommand = new StringBuilder(DEFAULT_DOCKER_COMMAND); 81 | appendVolumeOption(startCommand); 82 | appendPortOption(zapInfo, startCommand); 83 | startCommand.append(ZAP_IMAGE_OPTION); 84 | 85 | String options = zapInfo.getOptions(); 86 | startCommand.append(options != null ? options : DEFAULT_ZAP_OPTIONS); 87 | startCommand.append(" -port ").append(zapInfo.getPort()); 88 | 89 | return startCommand.toString(); 90 | } 91 | 92 | private static void appendVolumeOption(StringBuilder startCommand) { 93 | startCommand.append(" -v "); 94 | startCommand.append(CAS_AUTH_SCRIPT_DEFAULT_DOCKER_PATH); 95 | startCommand.append(":"); 96 | startCommand.append(CAS_AUTH_SCRIPT_DEFAULT_DOCKER_PATH); 97 | startCommand.append(":ro"); 98 | } 99 | 100 | private static void appendPortOption(ZapInfo zapInfo, StringBuilder startCommand) { 101 | startCommand.append(" -p "); 102 | startCommand.append(zapInfo.getPort()); 103 | startCommand.append(":"); 104 | startCommand.append(zapInfo.getPort()); 105 | } 106 | 107 | private static void startZap(String path, String startCommand) throws IOException { 108 | ProcessBuilder processBuilder = new ProcessBuilder(startCommand.split(" +")); 109 | // processBuilder.directory(new File(path)); 110 | 111 | Files.createDirectories(Paths.get(DEFAULT_ZAP_LOG_PATH)); 112 | processBuilder.redirectOutput(new File(DEFAULT_ZAP_LOG_PATH, DEFAULT_ZAP_LOG_FILE_NAME)); 113 | 114 | LOGGER.info("Starting ZAP with command: {}", startCommand); 115 | zap = processBuilder.start(); 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/Pscan.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class Pscan { 35 | 36 | private ClientApi api = null; 37 | 38 | public Pscan(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | /** 43 | * The number of records the passive scanner still has to scan 44 | */ 45 | public ApiResponse recordsToScan() throws ClientApiException { 46 | Map map = null; 47 | return api.callApi("pscan", "view", "recordsToScan", map); 48 | } 49 | 50 | /** 51 | * Lists all passive scanners with its ID, name, enabled state and alert threshold. 52 | */ 53 | public ApiResponse scanners() throws ClientApiException { 54 | Map map = null; 55 | return api.callApi("pscan", "view", "scanners", map); 56 | } 57 | 58 | /** 59 | * Sets whether or not the passive scanning is enabled 60 | */ 61 | public ApiResponse setEnabled(String apikey, String enabled) throws ClientApiException { 62 | Map map = null; 63 | map = new HashMap(); 64 | if (apikey != null) { 65 | map.put("apikey", apikey); 66 | } 67 | map.put("enabled", enabled); 68 | return api.callApi("pscan", "action", "setEnabled", map); 69 | } 70 | 71 | /** 72 | * Enables all passive scanners 73 | */ 74 | public ApiResponse enableAllScanners(String apikey) throws ClientApiException { 75 | Map map = null; 76 | map = new HashMap(); 77 | if (apikey != null) { 78 | map.put("apikey", apikey); 79 | } 80 | return api.callApi("pscan", "action", "enableAllScanners", map); 81 | } 82 | 83 | /** 84 | * Disables all passive scanners 85 | */ 86 | public ApiResponse disableAllScanners(String apikey) throws ClientApiException { 87 | Map map = null; 88 | map = new HashMap(); 89 | if (apikey != null) { 90 | map.put("apikey", apikey); 91 | } 92 | return api.callApi("pscan", "action", "disableAllScanners", map); 93 | } 94 | 95 | /** 96 | * Enables all passive scanners with the given IDs (comma separated list of IDs) 97 | */ 98 | public ApiResponse enableScanners(String apikey, String ids) throws ClientApiException { 99 | Map map = null; 100 | map = new HashMap(); 101 | if (apikey != null) { 102 | map.put("apikey", apikey); 103 | } 104 | map.put("ids", ids); 105 | return api.callApi("pscan", "action", "enableScanners", map); 106 | } 107 | 108 | /** 109 | * Disables all passive scanners with the given IDs (comma separated list of IDs) 110 | */ 111 | public ApiResponse disableScanners(String apikey, String ids) throws ClientApiException { 112 | Map map = null; 113 | map = new HashMap(); 114 | if (apikey != null) { 115 | map.put("apikey", apikey); 116 | } 117 | map.put("ids", ids); 118 | return api.callApi("pscan", "action", "disableScanners", map); 119 | } 120 | 121 | /** 122 | * Sets the alert threshold of the passive scanner with the given ID, accepted values for alert threshold: OFF, DEFAULT, LOW, MEDIUM and HIGH 123 | */ 124 | public ApiResponse setScannerAlertThreshold(String apikey, String id, String alertthreshold) throws ClientApiException { 125 | Map map = null; 126 | map = new HashMap(); 127 | if (apikey != null) { 128 | map.put("apikey", apikey); 129 | } 130 | map.put("id", id); 131 | map.put("alertThreshold", alertthreshold); 132 | return api.callApi("pscan", "action", "setScannerAlertThreshold", map); 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/authentication/AuthenticationInfoValidator.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.authentication; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import br.com.softplan.security.zap.api.exception.AuthenticationInfoValidationException; 10 | import br.com.softplan.security.zap.api.model.AuthenticationInfo; 11 | import br.com.softplan.security.zap.api.model.AuthenticationType; 12 | 13 | /** 14 | * Class to validate {@link AuthenticationInfo} instances. 15 | * 16 | * @author pdsec 17 | */ 18 | public final class AuthenticationInfoValidator { 19 | 20 | private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticationInfoValidator.class); 21 | 22 | public static void validate(AuthenticationInfo info) { 23 | LOGGER.info("--- Validating authentication information ---"); 24 | LOGGER.info("Authentication information provided: {}", info); 25 | if (info == null) { 26 | String message = "AuthenticationInfo cannot be null."; 27 | LOGGER.error(message); 28 | throw new AuthenticationInfoValidationException(message); 29 | } 30 | 31 | checkRequiredParameter(info.getType(), "type"); 32 | checkRequiredParameter(info.getUsername(), "username"); 33 | checkRequiredParameter(info.getPassword(), "password"); 34 | if (info.getType() != AuthenticationType.HTTP) { 35 | checkRequiredParameter(info.getLoginUrl(), "loginUrl"); 36 | } 37 | 38 | List warnings = new ArrayList<>(); 39 | switch (info.getType()) { 40 | case HTTP: 41 | validateHttpAuthenticationInfo(info, warnings); 42 | break; 43 | case FORM: 44 | validateFormAuthenticationInfo(info, warnings); 45 | break; 46 | case CAS: 47 | validateCasAuthenticationInfo(info, warnings); 48 | break; 49 | case SELENIUM: 50 | } 51 | 52 | if (warnings.isEmpty()) { 53 | LOGGER.info("The authentication information provided was successfully validated."); 54 | } else { 55 | LOGGER.warn("Some warnings were generated while validating the authentication information provided:"); 56 | for (String warning : warnings) { 57 | LOGGER.warn("\t{}", warning); 58 | } 59 | } 60 | LOGGER.info("--- Finished validating authentication information ---\n"); 61 | } 62 | 63 | private static void checkRequiredParameter(Object parameter, String parameterName) { 64 | if (parameter == null) { 65 | String message = "The parameter '" + parameterName + "' is required when working with authentication."; 66 | LOGGER.error(message); 67 | throw new AuthenticationInfoValidationException(message); 68 | } 69 | } 70 | 71 | private static void validateHttpAuthenticationInfo(AuthenticationInfo info, List warnings) { 72 | if (info.getHostname() == null) { 73 | String message = "The parameter 'hostname' is required for HTTP authentication."; 74 | LOGGER.error(message); 75 | throw new AuthenticationInfoValidationException(message); 76 | } 77 | if (info.getRealm() == null) { 78 | String message = "The parameter 'realm' is required for HTTP authentication."; 79 | LOGGER.error(message); 80 | throw new AuthenticationInfoValidationException(message); 81 | } 82 | } 83 | 84 | private static void validateFormAuthenticationInfo(AuthenticationInfo info, List warnings) { 85 | validateReauthenticationConfiguration(info, warnings); 86 | if (info.getProtectedPages() != null && info.getProtectedPages().length > 0) { 87 | warnings.add("The parameter 'protectedPages' is not used for form based authentication and is necessary only for CAS authentication."); 88 | } 89 | } 90 | 91 | private static void validateCasAuthenticationInfo(AuthenticationInfo info, List warnings) { 92 | validateReauthenticationConfiguration(info, warnings); 93 | if (info.getProtectedPages() == null || info.getProtectedPages().length == 0) { 94 | String message = "The 'protectedPages' parameter is required for CAS authentication. " 95 | + "A protected page of each context must be accessed prior to scanning to avoid later redirections."; 96 | LOGGER.error(message); 97 | throw new AuthenticationInfoValidationException(message); 98 | } 99 | } 100 | 101 | private static void validateReauthenticationConfiguration(AuthenticationInfo info, List warnings) { 102 | if (info.getLoggedInRegex() == null && info.getLoggedOutRegex() == null && 103 | (info.getExcludeFromScan() == null || info.getExcludeFromScan().length == 0)) { 104 | warnings.add("None of the parameters 'loggedInRegex', 'loggedOutRegex' and 'excludeFromScan' were provided. " 105 | + "Reauthentication will not be possible and there might be a chance that the Spider will log itself out during the scan."); 106 | } 107 | } 108 | 109 | private AuthenticationInfoValidator() {} 110 | 111 | } 112 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/Pnh.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class Pnh { 35 | 36 | private ClientApi api = null; 37 | 38 | public Pnh(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | /** 43 | * This component is optional and therefore the API will only work if it is installed 44 | */ 45 | public ApiResponse monitor(String apikey, String id, String message) throws ClientApiException { 46 | Map map = null; 47 | map = new HashMap(); 48 | if (apikey != null) { 49 | map.put("apikey", apikey); 50 | } 51 | map.put("id", id); 52 | map.put("message", message); 53 | return api.callApi("pnh", "action", "monitor", map); 54 | } 55 | 56 | /** 57 | * This component is optional and therefore the API will only work if it is installed 58 | */ 59 | public ApiResponse oracle(String apikey, String id) throws ClientApiException { 60 | Map map = null; 61 | map = new HashMap(); 62 | if (apikey != null) { 63 | map.put("apikey", apikey); 64 | } 65 | map.put("id", id); 66 | return api.callApi("pnh", "action", "oracle", map); 67 | } 68 | 69 | /** 70 | * This component is optional and therefore the API will only work if it is installed 71 | */ 72 | public ApiResponse startMonitoring(String apikey, String url) throws ClientApiException { 73 | Map map = null; 74 | map = new HashMap(); 75 | if (apikey != null) { 76 | map.put("apikey", apikey); 77 | } 78 | map.put("url", url); 79 | return api.callApi("pnh", "action", "startMonitoring", map); 80 | } 81 | 82 | /** 83 | * This component is optional and therefore the API will only work if it is installed 84 | */ 85 | public ApiResponse stopMonitoring(String apikey, String id) throws ClientApiException { 86 | Map map = null; 87 | map = new HashMap(); 88 | if (apikey != null) { 89 | map.put("apikey", apikey); 90 | } 91 | map.put("id", id); 92 | return api.callApi("pnh", "action", "stopMonitoring", map); 93 | } 94 | 95 | /** 96 | * This component is optional and therefore the API will only work if it is installed 97 | */ 98 | public byte[] pnh(String apikey) throws ClientApiException { 99 | Map map = null; 100 | map = new HashMap(); 101 | if (apikey != null) { 102 | map.put("apikey", apikey); 103 | } 104 | return api.callApiOther("pnh", "other", "pnh", map); 105 | } 106 | 107 | /** 108 | * This component is optional and therefore the API will only work if it is installed 109 | */ 110 | public byte[] manifest(String apikey) throws ClientApiException { 111 | Map map = null; 112 | map = new HashMap(); 113 | if (apikey != null) { 114 | map.put("apikey", apikey); 115 | } 116 | return api.callApiOther("pnh", "other", "manifest", map); 117 | } 118 | 119 | /** 120 | * This component is optional and therefore the API will only work if it is installed 121 | */ 122 | public byte[] service(String apikey) throws ClientApiException { 123 | Map map = null; 124 | map = new HashMap(); 125 | if (apikey != null) { 126 | map.put("apikey", apikey); 127 | } 128 | return api.callApiOther("pnh", "other", "service", map); 129 | } 130 | 131 | /** 132 | * This component is optional and therefore the API will only work if it is installed 133 | */ 134 | public byte[] fx_pnhxpi(String apikey) throws ClientApiException { 135 | Map map = null; 136 | map = new HashMap(); 137 | if (apikey != null) { 138 | map.put("apikey", apikey); 139 | } 140 | return api.callApiOther("pnh", "other", "fx_pnh.xpi", map); 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /zap-client-api/src/test/java/br/com/softplan/security/zap/api/authentication/AuthenticationInfoValidatorTest.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.authentication; 2 | 3 | import static org.testng.AssertJUnit.assertFalse; 4 | import static org.testng.AssertJUnit.assertTrue; 5 | 6 | import org.slf4j.LoggerFactory; 7 | import org.testng.annotations.AfterClass; 8 | import org.testng.annotations.AfterMethod; 9 | import org.testng.annotations.BeforeMethod; 10 | import org.testng.annotations.Test; 11 | 12 | import br.com.softplan.security.zap.api.exception.AuthenticationInfoValidationException; 13 | import br.com.softplan.security.zap.api.model.AuthenticationInfo; 14 | import br.com.softplan.security.zap.api.model.AuthenticationType; 15 | import br.com.softplan.security.zap.api.util.LogbackTestAppender; 16 | import ch.qos.logback.classic.Logger; 17 | 18 | public class AuthenticationInfoValidatorTest { 19 | 20 | private final LogbackTestAppender appender = new LogbackTestAppender(); 21 | 22 | @BeforeMethod 23 | public void setUp() { 24 | ((Logger) LoggerFactory.getLogger(AuthenticationInfoValidator.class)).addAppender(appender); 25 | } 26 | 27 | @AfterMethod 28 | public void clearAppender() { 29 | appender.clearLog(); 30 | } 31 | 32 | @AfterClass 33 | public void removeTestAppenderFromLogger() { 34 | ((Logger) LoggerFactory.getLogger(AuthenticationInfoValidator.class)).detachAppender(appender); 35 | } 36 | 37 | @Test(expectedExceptions = AuthenticationInfoValidationException.class) 38 | public void infoMustNotBeNull() { 39 | AuthenticationInfoValidator.validate(null); 40 | } 41 | 42 | @Test(expectedExceptions = AuthenticationInfoValidationException.class) 43 | public void typeMustNotBeNull() { 44 | AuthenticationInfoValidator.validate(AuthenticationInfo.builder().build()); 45 | } 46 | 47 | @Test(expectedExceptions = AuthenticationInfoValidationException.class) 48 | public void usernameMustNotBeNull() { 49 | AuthenticationInfo info = AuthenticationInfo.builder().type(AuthenticationType.FORM).build(); 50 | AuthenticationInfoValidator.validate(info); 51 | } 52 | 53 | @Test(expectedExceptions = AuthenticationInfoValidationException.class) 54 | public void passwordMustNotBeNull() { 55 | AuthenticationInfo info = AuthenticationInfo.builder() 56 | .type(AuthenticationType.FORM) 57 | .username("username") 58 | .build(); 59 | AuthenticationInfoValidator.validate(info); 60 | } 61 | 62 | @Test(expectedExceptions = AuthenticationInfoValidationException.class) 63 | public void loginUrlMustNotBeNull() { 64 | AuthenticationInfo info = AuthenticationInfo.builder() 65 | .type(AuthenticationType.FORM) 66 | .username("username") 67 | .username("password") 68 | .build(); 69 | AuthenticationInfoValidator.validate(info); 70 | } 71 | 72 | @Test 73 | public void testSimpleFormAuthenticationInfo() { 74 | AuthenticationInfo simpleFormInfo = AuthenticationInfo.builder() 75 | .loggedInRegex("loggedInRegex") 76 | .buildFormAuthenticationInfo("loginUrl", "username", "password"); 77 | AuthenticationInfoValidator.validate(simpleFormInfo); 78 | assertFalse(appender.hasWarn()); 79 | } 80 | 81 | @Test 82 | public void warningShouldBeGeneratedIfProtectedPageIsNotNullInFormAuthentication() { 83 | AuthenticationInfo simpleFormInfo = AuthenticationInfo.builder() 84 | .protectedPages("protectedPage") 85 | .buildFormAuthenticationInfo("loginUrl", "username", "password"); 86 | AuthenticationInfoValidator.validate(simpleFormInfo); 87 | assertTrue(appender.hasWarn()); 88 | } 89 | 90 | @Test 91 | public void warningShouldBeGeneratedIfNoReauthenticationIsPossibleInFormAuthentication() { 92 | AuthenticationInfo info = AuthenticationInfo.builder() 93 | .buildFormAuthenticationInfo("loginUrl", "username", "password"); 94 | AuthenticationInfoValidator.validate(info); 95 | assertTrue(appender.hasWarn()); 96 | } 97 | 98 | @Test 99 | public void testSimpleCasAuthenticationInfo() { 100 | AuthenticationInfo simpleCasInfo = AuthenticationInfo.builder() 101 | .loggedOutRegex("loggedOutRegex") 102 | .buildCasAuthenticationInfo("loginUrl", "username", "password", "protectedPage"); 103 | AuthenticationInfoValidator.validate(simpleCasInfo); 104 | assertFalse(appender.hasWarn()); 105 | } 106 | 107 | @Test 108 | public void warningShouldBeGeneratedIfNoReauthenticationIsPossibleInCasAuthentication() { 109 | AuthenticationInfo simpleCasInfo = AuthenticationInfo.builder() 110 | .buildCasAuthenticationInfo("loginUrl", "username", "password", "protectedPage"); 111 | AuthenticationInfoValidator.validate(simpleCasInfo); 112 | assertTrue(appender.hasWarn()); 113 | } 114 | 115 | @Test(expectedExceptions=AuthenticationInfoValidationException.class) 116 | public void protectedPagesMustNotBeVoidInCasAuthentication() { 117 | AuthenticationInfo simpleCasInfo = AuthenticationInfo.builder() 118 | .loggedOutRegex("loggedOutRegex") 119 | .buildCasAuthenticationInfo("loginUrl", "username", "password"); 120 | AuthenticationInfoValidator.validate(simpleCasInfo); 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/Users.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class Users { 35 | 36 | private ClientApi api = null; 37 | 38 | public Users(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | public ApiResponse usersList(String contextid) throws ClientApiException { 43 | Map map = null; 44 | map = new HashMap(); 45 | map.put("contextId", contextid); 46 | return api.callApi("users", "view", "usersList", map); 47 | } 48 | 49 | public ApiResponse getUserById(String contextid, String userid) throws ClientApiException { 50 | Map map = null; 51 | map = new HashMap(); 52 | map.put("contextId", contextid); 53 | map.put("userId", userid); 54 | return api.callApi("users", "view", "getUserById", map); 55 | } 56 | 57 | public ApiResponse getAuthenticationCredentialsConfigParams(String contextid) throws ClientApiException { 58 | Map map = null; 59 | map = new HashMap(); 60 | map.put("contextId", contextid); 61 | return api.callApi("users", "view", "getAuthenticationCredentialsConfigParams", map); 62 | } 63 | 64 | public ApiResponse getAuthenticationCredentials(String contextid, String userid) throws ClientApiException { 65 | Map map = null; 66 | map = new HashMap(); 67 | map.put("contextId", contextid); 68 | map.put("userId", userid); 69 | return api.callApi("users", "view", "getAuthenticationCredentials", map); 70 | } 71 | 72 | public ApiResponse newUser(String apikey, String contextid, String name) throws ClientApiException { 73 | Map map = null; 74 | map = new HashMap(); 75 | if (apikey != null) { 76 | map.put("apikey", apikey); 77 | } 78 | map.put("contextId", contextid); 79 | map.put("name", name); 80 | return api.callApi("users", "action", "newUser", map); 81 | } 82 | 83 | public ApiResponse removeUser(String apikey, String contextid, String userid) throws ClientApiException { 84 | Map map = null; 85 | map = new HashMap(); 86 | if (apikey != null) { 87 | map.put("apikey", apikey); 88 | } 89 | map.put("contextId", contextid); 90 | map.put("userId", userid); 91 | return api.callApi("users", "action", "removeUser", map); 92 | } 93 | 94 | public ApiResponse setUserEnabled(String apikey, String contextid, String userid, String enabled) throws ClientApiException { 95 | Map map = null; 96 | map = new HashMap(); 97 | if (apikey != null) { 98 | map.put("apikey", apikey); 99 | } 100 | map.put("contextId", contextid); 101 | map.put("userId", userid); 102 | map.put("enabled", enabled); 103 | return api.callApi("users", "action", "setUserEnabled", map); 104 | } 105 | 106 | public ApiResponse setUserName(String apikey, String contextid, String userid, String name) throws ClientApiException { 107 | Map map = null; 108 | map = new HashMap(); 109 | if (apikey != null) { 110 | map.put("apikey", apikey); 111 | } 112 | map.put("contextId", contextid); 113 | map.put("userId", userid); 114 | map.put("name", name); 115 | return api.callApi("users", "action", "setUserName", map); 116 | } 117 | 118 | public ApiResponse setAuthenticationCredentials(String apikey, String contextid, String userid, String authcredentialsconfigparams) throws ClientApiException { 119 | Map map = null; 120 | map = new HashMap(); 121 | if (apikey != null) { 122 | map.put("apikey", apikey); 123 | } 124 | map.put("contextId", contextid); 125 | map.put("userId", userid); 126 | map.put("authCredentialsConfigParams", authcredentialsconfigparams); 127 | return api.callApi("users", "action", "setAuthenticationCredentials", map); 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/core/AlertsFile.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.zaproxy.clientapi.core; 2 | 3 | import org.jdom.Document; 4 | import org.jdom.Element; 5 | import org.jdom.JDOMException; 6 | import org.jdom.input.SAXBuilder; 7 | import org.jdom.output.Format; 8 | import org.jdom.output.XMLOutputter; 9 | 10 | import java.io.File; 11 | import java.io.FileWriter; 12 | import java.io.IOException; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | public class AlertsFile { 17 | public static void saveAlertsToFile(List requireAlerts, List reportAlerts, List ignoredAlerts, File outputFile) throws JDOMException, IOException { 18 | Element alerts = new Element("alerts"); 19 | Document alertsDocument = new Document(alerts); 20 | alertsDocument.setRootElement(alerts); 21 | if (reportAlerts.size() > 0){ 22 | Element alertsFound = new Element("alertsFound"); 23 | alertsFound.setAttribute("alertsFound", Integer.toString(reportAlerts.size())); 24 | for (Alert alert : reportAlerts){ 25 | createAlertXMLElements(alertsFound, alert); 26 | } 27 | alertsDocument.getRootElement().addContent(alertsFound); 28 | } 29 | 30 | if (requireAlerts.size() > 0){ 31 | Element alertsNotFound = new Element("alertsNotFound"); 32 | alertsNotFound.setAttribute("alertsNotFound", Integer.toString(requireAlerts.size())); 33 | for (Alert alert : requireAlerts){ 34 | createAlertXMLElements(alertsNotFound, alert); 35 | } 36 | alertsDocument.getRootElement().addContent(alertsNotFound); 37 | } 38 | 39 | if (ignoredAlerts.size() > 0){ 40 | Element ignoredAlertsFound = new Element("ignoredAlertsFound"); 41 | ignoredAlertsFound.setAttribute("ignoredAlertsFound", Integer.toString(ignoredAlerts.size())); 42 | for (Alert alert : ignoredAlerts){ 43 | createAlertXMLElements(ignoredAlertsFound, alert); 44 | } 45 | alertsDocument.getRootElement().addContent(ignoredAlertsFound); 46 | } 47 | 48 | writeAlertsToFile(outputFile, alertsDocument); 49 | } 50 | 51 | private static void writeAlertsToFile(File outputFile, Document doc) { 52 | 53 | XMLOutputter xmlOutput = new XMLOutputter(); 54 | 55 | xmlOutput.setFormat(Format.getPrettyFormat()); 56 | try { 57 | xmlOutput.output(doc, new FileWriter(outputFile)); 58 | System.out.println("alert xml report saved to: "+outputFile.getAbsolutePath()); 59 | } catch (IOException e) { 60 | e.printStackTrace(); 61 | } 62 | } 63 | 64 | private static void createAlertXMLElements(Element alertsFound, Alert alert) { 65 | Element alertElement = new Element("alert"); 66 | if (alert.getAlert() != null) 67 | alertElement.setAttribute("alert", alert.getAlert()); 68 | if (alert.getRisk() != null) 69 | alertElement.setAttribute("risk", alert.getRisk().name()); 70 | if (alert.getUrl() != null) 71 | alertElement.setAttribute("confidence", alert.getConfidence().name()); 72 | if (alert.getUrl() != null) 73 | alertElement.setAttribute("url", alert.getUrl()); 74 | if (alert.getParam() != null) 75 | alertElement.setAttribute("param", alert.getParam()); 76 | if (alert.getOther() != null) 77 | alertElement.setAttribute("other", alert.getOther()); 78 | if (alert.getAttack() != null) 79 | alertElement.setAttribute("attack", alert.getAttack()); 80 | if (alert.getDescription() != null) 81 | alertElement.setAttribute("description", alert.getDescription()); 82 | if (alert.getSolution() != null) 83 | alertElement.setAttribute("solution", alert.getSolution()); 84 | if (alert.getReference() != null) 85 | alertElement.setAttribute("reference", alert.getReference()); 86 | alertsFound.addContent(alertElement); 87 | } 88 | 89 | public static List getAlertsFromFile(File file, String alertType) throws JDOMException, IOException { 90 | List alerts = new ArrayList<>(); 91 | SAXBuilder parser = new SAXBuilder(); 92 | Document alertsDoc = parser.build(file); 93 | @SuppressWarnings("unchecked") 94 | List alertElements = alertsDoc.getRootElement().getChildren(alertType); 95 | for (Element element: alertElements){ 96 | Alert alert = new Alert( 97 | element.getAttributeValue("alert"), 98 | element.getAttributeValue("url"), 99 | element.getAttributeValue("risk"), 100 | element.getAttributeValue("confidence"), 101 | element.getAttributeValue("param"), 102 | element.getAttributeValue("other")); 103 | alerts.add(alert); 104 | } 105 | return alerts; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/api/report/ZapReportUtil.java: -------------------------------------------------------------------------------- 1 | package br.com.softplan.security.zap.api.report; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.io.OutputStream; 7 | import java.nio.file.Files; 8 | import java.nio.file.Paths; 9 | 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | import br.com.softplan.security.zap.api.exception.ZapClientException; 14 | 15 | /** 16 | * Class responsible to save ZAP reports. 17 | * 18 | * @author pdsec 19 | */ 20 | public final class ZapReportUtil { 21 | 22 | private static final Logger LOGGER = LoggerFactory.getLogger(ZapReportUtil.class); 23 | 24 | private static final String DEFAULT_REPORTS_PATH = 25 | System.getProperty("user.dir") + File.separator + "target" + File.separator + "zap-reports"; 26 | 27 | /** 28 | * Saves all available reports to the default path (target/zap-reports/). 29 | * 30 | * @param report the {@link ZapReport} holding the reports to be saved. 31 | */ 32 | public static void saveAllReports(ZapReport report) { 33 | saveHtmlReport(report); 34 | saveXmlReport(report); 35 | saveHtmlSpiderResults(report); 36 | saveXmlSpiderResults(report); 37 | } 38 | 39 | /** 40 | * Saves all available reports to the given path. 41 | * 42 | * @param report the {@link ZapReport} holding the reports to be saved. 43 | * @param path the path to save the reports. 44 | */ 45 | public static void saveAllReports(ZapReport report, String path) { 46 | saveHtmlReport(report, path); 47 | saveXmlReport(report, path); 48 | saveHtmlSpiderResults(report, path); 49 | saveXmlSpiderResults(report, path); 50 | } 51 | 52 | /** 53 | * Saves the HTML report to the default path (target/zap-reports/). 54 | * 55 | * @param report the {@link ZapReport} holding the report to be saved. 56 | * @return the saved HTML report as a {@code File} instance. 57 | */ 58 | public static File saveHtmlReport(ZapReport report) { 59 | return saveHtmlReport(report, DEFAULT_REPORTS_PATH); 60 | } 61 | 62 | /** 63 | * Saves the HTML report to the given path. 64 | * 65 | * @param report the {@link ZapReport} holding the report to be saved. 66 | * @param path the path to save the HTML report. 67 | * @return the saved HTML report as a {@code File} instance. 68 | */ 69 | public static File saveHtmlReport(ZapReport report, String path) { 70 | return saveReport(report.getHtmlReport(), "zapReport.html", path); 71 | } 72 | 73 | /** 74 | * Saves the XML report to the default path (target/zap-reports/). 75 | * 76 | * @param report the {@link ZapReport} holding the report to be saved. 77 | * @return the saved XML report as a {@code File} instance. 78 | */ 79 | public static File saveXmlReport(ZapReport report) { 80 | return saveXmlReport(report, DEFAULT_REPORTS_PATH); 81 | } 82 | 83 | /** 84 | * Saves the XML report to the given path. 85 | * 86 | * @param report the {@link ZapReport} holding the report to be saved. 87 | * @param path the path to save the XML report. 88 | * @return the saved XML report as a {@code File} instance. 89 | */ 90 | public static File saveXmlReport(ZapReport report, String path) { 91 | return saveReport(report.getXmlReport(), "zapReport.xml", path); 92 | } 93 | 94 | /** 95 | * Saves the HTML Spider results report to the default path (target/zap-reports/). 96 | * 97 | * @param report the {@link ZapReport} holding the report to be saved. 98 | * @return the saved HTML Spider results report as a {@code File} instance. 99 | */ 100 | public static File saveHtmlSpiderResults(ZapReport report) { 101 | return saveHtmlSpiderResults(report, DEFAULT_REPORTS_PATH); 102 | } 103 | 104 | /** 105 | * Saves the HTML Spider results report to the given path. 106 | * 107 | * @param report the {@link ZapReport} holding the report to be saved. 108 | * @param path the path to save the HTML Spider results report. 109 | * @return the saved HTML Spider results report as a {@code File} instance. 110 | */ 111 | public static File saveHtmlSpiderResults(ZapReport report, String path) { 112 | return saveReport(report.getHtmlSpiderResults(), "zapSpiderResults.html", path); 113 | } 114 | 115 | /** 116 | * Saves the XML Spider results report to the default path (target/zap-reports/). 117 | * 118 | * @param report the {@link ZapReport} holding the report to be saved. 119 | * @return the saved XML Spider results report as a {@code File} instance. 120 | */ 121 | public static File saveXmlSpiderResults(ZapReport report) { 122 | return saveXmlSpiderResults(report, DEFAULT_REPORTS_PATH); 123 | } 124 | 125 | /** 126 | * Saves the XML Spider results report to the given path. 127 | * 128 | * @param report the {@link ZapReport} holding the report to be saved. 129 | * @param path the path to save the XML Spider results report. 130 | * @return the saved XML Spider results report as a {@code File} instance. 131 | */ 132 | public static File saveXmlSpiderResults(ZapReport report, String path) { 133 | return saveReport(report.getXmlSpiderResults(), "zapSpiderResults.xml", path); 134 | } 135 | 136 | private static File saveReport(byte[] report, String name, String path) { 137 | createReportsFolder(path); 138 | File reportFile = new File(path, name); 139 | 140 | try (OutputStream fos = new FileOutputStream(reportFile)) { 141 | fos.write(report); 142 | LOGGER.info("{} saved to {}", name, path); 143 | } catch(IOException e) { 144 | String message = "Error saving reports."; 145 | LOGGER.error(message, e); 146 | throw new ZapClientException(message, e); 147 | } 148 | 149 | return reportFile; 150 | } 151 | 152 | private static void createReportsFolder(String path) { 153 | try { 154 | Files.createDirectories(Paths.get(path)); 155 | } catch (IOException e) { 156 | String message = "Error creating reports folder."; 157 | LOGGER.error(message, e); 158 | throw new ZapClientException(message, e); 159 | } 160 | } 161 | 162 | private ZapReportUtil() {} 163 | 164 | } 165 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/HttpSessions.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class HttpSessions { 35 | 36 | private ClientApi api = null; 37 | 38 | public HttpSessions(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | /** 43 | * Gets the sessions of the given site. Optionally returning just the session with the given name. 44 | */ 45 | public ApiResponse sessions(String site, String session) throws ClientApiException { 46 | Map map = null; 47 | map = new HashMap(); 48 | map.put("site", site); 49 | map.put("session", session); 50 | return api.callApi("httpSessions", "view", "sessions", map); 51 | } 52 | 53 | /** 54 | * Gets the name of the active session for the given site. 55 | */ 56 | public ApiResponse activeSession(String site) throws ClientApiException { 57 | Map map = null; 58 | map = new HashMap(); 59 | map.put("site", site); 60 | return api.callApi("httpSessions", "view", "activeSession", map); 61 | } 62 | 63 | /** 64 | * Gets the names of the session tokens for the given site. 65 | */ 66 | public ApiResponse sessionTokens(String site) throws ClientApiException { 67 | Map map = null; 68 | map = new HashMap(); 69 | map.put("site", site); 70 | return api.callApi("httpSessions", "view", "sessionTokens", map); 71 | } 72 | 73 | /** 74 | * Creates an empty session for the given site. Optionally with the given name. 75 | */ 76 | public ApiResponse createEmptySession(String apikey, String site, String session) throws ClientApiException { 77 | Map map = null; 78 | map = new HashMap(); 79 | if (apikey != null) { 80 | map.put("apikey", apikey); 81 | } 82 | map.put("site", site); 83 | map.put("session", session); 84 | return api.callApi("httpSessions", "action", "createEmptySession", map); 85 | } 86 | 87 | /** 88 | * Removes the session from the given site. 89 | */ 90 | public ApiResponse removeSession(String apikey, String site, String session) throws ClientApiException { 91 | Map map = null; 92 | map = new HashMap(); 93 | if (apikey != null) { 94 | map.put("apikey", apikey); 95 | } 96 | map.put("site", site); 97 | map.put("session", session); 98 | return api.callApi("httpSessions", "action", "removeSession", map); 99 | } 100 | 101 | /** 102 | * Sets the given session as active for the given site. 103 | */ 104 | public ApiResponse setActiveSession(String apikey, String site, String session) throws ClientApiException { 105 | Map map = null; 106 | map = new HashMap(); 107 | if (apikey != null) { 108 | map.put("apikey", apikey); 109 | } 110 | map.put("site", site); 111 | map.put("session", session); 112 | return api.callApi("httpSessions", "action", "setActiveSession", map); 113 | } 114 | 115 | /** 116 | * Unsets the active session of the given site. 117 | */ 118 | public ApiResponse unsetActiveSession(String apikey, String site) throws ClientApiException { 119 | Map map = null; 120 | map = new HashMap(); 121 | if (apikey != null) { 122 | map.put("apikey", apikey); 123 | } 124 | map.put("site", site); 125 | return api.callApi("httpSessions", "action", "unsetActiveSession", map); 126 | } 127 | 128 | /** 129 | * Adds the session token to the given site. 130 | */ 131 | public ApiResponse addSessionToken(String apikey, String site, String sessiontoken) throws ClientApiException { 132 | Map map = null; 133 | map = new HashMap(); 134 | if (apikey != null) { 135 | map.put("apikey", apikey); 136 | } 137 | map.put("site", site); 138 | map.put("sessionToken", sessiontoken); 139 | return api.callApi("httpSessions", "action", "addSessionToken", map); 140 | } 141 | 142 | /** 143 | * Removes the session token from the given site. 144 | */ 145 | public ApiResponse removeSessionToken(String apikey, String site, String sessiontoken) throws ClientApiException { 146 | Map map = null; 147 | map = new HashMap(); 148 | if (apikey != null) { 149 | map.put("apikey", apikey); 150 | } 151 | map.put("site", site); 152 | map.put("sessionToken", sessiontoken); 153 | return api.callApi("httpSessions", "action", "removeSessionToken", map); 154 | } 155 | 156 | /** 157 | * Sets the value of the session token of the given session for the given site. 158 | */ 159 | public ApiResponse setSessionTokenValue(String apikey, String site, String session, String sessiontoken, String tokenvalue) throws ClientApiException { 160 | Map map = null; 161 | map = new HashMap(); 162 | if (apikey != null) { 163 | map.put("apikey", apikey); 164 | } 165 | map.put("site", site); 166 | map.put("session", session); 167 | map.put("sessionToken", sessiontoken); 168 | map.put("tokenValue", tokenvalue); 169 | return api.callApi("httpSessions", "action", "setSessionTokenValue", map); 170 | } 171 | 172 | /** 173 | * Renames the session of the given site. 174 | */ 175 | public ApiResponse renameSession(String apikey, String site, String oldsessionname, String newsessionname) throws ClientApiException { 176 | Map map = null; 177 | map = new HashMap(); 178 | if (apikey != null) { 179 | map.put("apikey", apikey); 180 | } 181 | map.put("site", site); 182 | map.put("oldSessionName", oldsessionname); 183 | map.put("newSessionName", newsessionname); 184 | return api.callApi("httpSessions", "action", "renameSession", map); 185 | } 186 | 187 | } 188 | -------------------------------------------------------------------------------- /zap-client-api/src/main/java/br/com/softplan/security/zap/zaproxy/clientapi/gen/Search.java: -------------------------------------------------------------------------------- 1 | /* Zed Attack Proxy (ZAP) and its related class files. 2 | * 3 | * ZAP is an HTTP/HTTPS proxy for assessing web application security. 4 | * 5 | * Copyright the ZAP development team 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | package br.com.softplan.security.zap.zaproxy.clientapi.gen; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ApiResponse; 27 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApi; 28 | import br.com.softplan.security.zap.zaproxy.clientapi.core.ClientApiException; 29 | 30 | 31 | /** 32 | * This file was automatically generated. 33 | */ 34 | public class Search { 35 | 36 | private ClientApi api = null; 37 | 38 | public Search(ClientApi api) { 39 | this.api = api; 40 | } 41 | 42 | public ApiResponse urlsByUrlRegex(String regex, String baseurl, String start, String count) throws ClientApiException { 43 | Map map = null; 44 | map = new HashMap(); 45 | map.put("regex", regex); 46 | map.put("baseurl", baseurl); 47 | map.put("start", start); 48 | map.put("count", count); 49 | return api.callApi("search", "view", "urlsByUrlRegex", map); 50 | } 51 | 52 | public ApiResponse urlsByRequestRegex(String regex, String baseurl, String start, String count) throws ClientApiException { 53 | Map map = null; 54 | map = new HashMap(); 55 | map.put("regex", regex); 56 | map.put("baseurl", baseurl); 57 | map.put("start", start); 58 | map.put("count", count); 59 | return api.callApi("search", "view", "urlsByRequestRegex", map); 60 | } 61 | 62 | public ApiResponse urlsByResponseRegex(String regex, String baseurl, String start, String count) throws ClientApiException { 63 | Map map = null; 64 | map = new HashMap(); 65 | map.put("regex", regex); 66 | map.put("baseurl", baseurl); 67 | map.put("start", start); 68 | map.put("count", count); 69 | return api.callApi("search", "view", "urlsByResponseRegex", map); 70 | } 71 | 72 | public ApiResponse urlsByHeaderRegex(String regex, String baseurl, String start, String count) throws ClientApiException { 73 | Map map = null; 74 | map = new HashMap(); 75 | map.put("regex", regex); 76 | map.put("baseurl", baseurl); 77 | map.put("start", start); 78 | map.put("count", count); 79 | return api.callApi("search", "view", "urlsByHeaderRegex", map); 80 | } 81 | 82 | public ApiResponse messagesByUrlRegex(String regex, String baseurl, String start, String count) throws ClientApiException { 83 | Map map = null; 84 | map = new HashMap(); 85 | map.put("regex", regex); 86 | map.put("baseurl", baseurl); 87 | map.put("start", start); 88 | map.put("count", count); 89 | return api.callApi("search", "view", "messagesByUrlRegex", map); 90 | } 91 | 92 | public ApiResponse messagesByRequestRegex(String regex, String baseurl, String start, String count) throws ClientApiException { 93 | Map map = null; 94 | map = new HashMap(); 95 | map.put("regex", regex); 96 | map.put("baseurl", baseurl); 97 | map.put("start", start); 98 | map.put("count", count); 99 | return api.callApi("search", "view", "messagesByRequestRegex", map); 100 | } 101 | 102 | public ApiResponse messagesByResponseRegex(String regex, String baseurl, String start, String count) throws ClientApiException { 103 | Map map = null; 104 | map = new HashMap(); 105 | map.put("regex", regex); 106 | map.put("baseurl", baseurl); 107 | map.put("start", start); 108 | map.put("count", count); 109 | return api.callApi("search", "view", "messagesByResponseRegex", map); 110 | } 111 | 112 | public ApiResponse messagesByHeaderRegex(String regex, String baseurl, String start, String count) throws ClientApiException { 113 | Map map = null; 114 | map = new HashMap(); 115 | map.put("regex", regex); 116 | map.put("baseurl", baseurl); 117 | map.put("start", start); 118 | map.put("count", count); 119 | return api.callApi("search", "view", "messagesByHeaderRegex", map); 120 | } 121 | 122 | public byte[] harByUrlRegex(String apikey, String regex, String baseurl, String start, String count) throws ClientApiException { 123 | Map map = null; 124 | map = new HashMap(); 125 | if (apikey != null) { 126 | map.put("apikey", apikey); 127 | } 128 | map.put("regex", regex); 129 | map.put("baseurl", baseurl); 130 | map.put("start", start); 131 | map.put("count", count); 132 | return api.callApiOther("search", "other", "harByUrlRegex", map); 133 | } 134 | 135 | public byte[] harByRequestRegex(String apikey, String regex, String baseurl, String start, String count) throws ClientApiException { 136 | Map map = null; 137 | map = new HashMap(); 138 | if (apikey != null) { 139 | map.put("apikey", apikey); 140 | } 141 | map.put("regex", regex); 142 | map.put("baseurl", baseurl); 143 | map.put("start", start); 144 | map.put("count", count); 145 | return api.callApiOther("search", "other", "harByRequestRegex", map); 146 | } 147 | 148 | public byte[] harByResponseRegex(String apikey, String regex, String baseurl, String start, String count) throws ClientApiException { 149 | Map map = null; 150 | map = new HashMap(); 151 | if (apikey != null) { 152 | map.put("apikey", apikey); 153 | } 154 | map.put("regex", regex); 155 | map.put("baseurl", baseurl); 156 | map.put("start", start); 157 | map.put("count", count); 158 | return api.callApiOther("search", "other", "harByResponseRegex", map); 159 | } 160 | 161 | public byte[] harByHeaderRegex(String apikey, String regex, String baseurl, String start, String count) throws ClientApiException { 162 | Map map = null; 163 | map = new HashMap(); 164 | if (apikey != null) { 165 | map.put("apikey", apikey); 166 | } 167 | map.put("regex", regex); 168 | map.put("baseurl", baseurl); 169 | map.put("start", start); 170 | map.put("count", count); 171 | return api.callApiOther("search", "other", "harByHeaderRegex", map); 172 | } 173 | 174 | } 175 | -------------------------------------------------------------------------------- /zap-utils/src/main/resources/scripts/cas-auth.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This script is intended to handle CAS (http://jasig.github.io/cas) authentication via ZAP. 3 | * 4 | * When working with CAS, a single POST request with the credentials is not enough to trigger the authentication. 5 | * When we GET the login page, some input values used by CAS are generated (the login ticket and some Spring Web 6 | * Flow related parameters), and they must be included in the POST request for the authentication to work. So 7 | * this script basically sends a GET to the login page, parses its response looking for the values generated by 8 | * CAS, and sends a POST request with these values and the credentials. 9 | * 10 | * This is enough to trigger the authentication, but it's not enough to enable a successfull authenticated scan 11 | * with ZAP. There is one more step needed because of redirects: CAS loves them and ZAP doesn't. More details on 12 | * that can be found in the comments within the script. 13 | * 14 | * Reauthentication works and a good way to achieve it is with a Logged Out Regex as something like: 15 | * \QLocation: http://your.domain/cas-server/\E.* 16 | * Unauthenticated responses will be 302 redirects to the CAS server, so this is the easiest way to identify that 17 | * there was a redirect to the CAS server and thus the user is not logged in. 18 | * 19 | * @author Thiago Porciúncula 20 | * @author Hugo Baes 21 | * @author Fábio Resner 22 | */ 23 | function authenticate(helper, paramsValues, credentials) { 24 | print("---- CAS authentication script has started ----"); 25 | 26 | // Enable Rhino behavior, in case ZAP is running on Java 8 (which uses Nashorn) 27 | if (java.lang.System.getProperty("java.version").startsWith("1.8")) { 28 | load("nashorn:mozilla_compat.js"); 29 | } 30 | 31 | // Imports 32 | importClass(org.parosproxy.paros.network.HttpRequestHeader) 33 | importClass(org.parosproxy.paros.network.HttpHeader) 34 | importClass(org.apache.commons.httpclient.URI) 35 | importClass(org.apache.commons.httpclient.params.HttpClientParams) 36 | importClass(java.util.regex.Pattern) 37 | 38 | var loginUri = new URI(paramsValues.get("loginUrl"), false); 39 | 40 | // Perform a GET request to the login page to get the values generated by CAS on the response (login ticket, event id, etc) 41 | var get = helper.prepareMessage(); 42 | get.setRequestHeader(new HttpRequestHeader(HttpRequestHeader.GET, loginUri, HttpHeader.HTTP10)); 43 | helper.sendAndReceive(get); 44 | var casInputValues = getCASInputValues(get.getResponseBody().toString()); 45 | 46 | // Build the request body using the credentials values and the CAS values obtained from the first request 47 | var requestBody = "username=" + encodeURIComponent(credentials.getParam("username")); 48 | requestBody += "&password=" + encodeURIComponent(credentials.getParam("password")); 49 | requestBody += "<=" + encodeURIComponent(casInputValues["lt"]); 50 | requestBody += "&execution=" + encodeURIComponent(casInputValues["execution"]); 51 | requestBody += "&_eventId=" + encodeURIComponent(casInputValues["_eventId"]); 52 | 53 | // Add any extra post data provided 54 | extraPostData = paramsValues.get("extraPostData"); 55 | if (extraPostData != null && !extraPostData.trim().isEmpty()) { 56 | requestBody += "&" + extraPostData.trim(); 57 | } 58 | 59 | // Perform a POST request to authenticate 60 | print("POST request body built for the authentication:\n " + requestBody.replaceAll("&", "\n ")); 61 | var post = helper.prepareMessage(); 62 | post.setRequestHeader(new HttpRequestHeader(HttpRequestHeader.POST, loginUri, HttpHeader.HTTP10)); 63 | post.setRequestBody(requestBody); 64 | helper.sendAndReceive(post); 65 | 66 | /* 67 | * At this point we are authenticated, but we are not done yet :( 68 | * 69 | * We have authenticated on the CAS server (let's say http://mydomain/cas-server), so when we access 70 | * the app (i.e. http://mydomain/my-app) for the first time, we will be redirected to the CAS server. 71 | * Since we are authenticated, the CAS server will redirect us back to the app: 72 | * 73 | * http://your.domain/your-app -> http://your.domain/cas-server -> http://your.domain/your-app 74 | * 75 | * There are two problems here: the first is that ZAP's Spider explicitly doesn't follow redirects. 76 | * So if the Spider access the app, it will get a redirect response and the page will never really 77 | * be spidered. However, this redirect happens only at the first time we access the app after the 78 | * authentication, so we could just access the app once before ZAP's Spider starts, right? Almost. 79 | * This is a circular redirect, and the second problem is that ZAP doesn't support it. So, this 80 | * strategy works, but we need a bit of code to get us through this. 81 | * 82 | * This script has another parameter that should hold at least one protected page for each app that 83 | * might be analyzed. We then proceed to enable circular redirect for ZAP (reflection to the rescue!) 84 | * and do a simple GET for each page, ensuring no redirects will happen during our analysis. 85 | */ 86 | 87 | // Get the protected pages 88 | var protectedPagesSeparatedByComma = paramsValues.get("protectedPages"); 89 | var protectedPages = protectedPagesSeparatedByComma.split(","); 90 | 91 | // Enable circular redirect 92 | var client = getHttpClientFromHelper(helper); 93 | client.getParams().setParameter(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS, true); 94 | 95 | // Perform a GET request on the protected pages to avoid redirects during the scan 96 | for (index in protectedPages) { 97 | var request = helper.prepareMessage(); 98 | request.setRequestHeader(new HttpRequestHeader(HttpRequestHeader.GET, new URI(protectedPages[index], false), HttpHeader.HTTP10)); 99 | helper.sendAndReceive(request, true); 100 | } 101 | 102 | // Disable circular redirect 103 | client.getParams().setParameter(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS, false); 104 | 105 | print("---- CAS authentication script has finished ----\n"); 106 | 107 | return post; 108 | } 109 | 110 | function getCASInputValues(response){ 111 | var result = {}; 112 | 113 | var regex = "