Skip to content
This repository was archived by the owner on Feb 26, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,18 @@ ENV SCB_REPOSITORY_URL ${REPOSITORY_URL}

RUN gradle clean build -Pvcs_commit=${SCB_COMMIT_ID} -Pvcs_version=${SCB_BRANCH} -Pvcs_url=${SCB_REPOSITORY_URL}

FROM owasp/zap2docker-bare
FROM owasp/zap2docker-weekly:w2019-02-05

COPY dockerfiles/init.sh /home/zap/init.sh
COPY dockerfiles/csrfAuthScript.js /home/zap/scripts/templates/authentication/csrfAuthScript.js
COPY --from=builder /home/gradle/build/libs/scanner-webapplication-zap-0.4.0-SNAPSHOT.jar /home/zap/app.jar

USER root

RUN apk --update --no-cache add curl
HEALTHCHECK --interval=30s --timeout=5s --start-period=120s --retries=3 CMD curl --fail http://localhost:8080/internal/health || exit 1

RUN chmod g+w /etc/passwd

RUN apk add --update ca-certificates openssl
RUN wget -O /home/zap/wait-for-it.sh https://raw.githubusercontent.com/vishnubob/wait-for-it/54d1f0bfeb6557adf8a3204455389d0901652242/wait-for-it.sh

RUN chmod +x /home/zap/init.sh && \
chmod +x /home/zap/wait-for-it.sh && \
chgrp -R 0 /home/zap/ && \
chmod -R g=u /home/zap/ && \
chown -R zap /home/zap
Expand All @@ -48,6 +44,8 @@ LABEL org.opencontainers.image.title="secureCodeBox scanner-webapplication-zap"
org.opencontainers.image.revision=$COMMIT_ID \
org.opencontainers.image.created=$BUILD_DATE

HEALTHCHECK --interval=30s --timeout=5s --start-period=120s --retries=3 CMD curl --fail http://localhost:8080/internal/health || exit 1

EXPOSE 8080 8090

ENV JAVA_OPTS ""
Expand Down
14 changes: 2 additions & 12 deletions dockerfiles/init.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,4 @@
#!/bin/bash
/zap/zap.sh -Xmx3G -daemon -dir /home/zap/ -port 8090 -host 0.0.0.0 -config api.disablekey=true -config api.addrs.addr.name=.* -config api.addrs.addr.regex=true -addoninstall soap -addoninstall openapi -addoninstall ascanrulesBeta -addoninstall ascanrulesAlpha -addoninstall pscanrulesBeta -addoninstall pscanrulesAlpha &

if [ `id -u` -ge 1000 ]; then
cat /etc/passwd | sed -e "s/^osUser:/builder:/" > /tmp/passwd
echo "osUser:x:`id -u`:`id -g`:,,,:/home/zap:/bin/bash" >> /tmp/passwd
cat /tmp/passwd > /etc/passwd
rm /tmp/passwd
fi

/zap/zap.sh -Xmx3G -daemon -dir /home/zap/ -port 8090 -host 0.0.0.0 -config api.disablekey=true -config api.addrs.addr.name=.* -config api.addrs.addr.regex=true -addoninstall soap -addoninstall openapi &

sleep 10

