diff --git a/Dockerfile b/Dockerfile index 5d530644c..ff465d403 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/eclipse-temurin:19-jre-focal +FROM docker.io/eclipse-temurin:21-jdk-ubi9-minimal LABEL NAME = "WebGoat: A deliberately insecure Web Application" MAINTAINER "WebGoat team" @@ -14,6 +14,8 @@ COPY --chown=webgoat target/webgoat-*.jar /home/webgoat/webgoat.jar EXPOSE 8080 EXPOSE 9090 +ENV TZ=Europe/Amsterdam + WORKDIR /home/webgoat ENTRYPOINT [ "java", \ "-Duser.home=/home/webgoat", \ @@ -30,8 +32,4 @@ ENTRYPOINT [ "java", \ "--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", \ "--add-opens", "java.base/java.io=ALL-UNNAMED", \ "-Drunning.in.docker=true", \ - "-Dwebgoat.host=0.0.0.0", \ - "-Dwebwolf.host=0.0.0.0", \ - "-Dwebgoat.port=8080", \ - "-Dwebwolf.port=9090", \ - "-jar", "webgoat.jar" ] + "-jar", "webgoat.jar", "--server.address", "0.0.0.0" ] diff --git a/README.md b/README.md index a1cadeae9..b8203e0bd 100644 --- a/README.md +++ b/README.md @@ -44,19 +44,27 @@ Every release is also published on [DockerHub](https://hub.docker.com/r/webgoat/ docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 webgoat/webgoat ``` -If you want to reuse the container, give it a name: +For some lessons you need the container run in the same timezone. For this you can set the TZ environment variable. +E.g. ```shell -docker run --name webgoat -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 webgoat/webgoat +docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=America/Boise webgoat/webgoat ``` -As long as you don't remove the container you can use: +If you want to use OWASP ZAP or another proxy, you can no longer use 127.0.0.1 or localhost. but +you can use custom host entries. For example: ```shell -docker start webgoat +127.0.0.1 www.webgoat.local www.webwolf.local ``` -This way, you can start where you left off. If you remove the container, you need to use `docker run` again. +Then you can run the container with: + +```shell +docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e WEBGOAT_HOST=www.webgoat.local -e WEBWOLF_HOST=www.webwolf.local -e TZ=America/Boise webgoat/webgoat +``` + +Then visit http://www.webgoat.local:8080/WebGoat/ and http://www.webwolf.local:9090/WebWolf/ ## 2. Run using Docker with complete Linux Desktop @@ -71,7 +79,8 @@ docker run -p 127.0.0.1:3000:3000 webgoat/webgoat-desktop Download the latest WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases) ```shell -java -Dfile.encoding=UTF-8 -Dwebgoat.port=8080 -Dwebwolf.port=9090 -jar webgoat-2023.5.jar +export TZ=Europe/Amsterdam # or your timezone +java -Dfile.encoding=UTF-8 -jar webgoat-2023.5.jar ``` Click the link in the log to start WebGoat. @@ -80,7 +89,7 @@ Click the link in the log to start WebGoat. ### Prerequisites: -* Java 17 +* Java 17 or 21 * Your favorite IDE * Git, or Git support in your IDE @@ -132,9 +141,10 @@ For specialist only. There is a way to set up WebGoat with a personalized menu. For instance running as a jar on a Linux/macOS it will look like this: ```Shell +export TZ=Europe/Amsterdam # or your timezone export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE" export EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations" -java -jar target/webgoat-2023.4-SNAPSHOT.jar +java -jar target/webgoat-2023.6-SNAPSHOT.jar ``` Or in a docker run it would (once this version is pushed into docker hub) look like this: diff --git a/pom.xml b/pom.xml index 6a6094419..86db9d546 100644 --- a/pom.xml +++ b/pom.xml @@ -141,10 +141,9 @@ 3.1.1.RELEASE 5.3.3 / - 8080 + false 0.53 / - 9090 2.27.2 1.2 1.4.5 @@ -513,10 +512,19 @@ org.apache.maven.plugins maven-failsafe-plugin + + ${webgoat.sslenabled} + 127.0.0.1 + ${webgoat.port} + ${webgoat.context} + 127.0.0.1 + ${webwolf.port} + ${webwolf.context} + ${basedir}/src/test/resources/logback-test.xml - -Xmx512m -Dwebgoatport=${webgoat.port} -Dwebwolfport=${webwolf.port} -Dwebwolfcontext=${webwolf.context} -Dwebgoatcontext=${webgoat.context} + -Xmx512m org/owasp/webgoat/*Test @@ -557,7 +565,6 @@ maven-checkstyle-plugin ${checkstyle.version} - UTF-8 true true config/checkstyle/checkstyle.xml @@ -686,16 +693,15 @@ webgoat.port webwolf.port - jmxPort - com.bazaarvoice.maven.plugins + org.honton.chas process-exec-maven-plugin - 0.9 + 0.9.2 start-jar @@ -703,8 +709,18 @@ start pre-integration-test + ${project.build.directory} + + ${webgoat.sslenabled} + 127.0.0.1 + ${webgoat.port} + ${webgoat.context} + 127.0.0.1 + ${webwolf.port} + ${webwolf.context} + java -jar @@ -712,10 +728,6 @@ -Dwebgoat.server.directory=${java.io.tmpdir}/webgoat_${webgoat.port} -Dwebgoat.user.directory=${java.io.tmpdir}/webgoat_${webgoat.port} -Dspring.main.banner-mode=off - -Dwebgoat.port=${webgoat.port} - -Dwebgoat.context=${webgoat.context} - -Dwebwolf.port=${webwolf.port} - -Dwebwolf.context=${webwolf.context} --add-opens java.base/java.lang=ALL-UNNAMED --add-opens @@ -741,8 +753,6 @@ ${project.build.directory}/webgoat-${project.version}.jar false - 120 - http://localhost:${webgoat.port}/WebGoat/actuator/health @@ -767,7 +777,6 @@ org.owasp dependency-check-maven - 8.4.3 7 false @@ -816,7 +825,6 @@ org.jacoco jacoco-maven-plugin - ${jacoco.version} before-unit-test diff --git a/src/it/java/org/owasp/webgoat/CSRFIntegrationTest.java b/src/it/java/org/owasp/webgoat/CSRFIntegrationTest.java index 54d9dc5a3..54231e893 100644 --- a/src/it/java/org/owasp/webgoat/CSRFIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/CSRFIntegrationTest.java @@ -253,6 +253,7 @@ public class CSRFIntegrationTest extends IntegrationTest { Overview[] assignments = RestAssured.given() .cookie("JSESSIONID", getWebGoatCookie()) + .relaxedHTTPSValidation() .get(url("service/lessonoverview.mvc")) .then() .extract() diff --git a/src/it/java/org/owasp/webgoat/IntegrationTest.java b/src/it/java/org/owasp/webgoat/IntegrationTest.java index 2694b56a7..06a626047 100644 --- a/src/it/java/org/owasp/webgoat/IntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/IntegrationTest.java @@ -5,7 +5,6 @@ import static io.restassured.RestAssured.given; import io.restassured.RestAssured; import io.restassured.http.ContentType; import java.util.Map; -import java.util.Objects; import lombok.Getter; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; @@ -15,23 +14,26 @@ import org.springframework.http.HttpStatus; public abstract class IntegrationTest { - private static String webGoatPort = - Objects.requireNonNull(System.getProperty("webgoatport", "8080")); + private static String webGoatPort = System.getenv().getOrDefault("WEBGOAT_PORT", "8080"); private static String webGoatContext = - Objects.requireNonNull(System.getProperty("webgoatcontext", "/WebGoat/")); + System.getenv().getOrDefault("WEBGOAT_CONTEXT", "/WebGoat/"); + + @Getter private static String webWolfPort = System.getenv().getOrDefault("WEBWOLF_PORT", "9090"); @Getter - private static String webWolfPort = - Objects.requireNonNull(System.getProperty("webwolfport", "9090")); + private static String webWolfHost = System.getenv().getOrDefault("WEBWOLF_HOST", "127.0.0.1"); + + @Getter + private static String webGoatHost = System.getenv().getOrDefault("WEBGOAT_HOST", "127.0.0.1"); private static String webWolfContext = - Objects.requireNonNull(System.getProperty("webwolfcontext", "/WebWolf/")); + System.getenv().getOrDefault("WEBWOLF_CONTEXT", "/WebWolf/"); - private static boolean useSSL = false; + private static boolean useSSL = + Boolean.valueOf(System.getenv().getOrDefault("WEBGOAT_SSLENABLED", "false")); private static String webgoatUrl = - (useSSL ? "https:" : "http:") + "//localhost:" + webGoatPort + webGoatContext; - private static String webWolfUrl = - (useSSL ? "https:" : "http:") + "//localhost:" + webWolfPort + webWolfContext; + (useSSL ? "https://" : "http://") + webGoatHost + ":" + webGoatPort + webGoatContext; + private static String webWolfUrl = "http://" + webWolfHost + ":" + webWolfPort + webWolfContext; @Getter private String webGoatCookie; @Getter private String webWolfCookie; @Getter private final String user = "webgoat"; diff --git a/src/it/java/org/owasp/webgoat/PasswordResetLessonIntegrationTest.java b/src/it/java/org/owasp/webgoat/PasswordResetLessonIntegrationTest.java index 8c7018c59..f3b700b9a 100644 --- a/src/it/java/org/owasp/webgoat/PasswordResetLessonIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/PasswordResetLessonIntegrationTest.java @@ -69,7 +69,6 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest { // WebWolf var link = getPasswordResetLinkFromLandingPage(); - // WebGoat changePassword(link); checkAssignment( @@ -137,7 +136,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest { private void clickForgotEmailLink(String user) { RestAssured.given() .when() - .header(HttpHeaders.HOST, String.format("%s:%s", "127.0.0.1", getWebWolfPort())) + .header(HttpHeaders.HOST, String.format("%s:%s", getWebWolfHost(), getWebWolfPort())) .relaxedHTTPSValidation() .cookie("JSESSIONID", getWebGoatCookie()) .formParams("email", user) diff --git a/src/main/java/org/owasp/webgoat/container/asciidoc/WebWolfMacro.java b/src/main/java/org/owasp/webgoat/container/asciidoc/WebWolfMacro.java index 8456d6dbe..119fd9269 100644 --- a/src/main/java/org/owasp/webgoat/container/asciidoc/WebWolfMacro.java +++ b/src/main/java/org/owasp/webgoat/container/asciidoc/WebWolfMacro.java @@ -1,12 +1,9 @@ package org.owasp.webgoat.container.asciidoc; -import jakarta.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; import org.asciidoctor.ast.ContentNode; import org.asciidoctor.extension.InlineMacroProcessor; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; /** * Usage in asciidoc: @@ -26,7 +23,7 @@ public class WebWolfMacro extends InlineMacroProcessor { @Override public Object process(ContentNode contentNode, String linkText, Map attributes) { var env = EnvironmentExposure.getEnv(); - var hostname = determineHost(env.getProperty("webwolf.port")); + var hostname = env.getProperty("webwolf.url"); var target = (String) attributes.getOrDefault("target", "home"); var href = hostname + "/" + target; @@ -45,29 +42,4 @@ public class WebWolfMacro extends InlineMacroProcessor { private boolean displayCompleteLinkNoFormatting(Map attributes) { return attributes.values().stream().anyMatch(a -> a.equals("noLink")); } - - /** - * Determine the host from the hostname and ports that were used. The purpose is to make it - * possible to use the application behind a reverse proxy. For instance in the docker - * compose/stack version with webgoat webwolf and nginx proxy. You do not have to use the - * indicated hostname, but if you do, you should define two hosts aliases 127.0.0.1 - * www.webgoat.local www.webwolf.local - */ - private String determineHost(String port) { - HttpServletRequest request = - ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); - String host = request.getHeader("Host"); - int semicolonIndex = host.indexOf(":"); - if (semicolonIndex == -1 || host.endsWith(":80")) { - host = host.replace(":80", "").replace("www.webgoat.local", "www.webwolf.local"); - } else { - host = host.substring(0, semicolonIndex); - host = host.concat(":").concat(port); - } - return "http://" + host + (includeWebWolfContext() ? "/WebWolf" : ""); - } - - protected boolean includeWebWolfContext() { - return true; - } } diff --git a/src/main/java/org/owasp/webgoat/container/asciidoc/WebWolfRootMacro.java b/src/main/java/org/owasp/webgoat/container/asciidoc/WebWolfRootMacro.java index 58b12e547..7044e125c 100644 --- a/src/main/java/org/owasp/webgoat/container/asciidoc/WebWolfRootMacro.java +++ b/src/main/java/org/owasp/webgoat/container/asciidoc/WebWolfRootMacro.java @@ -17,9 +17,4 @@ public class WebWolfRootMacro extends WebWolfMacro { public WebWolfRootMacro(String macroName, Map config) { super(macroName, config); } - - @Override - protected boolean includeWebWolfContext() { - return false; - } } diff --git a/src/main/java/org/owasp/webgoat/server/StartupMessage.java b/src/main/java/org/owasp/webgoat/server/StartupMessage.java index ecc52bc19..7273ed77b 100644 --- a/src/main/java/org/owasp/webgoat/server/StartupMessage.java +++ b/src/main/java/org/owasp/webgoat/server/StartupMessage.java @@ -17,6 +17,11 @@ public class StartupMessage { private String address; private String contextPath; + private String applicationName; + + private static boolean useSSL = + Boolean.valueOf(System.getenv().getOrDefault("WEBGOAT_SSLENABLED", "true")); + @EventListener void onStartup(ApplicationReadyEvent event) { @@ -24,9 +29,24 @@ public class StartupMessage { address = event.getApplicationContext().getEnvironment().getProperty("server.address"); contextPath = event.getApplicationContext().getEnvironment().getProperty("server.servlet.context-path"); - if (StringUtils.hasText(port) - && !StringUtils.hasText(System.getProperty("running.in.docker"))) { - log.warn("Please browse to http://{}:{}{} to get started...", address, port, contextPath); + applicationName = + event.getApplicationContext().getEnvironment().getProperty("spring.application.name"); + if (StringUtils.hasText(applicationName)) { + if (applicationName.equals("WebGoat")) { + log.warn( + "Please browse to " + + (useSSL ? "https://" : "http://") + + "{}:{}{} to start using WebGoat...", + event.getApplicationContext().getEnvironment().getProperty("webgoat.host"), + port, + contextPath); + } else { + log.warn( + "Please browse to http://{}:{}{} to start using WebWolf...", + event.getApplicationContext().getEnvironment().getProperty("webwolf.host"), + port, + contextPath); + } } } diff --git a/src/main/resources/application-webgoat.properties b/src/main/resources/application-webgoat.properties index 5d7ecf66f..aefde2765 100644 --- a/src/main/resources/application-webgoat.properties +++ b/src/main/resources/application-webgoat.properties @@ -1,9 +1,9 @@ server.error.include-stacktrace=always server.error.path=/error.html -server.servlet.context-path=${webgoat.context} +server.servlet.context-path=${WEBGOAT_CONTEXT:/WebGoat} server.servlet.session.persistent=false -server.port=${webgoat.port} -server.address=${webgoat.host} +server.port=${WEBGOAT_PORT:8080} +server.address=0.0.0.0 webgoat.host=${WEBGOAT_HOST:127.0.0.1} webgoat.port=${WEBGOAT_PORT:8080} webgoat.context=${WEBGOAT_CONTEXT:/WebGoat} @@ -47,7 +47,7 @@ webgoat.default.language=en webwolf.host=${WEBWOLF_HOST:127.0.0.1} webwolf.port=${WEBWOLF_PORT:9090} webwolf.context=${WEBWOLF_CONTEXT:/WebWolf} -webwolf.url=http://${webwolf.host}:${webwolf.port}${webwolf.context} +webwolf.url=http://${WEBWOLF_HOST:127.0.0.1}:${WEBWOLF_PORT:9090}${WEBWOLF_CONTEXT:/WebWolf} webwolf.landingpage.url=${webwolf.url}/landing webwolf.mail.url=${webwolf.url}/mail diff --git a/src/main/resources/application-webwolf.properties b/src/main/resources/application-webwolf.properties index 4d450fc90..986a70b80 100644 --- a/src/main/resources/application-webwolf.properties +++ b/src/main/resources/application-webwolf.properties @@ -1,8 +1,8 @@ server.error.include-stacktrace=always server.error.path=/error.html server.servlet.context-path=${webwolf.context} -server.port=${webwolf.port} -server.address=${webwolf.host} +server.port=${WEBWOLF_PORT:9090} +server.address=0.0.0.0 spring.application.name=WebWolf webwolf.host=${WEBWOLF_HOST:127.0.0.1}