From ffbc808e266bc6684d994a29a35fa5f264d5f81d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Zubcevic?= Date: Thu, 25 Jul 2019 10:49:25 +0200 Subject: [PATCH] Integration test support --- webgoat-server/pom.xml | 12 +- .../org/owasp/webgoat/General_TestHelper.java | 133 ++++++++++++++ .../SqlInjectionAdvanced_TestHelper.java | 36 ++++ .../SqlInjectionMitigation_TestHelper.java | 37 ++++ .../webgoat/SqlInjection_TestHelper.java | 80 +++++++++ .../java/org/owasp/webgoat/TestHelper.java | 95 ++++++++++ .../owasp/webgoat/WebGoatIntegrationTest.java | 162 ++++++++++++++++++ 7 files changed, 554 insertions(+), 1 deletion(-) create mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java create mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java create mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionMitigation_TestHelper.java create mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/SqlInjection_TestHelper.java create mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java create mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/WebGoatIntegrationTest.java 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); + + } + + +}