java -Djava.security.egd=file:/dev/./urandom -Xmx2G -jar /home/zap/app.jar
/home/zap/wait-for-it.sh --timeout=120 localhost:8090 -- java -Djava.security.egd=file:/dev/./urandom -Xmx2G -jar /home/zap/app.jar
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public class EngineWorkerJob implements JobRunnable {
@Autowired
private ZapTaskService taskService;
@Autowired
private ZapService service;
private ZapService zapService;

@Override
public JobDefinition getJobDefinition() {
Expand Down Expand Up @@ -138,7 +138,7 @@ private void performSpiderTask(JobEventPublisher publisher, ZapTask task) throws
ZapTargetAttributes attributes = target.getAttributes();

//Create a new Context for each target
String contextId = service.createContext(attributes.getBaseUrl(),
String contextId = zapService.createContext(attributes.getBaseUrl(),
attributes.getSpiderIncludeRegex(), attributes.getSpiderExcludeRegex());

String userId = configureAuthentication(target, contextId);
Expand Down Expand Up @@ -184,7 +184,7 @@ private void performScannerTask(JobEventPublisher publisher, ZapTask task) throw
}

// Save only one Raw Report, as zap doesn't support to get reports on the individual targets.
rawFindings.add(service.getRawReport());
rawFindings.add(zapService.getRawReport());

if (config.isFilterScannerResults()) {
log.info("Removing duplicate findings");
Expand Down Expand Up @@ -223,27 +223,28 @@ private List<Finding> executeSpider(Target target, String contextId, String user
ZapReplacerRule[] zapReplacerRules = target.getAttributes().getZapReplacerRules();

log.debug("Start Spider with URL: " + target.getLocation());
String scanId = (String) service.startSpiderAsUser(target.getLocation(), spiderApiSpecUrl,
String scanId = zapService.startSpiderAsUser(target.getLocation(), spiderApiSpecUrl,
spiderMaxDepth, contextId, userId, zapReplacerRules);
return service.retrieveSpiderResult(scanId);
return zapService.retrieveSpiderResult(scanId);
}

private List<Finding> executeScanner(Target target, String contextId, String userId) throws ClientApiException {
log.debug("Start Sitemap recreation");
service.recallTarget(target);
Integer delayInMs = target.getAttributes().getScannerDelayInMs();
Integer threadsPerHost = target.getAttributes().getThreadsPerHost();
ZapReplacerRule[] zapReplacerRules = target.getAttributes().getZapReplacerRules();

log.debug("Start Sitemap recreation");
zapService.recallTarget(target, zapReplacerRules);

log.debug("Start Scanner with URL: " + target.getLocation());
String scanId = (String) service.startScannerAsUser(target.getLocation(), contextId, userId, delayInMs, threadsPerHost, zapReplacerRules);
return service.retrieveScannerResult(scanId, target.getLocation());
String scanId = zapService.startScannerAsUser(target.getLocation(), contextId, userId, delayInMs, threadsPerHost, zapReplacerRules);
return zapService.retrieveScannerResult(scanId, target.getLocation());
}

private String configureScannerContext(String targetUrl, Target target) throws ClientApiException {
ZapTargetAttributes attributes = target.getAttributes();
// Create a new Context for all the targets belonging to this context
return service.createContext(targetUrl, attributes.getScannerIncludeRegex(), attributes.getScannerExcludeRegex());
return zapService.createContext(targetUrl, attributes.getScannerIncludeRegex(), attributes.getScannerExcludeRegex());
}

private String configureAuthentication(Target target, String contextId) throws ClientApiException, UnsupportedEncodingException {
Expand All @@ -260,7 +261,7 @@ private String configureAuthentication(Target target, String contextId) throws C
String csrfToken = target.getAttributes().getCsrfTokenId();

if (authentication) {
return service.configureAuthentication(
return zapService.configureAuthentication(
contextId, loginSite,
usernameFieldId, passwordFieldId,
loginUser, password,
Expand All @@ -278,7 +279,7 @@ private void completeTask(ZapTask task, JobEventPublisher publisher, List<Findin
CompleteTask completedTask = taskService.completeTask(task, findings, rawFindingsString, zapTopic);
publisher.info("Completed " + ((zapTopic == ZapTopic.ZAP_SCANNER) ? "scanner" : "spider") + " task: " + completedTask.getJobId());

service.clearSession();
zapService.clearSession();
} catch (JsonProcessingException e) {
log.warn("Could not persist rawFindings");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,25 +87,13 @@ public void init() {
* @return Returns true if the configured SCB Engine API is available and at least one processModell is deployed.
*/
boolean isApiAvailable() {
return (this.countProcesses() > 0);
}

/**
* @return Returns the number of currently deployed process models which are available at the SCB Engine.
*/
int countProcesses() {

String url = config.getProcessEngineApiUrl() + "/box/processes/";
log.debug("Call countProcesses() via {}", url);
String url = config.getProcessEngineApiUrl() + "/status";
log.debug("Call engine status via {}", url);

ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
log.debug(String.format("Result for countProcesses(): %s", response));
log.debug(String.format("Engine api status: %s", response));

if (response.getStatusCode().is2xxSuccessful() && response.getHeaders().getContentType().isCompatibleWith(MediaType.APPLICATION_JSON) && !response.toString().isEmpty()) {
return response.toString().split("id").length;
} else {
return 0;
}
return response.getStatusCode().is2xxSuccessful();
}

ZapTask fetchAndLockTask(ZapTopic zapTopic, String jobId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,9 @@ public boolean isApiAvailable() {
@Override
public StatusDetail statusDetail() {
try {
boolean isApiAvailable = this.isApiAvailable();

if (isApiAvailable) {
if (this.isApiAvailable()) {
log.debug("Internal health check: OK");
return StatusDetail.statusDetail("Engine SCB API", Status.OK, "The Engine API is up and running", singletonMap("Deployed Processes", String.valueOf(this.taskApiClient.countProcesses())));
return StatusDetail.statusDetail("Engine SCB API", Status.OK, "The Engine API is up and running");
} else {
return StatusDetail.statusDetail("Engine SCB API", Status.WARNING, "Couldn't reach the Engine API!");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package io.securecodebox.zap.service.zap;

import io.securecodebox.zap.service.engine.model.zap.ZapReplacerRule;
import javax.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.zaproxy.clientapi.core.ApiResponseList;
import org.zaproxy.clientapi.core.ApiResponseSet;
import org.zaproxy.clientapi.core.ClientApi;
import org.zaproxy.clientapi.core.ClientApiException;

@Slf4j
public class ReplacerPluginConfigurator {

private ClientApi api;

public ReplacerPluginConfigurator(ClientApi api) {
this.api = api;
}

public void configureZapWithReplacerRules(ZapReplacerRule[] replacerRules) throws ClientApiException {
resetReplacerRules();
if (replacerRules != null && replacerRules.length > 0) {
log.debug("Adding {} custom ZAP replacer rules", replacerRules.length);
addReplacerRules(replacerRules);
} else {
log.info("No custom ZAP replacer rule defined.");
}
}

/**
* Gets and converts the API wrapper request "replacer.rules()"
*
* @return array of replacer rules
* @throws ClientApiException can be thrown for any api request
*/
final ZapReplacerRule[] getCurrentReplacerRules() throws ClientApiException {
return ((ApiResponseList) api.replacer.rules()).getItems().stream()
.map(i -> ((ApiResponseSet) i))
.map(i -> {
ZapReplacerRule rule = new ZapReplacerRule();
rule.setMatchType(i.getStringValue("matchType"));
rule.setDescription(i.getStringValue("description"));
rule.setMatchString(i.getStringValue("matchString"));
rule.setInitiators(i.getStringValue("initiators"));
rule.setMatchRegex(i.getStringValue("matchRegex"));
rule.setReplacement(i.getStringValue("replacement"));
rule.setEnabled(i.getStringValue("enabled"));
return rule;
})
.toArray(ZapReplacerRule[]::new);
}

/**
* Adds ZAP replacer rules
*
* @param rules
* @throws ClientApiException thrown if at least one rule cannot be set
*/
void addReplacerRules(ZapReplacerRule[] rules) throws ClientApiException {
if (rules != null && rules.length > 0) {
log.debug("Adding #{} exiting replacer rules", rules.length);
for (ZapReplacerRule rule: rules) {
if (rule != null) {
addReplacerRule(rule);
} else {
log.warn("Couldn't add the replacer rule, the rule must not be null ot empty.");
}
}
} else {
log.warn("There is no replacer rule to add.");
}
}

void resetReplacerRules() throws ClientApiException {
log.debug("Resetting ZAP replacer rules");
ZapReplacerRule[] currentRules = getCurrentReplacerRules();
if (currentRules != null && currentRules.length > 0) {
removeReplacerRules(currentRules);
}
}

/**
* Adds ZAP replacer rule
*
* @param rule
* @throws ClientApiException thrown if rule cannot be set
*/
private void addReplacerRule(@NotNull ZapReplacerRule rule) throws ClientApiException {
api.replacer.addRule(
rule.getDescription(),
rule.getEnabled(),
rule.getMatchType(),
rule.getMatchRegex(),
rule.getMatchString(),
rule.getReplacement(),
rule.getInitiators());
}

/**
* Removes the given list of ZAP replacer rules.
*
* @param rules The list of ZAP replacer rules to remove.
* @throws ClientApiException thrown if at least one of the rules cannot be removed
*/
private void removeReplacerRules(@NotNull ZapReplacerRule[] rules) throws ClientApiException {
if (rules != null && rules.length > 0) {
log.debug("Removing #{} exiting replacer rules", rules.length);
for (ZapReplacerRule rule : rules){
removeReplacerRule(rule);
}
} else {
log.warn("There are no replacer rules to remove.");
}
}

/**
* Removes a single ZAP replacer rule.
*
* @param rule The ZAP replacer rule to remove.
* @throws ClientApiException thrown if rule cannot be removed
*/
private void removeReplacerRule(@NotNull ZapReplacerRule rule) throws ClientApiException {
if (rule != null) {
api.replacer.removeRule(rule.getDescription());
} else {
log.warn("You can't remove a replacer rule which is null.");
}
}
}
Loading