From ff530e926e5c81eb26c114bced9614bdd886c26d Mon Sep 17 00:00:00 2001
From: Nanne Baars
Date: Sun, 25 Aug 2019 17:43:14 +0200
Subject: [PATCH] Use separate project for integration tests so we can start
WebGoat and WebWolf
---
pom.xml | 1 +
.../main/java/org/owasp/webgoat/WebGoat.java | 20 +-
.../owasp/webgoat/lessons/AbstractLesson.java | 2 +-
.../org/owasp/webgoat/lessons/Category.java | 52 ++---
.../owasp/webgoat/lessons/LessonAdapter.java | 2 +-
.../org/owasp/webgoat/users/UserForm.java | 2 +-
...perties => application-webgoat.properties} | 0
.../org/owasp/webgoat/plugins/LessonTest.java | 2 +-
webgoat-integration-tests/pom.xml | 66 ++++++
.../org/owasp/webgoat/GeneralLessonTest.java | 127 +++++++++++
.../org/owasp/webgoat/IntegrationTest.java | 200 ++++++++++++++++++
.../webgoat/PasswordResetLessonTest.java | 76 +++++++
.../webgoat/SqlInjectionAdvancedTest.java | 49 +++++
.../owasp/webgoat/SqlInjectionLessonTest.java | 82 +++++++
.../webgoat/SqlInjectionMitigationTest.java | 76 +++----
.../src/test/resources/logback-test.xml | 15 ++
.../ResetLinkAssignmentForgotPassword.java | 99 +++++----
.../resources/i18n/WebGoatLabels.properties | 2 +
webgoat-server/pom.xml | 27 ++-
.../java/org/owasp/webgoat/StartWebGoat.java | 10 +-
.../org/owasp/webgoat/General_TestHelper.java | 137 ------------
.../SqlInjectionAdvanced_TestHelper.java | 48 -----
.../webgoat/SqlInjection_TestHelper.java | 80 -------
.../java/org/owasp/webgoat/TestHelper.java | 118 -----------
.../owasp/webgoat/WebGoatIntegrationTest.java | 162 --------------
webwolf/pom.xml | 16 ++
.../main/java/org/owasp/webwolf/WebWolf.java | 15 +-
.../java/org/owasp/webwolf/mailbox/Email.java | 1 +
.../org/owasp/webwolf/requests/Requests.java | 2 +-
.../requests/WebWolfTraceRepository.java | 21 +-
.../java/org/owasp/webwolf/user/UserForm.java | 2 +-
.../owasp/webwolf/user/WebGoatUserCookie.java | 22 --
...perties => application-webwolf.properties} | 1 +
33 files changed, 793 insertions(+), 742 deletions(-)
rename webgoat-container/src/main/resources/{application.properties => application-webgoat.properties} (100%)
create mode 100644 webgoat-integration-tests/pom.xml
create mode 100644 webgoat-integration-tests/src/test/java/org/owasp/webgoat/GeneralLessonTest.java
create mode 100644 webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java
create mode 100644 webgoat-integration-tests/src/test/java/org/owasp/webgoat/PasswordResetLessonTest.java
create mode 100644 webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionAdvancedTest.java
create mode 100644 webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionLessonTest.java
rename webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionMitigation_TestHelper.java => webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionMitigationTest.java (65%)
create mode 100644 webgoat-integration-tests/src/test/resources/logback-test.xml
delete mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java
delete mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java
delete mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/SqlInjection_TestHelper.java
delete mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java
delete mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/WebGoatIntegrationTest.java
delete mode 100644 webwolf/src/main/java/org/owasp/webwolf/user/WebGoatUserCookie.java
rename webwolf/src/main/resources/{application.properties => application-webwolf.properties} (98%)
diff --git a/pom.xml b/pom.xml
index c82018731..7036fabab 100644
--- a/pom.xml
+++ b/pom.xml
@@ -143,6 +143,7 @@
webgoat-lessons
webgoat-server
webwolf
+ webgoat-integration-tests
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java
index e18374c23..131c482ab 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java
@@ -30,7 +30,6 @@
*/
package org.owasp.webgoat;
-import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.plugins.PluginEndpointPublisher;
import org.owasp.webgoat.plugins.PluginsLoader;
import org.owasp.webgoat.session.Course;
@@ -38,30 +37,17 @@ import org.owasp.webgoat.session.UserSessionData;
import org.owasp.webgoat.session.WebSession;
import org.owasp.webgoat.session.WebgoatContext;
import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.web.client.RestTemplate;
import java.io.File;
-@SpringBootApplication
-@Slf4j
-public class WebGoat extends SpringBootServletInitializer {
-
- @Override
- protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
- return application.sources(WebGoat.class);
- }
-
- public static void main(String[] args) throws Exception {
- SpringApplication.run(WebGoat.class, args);
- }
+@Configuration
+public class WebGoat {
@Bean(name = "pluginTargetDirectory")
public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) {
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java
index 1336fa326..16eca3f45 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java
@@ -58,7 +58,7 @@ public abstract class AbstractLesson extends Screen implements Comparable
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java
index 1e0c44000..38d6b3947 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java
@@ -16,7 +16,7 @@ import javax.validation.constraints.Size;
public class UserForm {
@NotNull
- @Size(min=6, max=20)
+ @Size(min=6, max=40)
@Pattern(regexp = "[a-z0-9-]*", message = "can only contain lowercase letters, digits, and -")
private String username;
@NotNull
diff --git a/webgoat-container/src/main/resources/application.properties b/webgoat-container/src/main/resources/application-webgoat.properties
similarity index 100%
rename from webgoat-container/src/main/resources/application.properties
rename to webgoat-container/src/main/resources/application-webgoat.properties
diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java
index 3e6dffe9e..cd59ab8d9 100644
--- a/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java
+++ b/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java
@@ -22,7 +22,7 @@ import static org.mockito.Mockito.when;
* @since 5/20/17.
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
-@TestPropertySource(locations = "classpath:/application-test.properties")
+@TestPropertySource(locations = {"classpath:/application-webgoat.properties", "classpath:/application-test.properties"})
public abstract class LessonTest {
@LocalServerPort
diff --git a/webgoat-integration-tests/pom.xml b/webgoat-integration-tests/pom.xml
new file mode 100644
index 000000000..de8e86b47
--- /dev/null
+++ b/webgoat-integration-tests/pom.xml
@@ -0,0 +1,66 @@
+
+ 4.0.0
+ webgoat-integration-tests
+ jar
+
+ org.owasp.webgoat
+ webgoat-parent
+ v8.0.0-SNAPSHOT
+
+
+
+
+ org.owasp.webgoat
+ webgoat-server
+ ${project.version}
+
+
+ org.owasp.webgoat
+ webgoat-server
+ ${project.version}
+ internal
+
+
+ org.owasp.webgoat
+ webwolf
+ ${project.version}
+ internal
+
+
+ org.owasp.webgoat
+ webwolf
+ ${project.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ io.rest-assured
+ rest-assured
+ 4.0.0
+ test
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+ 0
+ true
+
+ --illegal-access=permit
+
+
+
+
+
+
+
diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/GeneralLessonTest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/GeneralLessonTest.java
new file mode 100644
index 000000000..80dfbc496
--- /dev/null
+++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/GeneralLessonTest.java
@@ -0,0 +1,127 @@
+package org.owasp.webgoat;
+
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+public class GeneralLessonTest extends IntegrationTest {
+
+ @Test
+ public void httpBasics() {
+ startLesson("HttpBasics");
+ Map params = new HashMap<>();
+ params.clear();
+ params.put("person", "goatuser");
+ checkAssignment(url("HttpBasics/attack1"), params, true);
+
+ params.clear();
+ params.put("answer", "POST");
+ params.put("magic_answer", "33");
+ params.put("magic_num", "4");
+ checkAssignment(url("HttpBasics/attack2"), params, false);
+
+ params.clear();
+ params.put("answer", "POST");
+ params.put("magic_answer", "33");
+ params.put("magic_num", "33");
+ checkAssignment(url("HttpBasics/attack2"), params, true);
+
+ checkResults("/HttpBasics/");
+ }
+
+ @Test
+ public void httpProxies() {
+ startLesson("HttpProxies");
+ Assert.assertThat(RestAssured.given()
+ .when().config(restConfig).cookie("JSESSIONID", getWebGoatCookie()).header("x-request-intercepted", "true")
+ .contentType(ContentType.JSON)
+ .get(url("HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
+ .then()
+ .statusCode(200).extract().path("lessonCompleted"), CoreMatchers.is(true));
+
+ checkResults("/HttpProxies/");
+ }
+
+ @Test
+ public void cia() {
+ startLesson("CIA");
+ Map params = new HashMap<>();
+ params.clear();
+ params.put("question_0_solution", "Solution 3: By stealing a database where names and emails are stored and uploading it to a website.");
+ params.put("question_1_solution", "Solution 1: By changing the names and emails of one or more users stored in a database.");
+ params.put("question_2_solution", "Solution 4: By launching a denial of service attack on the servers.");
+ params.put("question_3_solution", "Solution 2: The systems security is compromised even if only one goal is harmed.");
+ checkAssignment(url("/WebGoat/cia/quiz"), params, true);
+ checkResults("/cia/");
+
+ }
+
+ @Test
+ public void securePasswords() {
+ startLesson("SecurePasswords");
+ Map params = new HashMap<>();
+ params.clear();
+ params.put("password", "ajnaeliclm^&&@kjn.");
+ checkAssignment(url("/WebGoat/SecurePasswords/assignment"), params, true);
+ checkResults("SecurePasswords/");
+
+ startLesson("AuthBypass");
+ params.clear();
+ params.put("secQuestion2", "John");
+ params.put("secQuestion3", "Main");
+ params.put("jsEnabled", "1");
+ params.put("verifyMethod", "SEC_QUESTIONS");
+ params.put("userId", "12309746");
+ checkAssignment(url("/WebGoat/auth-bypass/verify-account"), params, true);
+ checkResults("/auth-bypass/");
+
+ startLesson("HttpProxies");
+ Assert.assertThat(RestAssured.given().when().config(restConfig).cookie("JSESSIONID", getWebGoatCookie()).header("x-request-intercepted", "true")
+ .contentType(ContentType.JSON)
+ .get(url("/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily")).then()
+ .statusCode(200).extract().path("lessonCompleted"), CoreMatchers.is(true));
+ checkResults("/HttpProxies/");
+
+ }
+
+ @Test
+ public void chrome() {
+ startLesson("ChromeDevTools");
+
+ Map params = new HashMap<>();
+ params.clear();
+ params.put("param1", "42");
+ params.put("param2", "24");
+
+ String result =
+ RestAssured.given()
+ .when()
+ .config(restConfig)
+ .cookie("JSESSIONID", getWebGoatCookie())
+ .header("webgoat-requested-by", "dom-xss-vuln")
+ .header("X-Requested-With", "XMLHttpRequest")
+ .formParams(params)
+ .post(url("/WebGoat/CrossSiteScripting/phone-home-xss"))
+ .then()
+ .statusCode(200)
+ .extract().path("output");
+ String secretNumber = result.substring("phoneHome Response is ".length());
+
+ params.clear();
+ params.put("successMessage", secretNumber);
+ checkAssignment(url("/WebGoat/ChromeDevTools/dummy"), params, true);
+
+ params.clear();
+ params.put("number", "24");
+ params.put("network_num", "24");
+ checkAssignment(url("/WebGoat/ChromeDevTools/network"), params, true);
+
+ checkResults("/ChromeDevTools/");
+ }
+}
diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java
new file mode 100644
index 000000000..f26dec4f3
--- /dev/null
+++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java
@@ -0,0 +1,200 @@
+package org.owasp.webgoat;
+
+import io.restassured.RestAssured;
+import io.restassured.config.RestAssuredConfig;
+import io.restassured.config.SSLConfig;
+import lombok.Getter;
+import org.hamcrest.CoreMatchers;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.owasp.webwolf.WebWolf;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.Map;
+import java.util.UUID;
+
+public abstract class IntegrationTest {
+
+ private static String WEBGOAT_URL = "http://localhost:8080/WebGoat/";
+ private static String WEBWOLF_URL = "http://localhost:9090/";
+
+ //This also allows to test the application with HTTPS when outside testing option is used
+ protected static RestAssuredConfig restConfig = RestAssuredConfig.newConfig().sslConfig(new SSLConfig().relaxedHTTPSValidation());
+
+ @Getter
+ private String webGoatCookie;
+ @Getter
+ private String webWolfCookie;
+ @Getter
+ private String webgoatUser = UUID.randomUUID().toString();
+
+ private static boolean started = false;
+
+ @BeforeClass
+ public static void beforeAll() {
+ if (!started) {
+ started = true;
+ if (!areAlreadyRunning()) {
+ SpringApplicationBuilder wgs = new SpringApplicationBuilder(StartWebGoat.class)
+ .properties(Map.of("spring.config.name", "application-webgoat"));
+ wgs.run();
+ SpringApplicationBuilder wws = new SpringApplicationBuilder(WebWolf.class)
+ .properties(Map.of("spring.config.name", "application-webwolf"));
+ wws.run();
+ }
+ }
+ }
+
+ private static boolean areAlreadyRunning() {
+ return checkIfServerIsRunnningOn(9090) && checkIfServerIsRunnningOn(8080);
+ }
+
+ private static boolean checkIfServerIsRunnningOn(int port) {
+ try (var ignored = new ServerSocket(port)) {
+ return false;
+ } catch (IOException e) {
+ return true;
+ }
+ }
+
+ protected String url(String url) {
+ url = url.replaceFirst("/WebGoat/", "");
+ url = url.replaceFirst("/WebGoat", "");
+ url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
+ return WEBGOAT_URL + url;
+ }
+
+ protected String webWolfUrl(String url) {
+ url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
+ return WEBWOLF_URL + url;
+ }
+
+ @Before
+ public void login() {
+ webGoatCookie = RestAssured.given()
+ .when()
+ .config(restConfig)
+ .formParam("username", webgoatUser)
+ .formParam("password", "password")
+ .formParam("matchingPassword", "password")
+ .formParam("agree", "agree")
+ .post(url("register.mvc"))
+ .then()
+ .cookie("JSESSIONID")
+ .statusCode(302)
+ .extract()
+ .cookie("JSESSIONID");
+
+ webWolfCookie = RestAssured.given()
+ .when()
+ .config(restConfig)
+ .formParam("username", webgoatUser)
+ .formParam("password", "password")
+ .post(WEBWOLF_URL + "login")
+ .then()
+ .cookie("WEBWOLFSESSION")
+ .statusCode(302)
+ .extract()
+ .cookie("WEBWOLFSESSION");
+ }
+
+ @After
+ public void logout() {
+ RestAssured.given()
+ .when()
+ .config(restConfig)
+ .get(WEBGOAT_URL + "logout")
+ .then()
+ .statusCode(200);
+ }
+
+ /**
+ * At start of a lesson. The .lesson.lesson is visited and the lesson is reset.
+ *
+ * @param lessonName
+ */
+ public void startLesson(String lessonName) {
+ RestAssured.given()
+ .when()
+ .config(restConfig)
+ .cookie("JSESSIONID", getWebGoatCookie())
+ .get(url(lessonName + ".lesson.lesson"))
+ .then()
+ .statusCode(200);
+
+ RestAssured.given()
+ .when()
+ .config(restConfig)
+ .cookie("JSESSIONID", getWebGoatCookie())
+ .get(url("service/restartlesson.mvc"))
+ .then()
+ .statusCode(200);
+ }
+
+ /**
+ * Helper method for most common type of test.
+ * POST with parameters.
+ * Checks for 200 and lessonCompleted as indicated by expectedResult
+ *
+ * @param url
+ * @param params
+ * @param expectedResult
+ */
+ public void checkAssignment(String url, Map params, boolean expectedResult) {
+ Assert.assertThat(
+ RestAssured.given()
+ .when()
+ .config(restConfig)
+ .cookie("JSESSIONID", getWebGoatCookie())
+ .formParams(params)
+ .post(url)
+ .then()
+ .statusCode(200)
+ .extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
+ }
+
+ /**
+ * Helper method for most common type of test.
+ * PUT with parameters.
+ * Checks for 200 and lessonCompleted as indicated by expectedResult
+ *
+ * @param url
+ * @param params
+ * @param expectedResult
+ */
+ public void checkAssignmentWithPUT(String url, Map params, boolean expectedResult) {
+ Assert.assertThat(
+ RestAssured.given()
+ .when()
+ .config(restConfig)
+ .cookie("JSESSIONID", getWebGoatCookie())
+ .formParams(params)
+ .put(url)
+ .then()
+ .statusCode(200)
+ .extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
+ }
+
+ public void checkResults(String prefix) {
+ Assert.assertThat(RestAssured.given()
+ .when()
+ .config(restConfig)
+ .cookie("JSESSIONID", getWebGoatCookie())
+ .get(url("service/lessonoverview.mvc"))
+ .then()
+ .statusCode(200).extract().jsonPath().getList("solved"), CoreMatchers.everyItem(CoreMatchers.is(true)));
+
+ Assert.assertThat(RestAssured.given()
+ .when()
+ .config(restConfig)
+ .cookie("JSESSIONID", getWebGoatCookie())
+ .get(url("service/lessonoverview.mvc"))
+ .then()
+ .statusCode(200).extract().jsonPath().getList("assignment.path"), CoreMatchers.everyItem(CoreMatchers.startsWith(prefix)));
+
+ }
+}
diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/PasswordResetLessonTest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/PasswordResetLessonTest.java
new file mode 100644
index 000000000..ebe2b210a
--- /dev/null
+++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/PasswordResetLessonTest.java
@@ -0,0 +1,76 @@
+package org.owasp.webgoat;
+
+import io.restassured.RestAssured;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+import java.util.Map;
+
+public class PasswordResetLessonTest extends IntegrationTest {
+
+ @Test
+ public void solveAssignment() {
+ //WebGoat
+ startLesson("PasswordReset");
+ clickForgotEmailLink("tom@webgoat-cloud.org");
+
+ //WebWolf
+ var link = getPasswordResetLinkFromLandingPage();
+
+ //WebGoat
+ changePassword(link);
+ checkAssignment(url("PasswordReset/reset/login"), Map.of("email", "tom@webgoat-cloud.org", "password", "123456"), true);
+ }
+
+ @Test
+ public void sendEmailShouldBeAvailabeInWebWolf() {
+ startLesson("PasswordReset");
+ clickForgotEmailLink(getWebgoatUser() + "@webgoat.org");
+
+ var responseBody = RestAssured.given()
+ .when()
+ .config(restConfig)
+ .cookie("WEBWOLFSESSION", getWebWolfCookie())
+ .get(webWolfUrl("/WebWolf/mail"))
+ .then()
+ .extract().response().getBody().asString();
+
+ Assertions.assertThat(responseBody).contains("Hi, you requested a password reset link");
+ }
+
+ private void changePassword(String link) {
+ RestAssured.given()
+ .when()
+ .config(restConfig)
+ .cookie("JSESSIONID", getWebGoatCookie())
+ .formParams("resetLink", link, "password", "123456")
+ .post(url("PasswordReset/reset/change-password"))
+ .then()
+ .statusCode(200);
+ }
+
+ private String getPasswordResetLinkFromLandingPage() {
+ var responseBody = RestAssured.given()
+ .when()
+ .config(restConfig)
+ .cookie("WEBWOLFSESSION", getWebWolfCookie())
+ .get(webWolfUrl("WebWolf/requests"))
+ .then()
+ .extract().response().getBody().asString();
+ int startIndex = responseBody.lastIndexOf("\"path\" : \"/PasswordReset/reset/reset-password/");
+ var link = responseBody.substring(startIndex + "\"path\" : \"/PasswordReset/reset/reset-password/".length(), responseBody.indexOf(",", startIndex) - 1);
+ return link;
+ }
+
+ private void clickForgotEmailLink(String user) {
+ RestAssured.given()
+ .when()
+ .header("host", "localhost:9090")
+ .config(restConfig)
+ .cookie("JSESSIONID", getWebGoatCookie())
+ .formParams("email", user)
+ .post(url("PasswordReset/ForgotPassword/create-password-reset-link"))
+ .then()
+ .statusCode(200);
+ }
+}
diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionAdvancedTest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionAdvancedTest.java
new file mode 100644
index 000000000..5bb9b5bcf
--- /dev/null
+++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionAdvancedTest.java
@@ -0,0 +1,49 @@
+package org.owasp.webgoat;
+
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class SqlInjectionAdvancedTest extends IntegrationTest {
+
+ @Test
+ public void runTests() {
+ startLesson("SqlInjectionAdvanced");
+
+ Map params = new HashMap<>();
+ params.clear();
+ params.put("username_reg", "tom' AND substring(password,1,1)='t");
+ params.put("password_reg", "password");
+ params.put("email_reg", "someone@microsoft.com");
+ params.put("confirm_password", "password");
+ checkAssignmentWithPUT(url("/WebGoat/SqlInjectionAdvanced/challenge"), params, true);
+
+ params.clear();
+ params.put("username_login", "tom");
+ params.put("password_login", "thisisasecretfortomonly");
+ checkAssignment(url("/WebGoat/SqlInjectionAdvanced/challenge_Login"), params, true);
+
+ params.clear();
+ params.put("userid_6a", "'; SELECT * FROM user_system_data;--");
+ checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true);
+
+ params.clear();
+ params.put("userid_6a", "Smith' union select userid,user_name, user_name,user_name,password,cookie,userid from user_system_data --");
+ checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true);
+
+ params.clear();
+ params.put("userid_6b", "passW0rD");
+ checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6b"), params, true);
+
+ params.clear();
+ params.put("question_0_solution", "Solution 4: A statement has got values instead of a prepared statement");
+ params.put("question_1_solution", "Solution 3: ?");
+ params.put("question_2_solution", "Solution 2: Prepared statements are compiled once by the database management system waiting for input and are pre-compiled this way.");
+ params.put("question_3_solution", "Solution 3: Placeholders can prevent that the users input gets attached to the SQL query resulting in a seperation of code and data.");
+ params.put("question_4_solution", "Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'.");
+ checkAssignment(url("/WebGoat/SqlInjectionAdvanced/quiz"), params, true);
+
+ checkResults("/SqlInjectionAdvanced/");
+ }
+}
diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionLessonTest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionLessonTest.java
new file mode 100644
index 000000000..941b088e6
--- /dev/null
+++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionLessonTest.java
@@ -0,0 +1,82 @@
+package org.owasp.webgoat;
+
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class SqlInjectionLessonTest extends IntegrationTest {
+
+ private static final String sql_2 = "select department from employees where last_name='Franco'";
+ private static final String sql_3 = "update employees set department='Sales' where last_name='Barnett'";
+ private static final String sql_4_drop = "alter table employees drop column phone";
+ private static final String sql_4_add = "alter table employees add column phone varchar(20)";
+ private static final String sql_5 = "grant alter table to UnauthorizedUser";
+ private static final String sql_9_account = " ' ";
+ private static final String sql_9_operator = "or";
+ private static final String sql_9_injection = "'1'='1";
+ private static final String sql_10_login_count = "2";
+ private static final String sql_10_userid = "1 or 1=1";
+
+ private static final String sql_11_a = "Smith' or '1' = '1";
+ private static final String sql_11_b = "3SL99A' or '1'='1";
+
+ private static final String sql_12_a = "Smith";
+ private static final String sql_12_b = "3SL99A' ; update employees set salary= '100000' where last_name='Smith";
+
+ private static final String sql_13 = "%update% '; drop table access_log ; --'";
+
+ @Test
+ public void runTests() {
+ startLesson("SqlInjection");
+
+ Map params = new HashMap<>();
+ params.clear();
+ params.put("query", sql_2);
+ checkAssignment(url("/WebGoat/SqlInjection/attack2"), params, true);
+
+ params.clear();
+ params.put("query", sql_3);
+ checkAssignment(url("/WebGoat/SqlInjection/attack3"), params, true);
+
+ params.clear();
+ params.put("query", sql_4_drop);
+ checkAssignment(url("/WebGoat/SqlInjection/attack4"), params, false);
+
+ params.clear();
+ params.put("query", sql_4_add);
+ checkAssignment(url("/WebGoat/SqlInjection/attack4"), params, true);
+
+ params.clear();
+ params.put("query", sql_5);
+ checkAssignment(url("/WebGoat/SqlInjection/attack5"), params, true);
+
+ params.clear();
+ params.put("operator", sql_9_operator);
+ params.put("account", sql_9_account);
+ params.put("injection", sql_9_injection);
+ checkAssignment(url("/WebGoat/SqlInjection/assignment5a"), params, true);
+
+ params.clear();
+ params.put("login_count", sql_10_login_count);
+ params.put("userid", sql_10_userid);
+ checkAssignment(url("/WebGoat/SqlInjection/assignment5b"), params, true);
+
+ params.clear();
+ params.put("name", sql_11_a);
+ params.put("auth_tan", sql_11_b);
+ checkAssignment(url("/WebGoat/SqlInjection/attack8"), params, true);
+
+ params.clear();
+ params.put("name", sql_12_a);
+ params.put("auth_tan", sql_12_b);
+ checkAssignment(url("/WebGoat/SqlInjection/attack9"), params, true);
+
+ params.clear();
+ params.put("action_string", sql_13);
+ checkAssignment(url("/WebGoat/SqlInjection/attack10"), params, true);
+
+ checkResults("/SqlInjection/");
+
+ }
+}
diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionMitigation_TestHelper.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionMitigationTest.java
similarity index 65%
rename from webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionMitigation_TestHelper.java
rename to webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionMitigationTest.java
index 70389dee2..d51af280c 100644
--- a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionMitigation_TestHelper.java
+++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionMitigationTest.java
@@ -1,37 +1,39 @@
-package org.owasp.webgoat;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class SqlInjectionMitigation_TestHelper extends TestHelper {
-
- public void runTests(String webgoatURL, String cookie) {
-
- startLesson(cookie, webgoatURL, "SqlInjectionMitigations");
-
- Map params = new HashMap<>();
- params.clear();
- params.put("field1", "getConnection");
- params.put("field2", "PreparedStatement prep");
- params.put("field3", "prepareStatement");
- params.put("field4", "?");
- params.put("field5", "?");
- params.put("field6", "prep.setString(1,\"\")");
- params.put("field7", "prep.setString(2,\\\"\\\")");
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionMitigations/attack10a", params, true);
-
- params.put("editor", "try {\r\n" +
- " Connection conn = DriverManager.getConnection(DBURL,DBUSER,DBPW);\r\n" +
- " PreparedStatement prep = conn.prepareStatement(\"select id from users where name = ?\");\r\n" +
- " prep.setString(1,\"me\");\r\n" +
- " prep.execute();\r\n" +
- " System.out.println(conn); //should output 'null'\r\n" +
- "} catch (Exception e) {\r\n" +
- " System.out.println(\"Oops. Something went wrong!\");\r\n" +
- "}");
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionMitigations/attack10b", params, true);
-
- //checkResults(cookie, webgoatURL, "/SqlInjectionMitigations/");
-
- }
-}
+package org.owasp.webgoat;
+
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class SqlInjectionMitigationTest extends IntegrationTest {
+
+ @Test
+ public void runTests() {
+ startLesson("SqlInjectionMitigations");
+
+ Map params = new HashMap<>();
+ params.clear();
+ params.put("field1", "getConnection");
+ params.put("field2", "PreparedStatement prep");
+ params.put("field3", "prepareStatement");
+ params.put("field4", "?");
+ params.put("field5", "?");
+ params.put("field6", "prep.setString(1,\"\")");
+ params.put("field7", "prep.setString(2,\\\"\\\")");
+ checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10a"), params, true);
+
+ params.put("editor", "try {\r\n" +
+ " Connection conn = DriverManager.getConnection(DBURL,DBUSER,DBPW);\r\n" +
+ " PreparedStatement prep = conn.prepareStatement(\"select id from users where name = ?\");\r\n" +
+ " prep.setString(1,\"me\");\r\n" +
+ " prep.execute();\r\n" +
+ " System.out.println(conn); //should output 'null'\r\n" +
+ "} catch (Exception e) {\r\n" +
+ " System.out.println(\"Oops. Something went wrong!\");\r\n" +
+ "}");
+ checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10b"), params, true);
+
+ //checkResults(webGoatCookie, webgoatURL, "/SqlInjectionMitigations/");
+
+ }
+}
diff --git a/webgoat-integration-tests/src/test/resources/logback-test.xml b/webgoat-integration-tests/src/test/resources/logback-test.xml
new file mode 100644
index 000000000..2ee84585a
--- /dev/null
+++ b/webgoat-integration-tests/src/test/resources/logback-test.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/ResetLinkAssignmentForgotPassword.java b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/ResetLinkAssignmentForgotPassword.java
index daceaa377..88bb7cd24 100644
--- a/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/ResetLinkAssignmentForgotPassword.java
+++ b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/ResetLinkAssignmentForgotPassword.java
@@ -7,7 +7,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
-import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@@ -17,69 +16,67 @@ import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.UUID;
+import static org.springframework.util.StringUtils.*;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
/**
* Part of the password reset assignment. Used to send the e-mail.
+ *
* @author nbaars
* @since 8/20/17.
*/
@AssignmentPath("/PasswordReset/ForgotPassword")
public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
- private final RestTemplate restTemplate;
- private final String webWolfMailURL;
+ private final RestTemplate restTemplate;
+ private final String webWolfMailURL;
- public ResetLinkAssignmentForgotPassword(RestTemplate restTemplate,
- @Value("${webwolf.url.mail}") String webWolfMailURL) {
- this.restTemplate = restTemplate;
- this.webWolfMailURL = webWolfMailURL;
- }
+ public ResetLinkAssignmentForgotPassword(RestTemplate restTemplate,
+ @Value("${webwolf.url.mail}") String webWolfMailURL) {
+ this.restTemplate = restTemplate;
+ this.webWolfMailURL = webWolfMailURL;
+ }
- @RequestMapping(method = POST, value = "/create-password-reset-link")
- @ResponseBody
- public AttackResult sendPasswordResetLink(@RequestParam String email, HttpServletRequest request, @CookieValue("JSESSIONID") String cookie) {
- String resetLink = UUID.randomUUID().toString();
- ResetLinkAssignment.resetLinks.add(resetLink);
- String host = request.getHeader("host");
- if (org.springframework.util.StringUtils.hasText(email)) {
- if (email.equals(ResetLinkAssignment.TOM_EMAIL) && host.contains("9090")) { //User indeed changed the host header.
- ResetLinkAssignment.userToTomResetLink.put(getWebSession().getUserName(), resetLink);
- fakeClickingLinkEmail(host, resetLink);
- } else {
+ @RequestMapping(method = POST, value = "/create-password-reset-link")
+ @ResponseBody
+ public AttackResult sendPasswordResetLink(@RequestParam String email, HttpServletRequest request) {
+ String resetLink = UUID.randomUUID().toString();
+ ResetLinkAssignment.resetLinks.add(resetLink);
+ String host = request.getHeader("host");
+ if (hasText(email)) {
+ if (email.equals(ResetLinkAssignment.TOM_EMAIL) && host.contains("9090")) { //User indeed changed the host header.
+ ResetLinkAssignment.userToTomResetLink.put(getWebSession().getUserName(), resetLink);
+ fakeClickingLinkEmail(host, resetLink);
+ } else {
+ try {
+ sendMailToUser(email, host, resetLink);
+ } catch (Exception e) {
+ return failed().output("E-mail can't be send. please try again.").build();
+ }
+ }
+ }
+ return success().feedback("email.send").feedbackArgs(email).build();
+ }
+
+ private void sendMailToUser(@RequestParam String email, String host, String resetLink) {
+ int index = email.indexOf("@");
+ String username = email.substring(0, index == -1 ? email.length() : index);
+ PasswordResetEmail mail = PasswordResetEmail.builder()
+ .title("Your password reset link")
+ .contents(String.format(ResetLinkAssignment.TEMPLATE, host, resetLink))
+ .sender("password-reset@webgoat-cloud.net")
+ .recipient(username).build();
+ this.restTemplate.postForEntity(webWolfMailURL, mail, Object.class);
+ }
+
+ private void fakeClickingLinkEmail(String host, String resetLink) {
try {
- sendMailToUser(email, host, resetLink);
- } catch(Exception e) { return failed().output("E-mail can't be send. please try again.").build(); }
- }
+ HttpHeaders httpHeaders = new HttpHeaders();
+ HttpEntity httpEntity = new HttpEntity(httpHeaders);
+ new RestTemplate().exchange(String.format("http://%s/PasswordReset/reset/reset-password/%s", host, resetLink), HttpMethod.GET, httpEntity, Void.class);
+ } catch (Exception e) {
+ //don't care
+ }
}
- return success().feedback("email.send").feedbackArgs(email).build();
- }
-
- private void sendMailToUser(@RequestParam String email, String host, String resetLink) {
- int index = email.indexOf("@");
- String username = email.substring(0, index == -1 ? email.length() : index);
- PasswordResetEmail mail = PasswordResetEmail.builder()
- .title("Your password reset link")
- .contents(String.format(ResetLinkAssignment.TEMPLATE, host, resetLink))
- .sender("password-reset@webgoat-cloud.net")
- .recipient(username)
- .time(LocalDateTime.now()).build();
- this.restTemplate.postForEntity(webWolfMailURL, mail, Object.class);
- }
-
- /**
- * We need to add the current cookie of the user otherwise we cannot distinguish in WebWolf for
- * which user we need to trace the incoming request. In normal situation this HOST will be in your
- * full control so every incoming request would be valid.
- */
- private void fakeClickingLinkEmail(String host, String resetLink) {
- try {
- HttpHeaders httpHeaders = new HttpHeaders();
- HttpEntity httpEntity = new HttpEntity(httpHeaders);
- new RestTemplate().exchange(String.format("http://%s/PasswordReset/reset/reset-password/%s", host, resetLink), HttpMethod.GET, httpEntity, Void.class);
- } catch (Exception e) {
- //don't care
- }
- }
}
diff --git a/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties
index 283ab18b4..2b88df6a4 100644
--- a/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties
+++ b/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties
@@ -9,6 +9,8 @@ password-questions-wrong-user=You need to find a different user you are logging
password-questions-unknown-user=User {0} is not a valid user.
password-questions-one-successful=You answered one question successfully please try another one.
+email.send=An e-mail has been send to {0}
+
password-reset-no-user=Please supply a valid e-mail address.
password-reset-solved=Congratulations you solved the assignment, please type in the following code in the e-mail field: {0}
password-reset-not-solved=Sorry but you did not redirect the reset link to WebWolf
diff --git a/webgoat-server/pom.xml b/webgoat-server/pom.xml
index 5c0ae93b2..312887d4c 100644
--- a/webgoat-server/pom.xml
+++ b/webgoat-server/pom.xml
@@ -139,17 +139,6 @@
secure-passwords
${project.version}
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- io.rest-assured
- rest-assured
- 4.0.0
- test
-
@@ -199,6 +188,22 @@
true
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.2
+
+
+ test-compile
+
+ jar
+
+
+ internal
+
+
+
+
diff --git a/webgoat-server/src/main/java/org/owasp/webgoat/StartWebGoat.java b/webgoat-server/src/main/java/org/owasp/webgoat/StartWebGoat.java
index 473114c0e..bf7b8a223 100644
--- a/webgoat-server/src/main/java/org/owasp/webgoat/StartWebGoat.java
+++ b/webgoat-server/src/main/java/org/owasp/webgoat/StartWebGoat.java
@@ -27,6 +27,11 @@ package org.owasp.webgoat;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.Import;
+
+import java.util.Map;
/**
* Main entry point, this project is here to get all the lesson jars included to the final jar file
@@ -36,10 +41,11 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
*/
@SpringBootApplication
@Slf4j
-public class StartWebGoat {
+public class StartWebGoat extends SpringBootServletInitializer {
public static void main(String[] args) {
log.info("Starting WebGoat with args: {}", args);
- SpringApplication.run(WebGoat.class, args);
+ System.setProperty("spring.config.name", "application-webgoat");
+ SpringApplication.run(StartWebGoat.class, args);
}
}
diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java
deleted file mode 100644
index 694084f50..000000000
--- a/webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package org.owasp.webgoat;
-
-import static io.restassured.RestAssured.given;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import io.restassured.http.ContentType;
-
-
-public class General_TestHelper extends TestHelper {
-
-
- public void httpBasics(String webgoatURL, String cookie) {
-
- startLesson(cookie, webgoatURL, "HttpBasics");
- Map params = new HashMap<>();
- params.clear();
- params.put("person", "goatuser");
- checkAssignment(cookie, webgoatURL+"/WebGoat/HttpBasics/attack1", params, true);
-
- params.clear();
- params.put("answer", "POST");
- params.put("magic_answer", "33");
- params.put("magic_num", "4");
- checkAssignment(cookie, webgoatURL+"/WebGoat/HttpBasics/attack2", params, false);
-
- params.clear();
- params.put("answer", "POST");
- params.put("magic_answer", "33");
- params.put("magic_num", "33");
- checkAssignment(cookie, webgoatURL+"/WebGoat/HttpBasics/attack2", params, true);
-
- checkResults(cookie, webgoatURL, "/HttpBasics/");
-
- }
-
- public void httpProxies(String webgoatURL, String cookie) {
-
- startLesson(cookie, webgoatURL, "HttpProxies");
- assertThat(given()
- .when().config(restConfig).cookie("JSESSIONID", cookie).header("x-request-intercepted", "true")
- .contentType(ContentType.JSON)
- //.log().all()
- .get(webgoatURL + "/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily").then()
- //.log().all()
- .statusCode(200).extract().path("lessonCompleted"), is(true));
-
- checkResults(cookie, webgoatURL, "/HttpProxies/");
-
- }
-
- public void cia(String webgoatURL, String cookie) {
-
- startLesson(cookie, webgoatURL, "CIA");
- Map params = new HashMap<>();
- params.clear();
- params.put("question_0_solution", "Solution 3: By stealing a database where names and emails are stored and uploading it to a website.");
- params.put("question_1_solution", "Solution 1: By changing the names and emails of one or more users stored in a database.");
- params.put("question_2_solution", "Solution 4: By launching a denial of service attack on the servers.");
- params.put("question_3_solution", "Solution 2: The systems security is compromised even if only one goal is harmed.");
- checkAssignment(cookie, webgoatURL+"/WebGoat/cia/quiz", params, true);
- checkResults(cookie, webgoatURL, "/cia/");
-
- }
-
- public void securePasswords(String webgoatURL, String cookie) {
-
- startLesson(cookie, webgoatURL, "SecurePasswords");
- Map params = new HashMap<>();
- params.clear();
- params.put("password", "ajnaeliclm^&&@kjn.");
- checkAssignment(cookie, webgoatURL+"/WebGoat/SecurePasswords/assignment", params, true);
- checkResults(cookie, webgoatURL, "SecurePasswords/");
-
- startLesson(cookie, webgoatURL, "AuthBypass");
- params.clear();
- params.put("secQuestion2", "John");
- params.put("secQuestion3", "Main");
- params.put("jsEnabled", "1");
- params.put("verifyMethod", "SEC_QUESTIONS");
- params.put("userId", "12309746");
- checkAssignment(cookie, webgoatURL + "/WebGoat/auth-bypass/verify-account", params, true);
- checkResults(cookie, webgoatURL, "/auth-bypass/");
-
- startLesson(cookie, webgoatURL, "HttpProxies");
- assertThat(given().when().config(restConfig).cookie("JSESSIONID", cookie).header("x-request-intercepted", "true")
- .contentType(ContentType.JSON)
- //.log().all()
- .get(webgoatURL + "/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily").then()
- //.log().all()
- .statusCode(200).extract().path("lessonCompleted"), is(true));
- checkResults(cookie, webgoatURL, "/HttpProxies/");
-
- }
-
- public void chrome(String webgoatURL, String cookie) {
-
- startLesson(cookie, webgoatURL, "ChromeDevTools");
-
- Map params = new HashMap<>();
- params.clear();
- params.put("param1", "42");
- params.put("param2", "24");
-
- String result =
- given()
- .when()
- .config(restConfig)
- .cookie("JSESSIONID", cookie)
- .header("webgoat-requested-by","dom-xss-vuln")
- .header("X-Requested-With", "XMLHttpRequest")
- .formParams(params)
- .post(webgoatURL+"/WebGoat/CrossSiteScripting/phone-home-xss")
- .then()
- //.log().all()
- .statusCode(200)
- .extract().path("output");
- String secretNumber = result.substring("phoneHome Response is ".length());
-
- params.clear();
- params.put("successMessage", secretNumber);
- checkAssignment(cookie, webgoatURL+"/WebGoat/ChromeDevTools/dummy", params, true);
-
- params.clear();
- params.put("number", "24");
- params.put("network_num", "24");
- checkAssignment(cookie, webgoatURL+"/WebGoat/ChromeDevTools/network", params, true);
-
- checkResults(cookie, webgoatURL, "/ChromeDevTools/");
-
- }
-
-
-}
diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java
deleted file mode 100644
index 7328475f2..000000000
--- a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.owasp.webgoat;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class SqlInjectionAdvanced_TestHelper extends TestHelper {
-
- public void runTests(String webgoatURL, String cookie) {
-
- startLesson(cookie, webgoatURL, "SqlInjectionAdvanced");
-
- Map params = new HashMap<>();
- params.clear();
- params.put("username_reg", "tom' AND substring(password,1,1)='t");
- params.put("password_reg", "password");
- params.put("email_reg", "someone@microsoft.com");
- params.put("confirm_password", "password");
- checkAssignmentWithPUT(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/challenge", params, true);
-
- params.clear();
- params.put("username_login", "tom");
- params.put("password_login", "thisisasecretfortomonly");
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/challenge_Login", params, true);
-
- params.clear();
- params.put("userid_6a", "'; SELECT * FROM user_system_data;--");
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/attack6a", params, true);
-
- params.clear();
- params.put("userid_6a", "Smith' union select userid,user_name, user_name,user_name,password,cookie,userid from user_system_data --");
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/attack6a", params, true);
-
- params.clear();
- params.put("userid_6b", "passW0rD");
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/attack6b", params, true);
-
- params.clear();
- params.put("question_0_solution", "Solution 4: A statement has got values instead of a prepared statement");
- params.put("question_1_solution", "Solution 3: ?");
- params.put("question_2_solution", "Solution 2: Prepared statements are compiled once by the database management system waiting for input and are pre-compiled this way.");
- params.put("question_3_solution", "Solution 3: Placeholders can prevent that the users input gets attached to the SQL query resulting in a seperation of code and data.");
- params.put("question_4_solution", "Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'.");
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/quiz", params, true);
-
- checkResults(cookie, webgoatURL, "/SqlInjectionAdvanced/");
-
- }
-}
diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjection_TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjection_TestHelper.java
deleted file mode 100644
index 1f1db2ab4..000000000
--- a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjection_TestHelper.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.owasp.webgoat;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class SqlInjection_TestHelper extends TestHelper {
-
- private static final String sql_2 = "select department from employees where last_name='Franco'";
- private static final String sql_3 = "update employees set department='Sales' where last_name='Barnett'";
- private static final String sql_4_drop = "alter table employees drop column phone";
- private static final String sql_4_add = "alter table employees add column phone varchar(20)";
- private static final String sql_5 = "grant alter table to UnauthorizedUser";
- private static final String sql_9_account = " ' ";
- private static final String sql_9_operator = "or";
- private static final String sql_9_injection = "'1'='1";
- private static final String sql_10_login_count = "2";
- private static final String sql_10_userid = "1 or 1=1";
-
- private static final String sql_11_a = "Smith' or '1' = '1";
- private static final String sql_11_b = "3SL99A' or '1'='1";
-
- private static final String sql_12_a = "Smith";
- private static final String sql_12_b = "3SL99A' ; update employees set salary= '100000' where last_name='Smith";
-
- private static final String sql_13 = "%update% '; drop table access_log ; --'";
-
- public void runTests(String webgoatURL, String cookie) {
-
- startLesson(cookie, webgoatURL, "SqlInjection");
-
- Map params = new HashMap<>();
- params.clear();
- params.put("query", sql_2);
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack2", params, true);
-
- params.clear();
- params.put("query", sql_3);
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack3", params, true);
-
- params.clear();
- params.put("query", sql_4_drop);
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack4", params, false);
-
- params.clear();
- params.put("query", sql_4_add);
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack4", params, true);
-
- params.clear();
- params.put("query", sql_5);
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack5", params, true);
-
- params.clear();
- params.put("operator", sql_9_operator);
- params.put("account", sql_9_account);
- params.put("injection", sql_9_injection);
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/assignment5a", params, true);
-
- params.clear();
- params.put("login_count", sql_10_login_count);
- params.put("userid", sql_10_userid);
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/assignment5b", params, true);
-
- params.clear();
- params.put("name", sql_11_a);
- params.put("auth_tan", sql_11_b);
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack8", params, true);
-
- params.clear();
- params.put("name", sql_12_a);
- params.put("auth_tan", sql_12_b);
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack9", params, true);
-
- params.clear();
- params.put("action_string", sql_13);
- checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack10", params, true);
-
- checkResults(cookie, webgoatURL, "/SqlInjection/");
-
- }
-}
diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java
deleted file mode 100644
index fd2b67141..000000000
--- a/webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package org.owasp.webgoat;
-
-import static io.restassured.RestAssured.given;
-import static org.hamcrest.CoreMatchers.everyItem;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.startsWith;
-
-import static org.junit.Assert.assertThat;
-
-import java.util.Map;
-
-import io.restassured.config.RestAssuredConfig;
-import io.restassured.config.SSLConfig;
-
-public class TestHelper {
-
- //This also allows to test the application with HTTPS when outside testing option is used
- protected RestAssuredConfig restConfig = RestAssuredConfig.newConfig().sslConfig(new SSLConfig().relaxedHTTPSValidation());
-
- /**
- * At start of a lesson. The .lesson.lesson is visited and the lesson is reset.
- * @param cookie
- * @param url
- * @param lessonName
- */
- public void startLesson(String cookie, String url, String lessonName) {
- given()
- .when()
- .config(restConfig)
- .cookie("JSESSIONID", cookie)
- .get(url+"/WebGoat/"+lessonName+".lesson.lesson")
- .then()
- .statusCode(200);
-
- given()
- .when()
- .config(restConfig)
- .cookie("JSESSIONID", cookie)
- .get(url+"/WebGoat/service/restartlesson.mvc")
- .then()
- .statusCode(200);
- }
-
- /**
- * Helper method for most common type of test.
- * POST with parameters.
- * Checks for 200 and lessonCompleted as indicated by expectedResult
- * @param webgoatCookie
- * @param url
- * @param params
- * @param expectedResult
- */
- public void checkAssignment(String webgoatCookie, String url, Map params, boolean expectedResult) {
- assertThat(
- given()
- .when()
- .config(restConfig)
- .cookie("JSESSIONID", webgoatCookie)
- .formParams(params)
- .post(url)
- .then()
- //.log().all()
- .statusCode(200)
- .extract().path("lessonCompleted"), is(expectedResult));
- }
-
- /**
- * Helper method for most common type of test.
- * PUT with parameters.
- * Checks for 200 and lessonCompleted as indicated by expectedResult
- * @param webgoatCookie
- * @param url
- * @param params
- * @param expectedResult
- */
- public void checkAssignmentWithPUT(String webgoatCookie, String url, Map params, boolean expectedResult) {
- assertThat(
- given()
- .when()
- .config(restConfig)
- .cookie("JSESSIONID", webgoatCookie)
- .formParams(params)
- .put(url)
- .then()
- //.log().all()
- .statusCode(200)
- .extract().path("lessonCompleted"), is(expectedResult));
- }
-
- /**
- * Helper method at the end of a lesson.
- * Check if all path paramters are correct for the progress.
- * Check if all are solved.
- * @param webgoatCookie
- * @param webgoatURL
- * @param prefix
- */
- public void checkResults(String webgoatCookie, String webgoatURL, String prefix) {
- assertThat(given()
- .when()
- .config(restConfig)
- .cookie("JSESSIONID", webgoatCookie)
- .get(webgoatURL+"/WebGoat/service/lessonoverview.mvc")
- .then()
- //.log().all()
- .statusCode(200).extract().jsonPath().getList("solved"),everyItem(is(true)));
-
- assertThat(given()
- .when()
- .config(restConfig)
- .cookie("JSESSIONID", webgoatCookie)
- .get(webgoatURL+"/WebGoat/service/lessonoverview.mvc")
- .then()
- //.log().all()
- .statusCode(200).extract().jsonPath().getList("assignment.path"),everyItem(startsWith(prefix)));
-
- }
-}
diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/WebGoatIntegrationTest.java b/webgoat-server/src/test/java/org/owasp/webgoat/WebGoatIntegrationTest.java
deleted file mode 100644
index 12967099e..000000000
--- a/webgoat-server/src/test/java/org/owasp/webgoat/WebGoatIntegrationTest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-package org.owasp.webgoat;
-
-import static io.restassured.RestAssured.given;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.boot.context.embedded.LocalServerPort;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
-import org.springframework.test.context.junit4.SpringRunner;
-
-@RunWith(SpringRunner.class)
-@SpringBootTest(classes=WebGoat.class, webEnvironment = WebEnvironment.RANDOM_PORT)
-@EnableAutoConfiguration
-public class WebGoatIntegrationTest extends TestHelper {
-
- /*
- * Unique port for http server. Database port is not yet overruled. But this is
- * not a problem for the integration test.
- */
- @LocalServerPort
- int randomServerPort;
-
- private General_TestHelper generalTestHelper = new General_TestHelper();
- private SqlInjection_TestHelper sqlInjectionHelper = new SqlInjection_TestHelper();
- private SqlInjectionAdvanced_TestHelper sqlInjectionAdvancedHelper = new SqlInjectionAdvanced_TestHelper();
- private SqlInjectionMitigation_TestHelper sqlInjectionMitigationHelper = new SqlInjectionMitigation_TestHelper();
-
- String webgoatURL = System.getProperty("WEBGOAT_URL","");
- String webgoatUser = System.getProperty("WEBGOAT_USER","");
- String webgoatPassword = System.getProperty("WEBGOAT_PASSWORD","password");
- String cookie = "";
-
- @Before
- public void init() {
-
- /*
- * If no system properties are set, the test runs against the random port
- * of the webgoat application that starts with this test.
- * If set you can use it to test an oustide running application. If testing
- * against outside running applications, the tests that require WebWolf can be tested as well.
- */
- //TODO add support for testing the lessons that require WebWolf as well.
- if (webgoatURL.equals("")) {
- webgoatURL = "http://127.0.0.1:"+randomServerPort;
- }
-
- /*
- * If not defined a random user will be registered and used in the test.
- * If you run against an outside application and want to visually see the results,
- * you can set a username.
- */
- if (webgoatUser.equals("")) {
- webgoatUser = "tester"+Math.round(Math.random()*1000);
- }
-
- //check if user exists
- String location = given()
- .when()
- .config(restConfig)
- .formParam("username", webgoatUser)
- .formParam("password", "password")
- .post(webgoatURL+"/WebGoat/login")
- .then()
- //.log().all()
- .cookie("JSESSIONID")
- .statusCode(302)
- .extract().header("Location");
-
- //register when not existing, otherwise log in and save the cookie
- if (location.endsWith("error")) {
-
- cookie = given()
- .when()
- .config(restConfig)
- .formParam("username", webgoatUser)
- .formParam("password", "password")
- .formParam("matchingPassword", "password")
- .formParam("agree", "agree")
- .post(webgoatURL+"/WebGoat/register.mvc")
- .then()
- .cookie("JSESSIONID")
- .statusCode(302)
- .extract()
- .cookie("JSESSIONID");
-
- } else {
-
- cookie = given()
- .when()
- .config(restConfig)
- .formParam("username", webgoatUser)
- .formParam("password", "password")
- .post(webgoatURL+"/WebGoat/login")
- .then()
- //.log().all()
- .cookie("JSESSIONID")
- .statusCode(302)
- .extract().cookie("JSESSIONID");
- }
- }
-
- @Test
- public void testGeneral_HttpBasics() {
-
- generalTestHelper.httpBasics(webgoatURL, cookie);
-
- }
-
- @Test
- public void testGeneral_HttpProxies() {
-
- generalTestHelper.httpProxies(webgoatURL, cookie);
-
- }
-
- @Test
- public void testGeneral_CIA() {
-
- generalTestHelper.cia(webgoatURL, cookie);
-
- }
-
- @Test
- public void testGeneral_Chrome() {
-
- generalTestHelper.chrome(webgoatURL, cookie);
-
- }
-
- @Test
- public void testSecurePassords() {
-
- generalTestHelper.securePasswords(webgoatURL, cookie);
-
- }
-
- @Test
- public void testSQLInjection() {
-
- sqlInjectionHelper.runTests(webgoatURL, cookie);
-
- }
-
- @Test
- public void testSQLInjectionAdvanced() {
-
- sqlInjectionAdvancedHelper.runTests(webgoatURL, cookie);
-
- }
-
- @Test
- public void testSQLInjectionMitigation() {
-
- sqlInjectionMitigationHelper.runTests(webgoatURL, cookie);
-
- }
-
-
-}
diff --git a/webwolf/pom.xml b/webwolf/pom.xml
index c0126b712..54c0eb81f 100644
--- a/webwolf/pom.xml
+++ b/webwolf/pom.xml
@@ -110,6 +110,22 @@
org.springframework.boot
spring-boot-maven-plugin
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.2
+
+
+ test-compile
+
+ jar
+
+
+ internal
+
+
+
+
org.apache.maven.plugins
maven-surefire-plugin
diff --git a/webwolf/src/main/java/org/owasp/webwolf/WebWolf.java b/webwolf/src/main/java/org/owasp/webwolf/WebWolf.java
index 768b78347..1153f14cb 100644
--- a/webwolf/src/main/java/org/owasp/webwolf/WebWolf.java
+++ b/webwolf/src/main/java/org/owasp/webwolf/WebWolf.java
@@ -1,29 +1,24 @@
package org.owasp.webwolf;
-import lombok.extern.slf4j.Slf4j;
import org.owasp.webwolf.requests.WebWolfTraceRepository;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.trace.TraceRepository;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
+import java.util.Map;
+
@SpringBootApplication
-@Slf4j
-public class WebWolf extends SpringBootServletInitializer {
+public class WebWolf {
@Bean
public TraceRepository traceRepository() {
return new WebWolfTraceRepository();
}
- @Override
- protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
- return application.sources(WebWolf.class);
- }
-
- public static void main(String[] args) throws Exception {
+ public static void main(String[] args) {
+ System.setProperty("spring.config.name", "application-webwolf");
SpringApplication.run(WebWolf.class, args);
}
}
diff --git a/webwolf/src/main/java/org/owasp/webwolf/mailbox/Email.java b/webwolf/src/main/java/org/owasp/webwolf/mailbox/Email.java
index c97e0ba4e..aa31da1f7 100644
--- a/webwolf/src/main/java/org/owasp/webwolf/mailbox/Email.java
+++ b/webwolf/src/main/java/org/owasp/webwolf/mailbox/Email.java
@@ -25,6 +25,7 @@ public class Email implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
+ @JsonIgnore
private LocalDateTime time = LocalDateTime.now();
@Column(length = 1024)
private String contents;
diff --git a/webwolf/src/main/java/org/owasp/webwolf/requests/Requests.java b/webwolf/src/main/java/org/owasp/webwolf/requests/Requests.java
index d92bb4bf1..7bf9bd162 100644
--- a/webwolf/src/main/java/org/owasp/webwolf/requests/Requests.java
+++ b/webwolf/src/main/java/org/owasp/webwolf/requests/Requests.java
@@ -42,7 +42,7 @@ public class Requests {
}
@GetMapping
- public ModelAndView get(HttpServletRequest request) {
+ public ModelAndView get() {
ModelAndView m = new ModelAndView("requests");
List traces = traceRepository.findAllTraces().stream()
.map(t -> new Tracert(t.getTimestamp(), path(t), toJsonString(t))).collect(toList());
diff --git a/webwolf/src/main/java/org/owasp/webwolf/requests/WebWolfTraceRepository.java b/webwolf/src/main/java/org/owasp/webwolf/requests/WebWolfTraceRepository.java
index 23e95ba02..d08ed00f6 100644
--- a/webwolf/src/main/java/org/owasp/webwolf/requests/WebWolfTraceRepository.java
+++ b/webwolf/src/main/java/org/owasp/webwolf/requests/WebWolfTraceRepository.java
@@ -7,7 +7,10 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.actuate.trace.Trace;
import org.springframework.boot.actuate.trace.TraceRepository;
-import java.util.*;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
/**
* Keep track of all the incoming requests, we are only keeping track of request originating from
@@ -20,7 +23,7 @@ import java.util.*;
public class WebWolfTraceRepository implements TraceRepository {
private final EvictingQueue traces = EvictingQueue.create(10000);
- private List exclusionList = Lists.newArrayList("/WebWolf/home", "/WebWolf/mail","/WebWolf/files", "/images/", "/login", "/favicon.ico", "/js/", "/webjars/", "/WebWolf/requests", "/css/", "/mail");
+ private List exclusionList = Lists.newArrayList("/WebWolf/home", "/WebWolf/mail", "/WebWolf/files", "/images/", "/login", "/favicon.ico", "/js/", "/webjars/", "/WebWolf/requests", "/css/", "/mail");
@Override
public List findAll() {
@@ -40,21 +43,9 @@ public class WebWolfTraceRepository implements TraceRepository {
@Override
public void add(Map map) {
- Optional host = getFromHeaders("host", map);
String path = (String) map.getOrDefault("path", "");
- if (host.isPresent() && !isInExclusionList(path)) {
+ if (!isInExclusionList(path)) {
traces.add(new Trace(new Date(), map));
}
}
-
- private Optional getFromHeaders(String header, Map map) {
- Map headers = (Map) map.get("headers");
- if (headers != null) {
- Map request = (Map) headers.get("request");
- if (request != null) {
- return Optional.ofNullable((String) request.get(header));
- }
- }
- return Optional.empty();
- }
}
diff --git a/webwolf/src/main/java/org/owasp/webwolf/user/UserForm.java b/webwolf/src/main/java/org/owasp/webwolf/user/UserForm.java
index 7e9d82a82..bb983126e 100644
--- a/webwolf/src/main/java/org/owasp/webwolf/user/UserForm.java
+++ b/webwolf/src/main/java/org/owasp/webwolf/user/UserForm.java
@@ -15,7 +15,7 @@ import javax.validation.constraints.Size;
public class UserForm {
@NotNull
- @Size(min=6, max=20)
+ @Size(min=6, max=40)
private String username;
@NotNull
@Size(min=6, max=10)
diff --git a/webwolf/src/main/java/org/owasp/webwolf/user/WebGoatUserCookie.java b/webwolf/src/main/java/org/owasp/webwolf/user/WebGoatUserCookie.java
deleted file mode 100644
index 618d6df25..000000000
--- a/webwolf/src/main/java/org/owasp/webwolf/user/WebGoatUserCookie.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.owasp.webwolf.user;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import org.springframework.data.annotation.Id;
-
-import java.io.Serializable;
-
-/**
- * @author nbaars
- * @since 8/20/17.
- */
-@Getter
-@NoArgsConstructor
-@AllArgsConstructor
-public class WebGoatUserCookie implements Serializable {
-
- @Id
- private String username;
- private String cookie;
-}
diff --git a/webwolf/src/main/resources/application.properties b/webwolf/src/main/resources/application-webwolf.properties
similarity index 98%
rename from webwolf/src/main/resources/application.properties
rename to webwolf/src/main/resources/application-webwolf.properties
index 981ce87aa..cb3c0f617 100644
--- a/webwolf/src/main/resources/application.properties
+++ b/webwolf/src/main/resources/application-webwolf.properties
@@ -10,6 +10,7 @@ spring.datasource.url=jdbc:hsqldb:hsql://${WEBGOAT_HOST:127.0.0.1}:${WEBGOAT_HSQ
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect
spring.jpa.hibernate.ddl-auto=update
spring.messages.basename=i18n/messages
+spring.jmx.enabled=false
logging.level.org.springframework=INFO
logging.level.org.springframework.boot.devtools=WARN