diff --git a/webgoat-server/pom.xml b/webgoat-server/pom.xml
index 95bb65f69..5c0ae93b2 100644
--- a/webgoat-server/pom.xml
+++ b/webgoat-server/pom.xml
@@ -139,7 +139,17 @@
secure-passwords
${project.version}
-
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ io.rest-assured
+ rest-assured
+ 4.0.0
+ test
+
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
new file mode 100644
index 000000000..adce19bb5
--- /dev/null
+++ b/webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java
@@ -0,0 +1,133 @@
+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
new file mode 100644
index 000000000..13673a352
--- /dev/null
+++ b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java
@@ -0,0 +1,36 @@
+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("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/SqlInjectionMitigation_TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionMitigation_TestHelper.java
new file mode 100644
index 000000000..70389dee2
--- /dev/null
+++ b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionMitigation_TestHelper.java
@@ -0,0 +1,37 @@
+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/");
+
+ }
+}
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
new file mode 100644
index 000000000..1f1db2ab4
--- /dev/null
+++ b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjection_TestHelper.java
@@ -0,0 +1,80 @@
+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
new file mode 100644
index 000000000..dfad6d538
--- /dev/null
+++ b/webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java
@@ -0,0 +1,95 @@
+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 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
new file mode 100644
index 000000000..12967099e
--- /dev/null
+++ b/webgoat-server/src/test/java/org/owasp/webgoat/WebGoatIntegrationTest.java
@@ -0,0 +1,162 @@
+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);
+
+ }
+
+
+}