diff --git a/pom.xml b/pom.xml index edaf48b00..74af4dd62 100644 --- a/pom.xml +++ b/pom.xml @@ -536,6 +536,11 @@ <flexmark></flexmark> </markdown> <java> + <includes> + <include>src/main/java/**/*.java</include> + <include>src/test/java/**/*.java</include> + <include>src/it/java/**/*.java</include> + </includes> <removeUnusedImports></removeUnusedImports> <googleJavaFormat> <style>GOOGLE</style> diff --git a/src/it/java/org/owasp/webgoat/AccessControlIntegrationTest.java b/src/it/java/org/owasp/webgoat/AccessControlIntegrationTest.java index d57661f9a..761aa07f7 100644 --- a/src/it/java/org/owasp/webgoat/AccessControlIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/AccessControlIntegrationTest.java @@ -1,86 +1,86 @@ package org.owasp.webgoat; - import io.restassured.RestAssured; import io.restassured.http.ContentType; +import java.util.Map; import org.apache.http.HttpStatus; import org.junit.jupiter.api.Test; -import java.util.Map; - class AccessControlIntegrationTest extends IntegrationTest { - @Test - void testLesson() { - startLesson("MissingFunctionAC", true); - assignment1(); - assignment2(); - assignment3(); + @Test + void testLesson() { + startLesson("MissingFunctionAC", true); + assignment1(); + assignment2(); + assignment3(); - checkResults("/access-control"); - } + checkResults("/access-control"); + } - private void assignment3() { - //direct call should fail if user has not been created - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .contentType(ContentType.JSON) - .get(url("/WebGoat/access-control/users-admin-fix")) - .then() - .statusCode(HttpStatus.SC_FORBIDDEN); + private void assignment3() { + // direct call should fail if user has not been created + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .contentType(ContentType.JSON) + .get(url("/WebGoat/access-control/users-admin-fix")) + .then() + .statusCode(HttpStatus.SC_FORBIDDEN); - //create user - var userTemplate = """ + // create user + var userTemplate = + """ {"username":"%s","password":"%s","admin": "true"} """; + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .contentType(ContentType.JSON) + .body(String.format(userTemplate, this.getUser(), this.getUser())) + .post(url("/WebGoat/access-control/users")) + .then() + .statusCode(HttpStatus.SC_OK); + + // get the users + var userHash = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .contentType(ContentType.JSON) - .body(String.format(userTemplate, this.getUser(), this.getUser())) - .post(url("/WebGoat/access-control/users")) - .then() - .statusCode(HttpStatus.SC_OK); + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .contentType(ContentType.JSON) + .get(url("/WebGoat/access-control/users-admin-fix")) + .then() + .statusCode(200) + .extract() + .jsonPath() + .get("find { it.username == \"Jerry\" }.userHash"); - //get the users - var userHash = - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .contentType(ContentType.JSON) - .get(url("/WebGoat/access-control/users-admin-fix")) - .then() - .statusCode(200) - .extract() - .jsonPath() - .get("find { it.username == \"Jerry\" }.userHash"); + checkAssignment( + url("/WebGoat/access-control/user-hash-fix"), Map.of("userHash", userHash), true); + } - checkAssignment(url("/WebGoat/access-control/user-hash-fix"), Map.of("userHash", userHash), true); - } + private void assignment2() { + var userHash = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .contentType(ContentType.JSON) + .get(url("/WebGoat/access-control/users")) + .then() + .statusCode(200) + .extract() + .jsonPath() + .get("find { it.username == \"Jerry\" }.userHash"); - private void assignment2() { - var userHash = - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .contentType(ContentType.JSON) - .get(url("/WebGoat/access-control/users")) - .then() - .statusCode(200) - .extract() - .jsonPath() - .get("find { it.username == \"Jerry\" }.userHash"); + checkAssignment(url("/WebGoat/access-control/user-hash"), Map.of("userHash", userHash), true); + } - checkAssignment(url("/WebGoat/access-control/user-hash"), Map.of("userHash", userHash), true); - } - - private void assignment1() { - var params = Map.of("hiddenMenu1", "Users", "hiddenMenu2", "Config"); - checkAssignment(url("/WebGoat/access-control/hidden-menu"), params, true); - } + private void assignment1() { + var params = Map.of("hiddenMenu1", "Users", "hiddenMenu2", "Config"); + checkAssignment(url("/WebGoat/access-control/hidden-menu"), params, true); + } } diff --git a/src/it/java/org/owasp/webgoat/CSRFIntegrationTest.java b/src/it/java/org/owasp/webgoat/CSRFIntegrationTest.java index 01d22d1aa..e590624f2 100644 --- a/src/it/java/org/owasp/webgoat/CSRFIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/CSRFIntegrationTest.java @@ -1,8 +1,18 @@ package org.owasp.webgoat; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.DynamicTest.dynamicTest; import io.restassured.RestAssured; import io.restassured.http.ContentType; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import lombok.Data; import lombok.SneakyThrows; import org.junit.jupiter.api.AfterEach; @@ -11,249 +21,265 @@ import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; import org.owasp.webgoat.container.lessons.Assignment; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.DynamicTest.dynamicTest; - public class CSRFIntegrationTest extends IntegrationTest { - private static final String trickHTML3 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" + - "<input type=\"hidden\" name=\"csrf\" value=\"thisisnotchecked\"/>\n" + - "<input type=\"submit\" name=\"submit\" value=\"assignment 3\"/>\n" + - "</form></body></html>"; + private static final String trickHTML3 = + "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" + + "<input type=\"hidden\" name=\"csrf\" value=\"thisisnotchecked\"/>\n" + + "<input type=\"submit\" name=\"submit\" value=\"assignment 3\"/>\n" + + "</form></body></html>"; - private static final String trickHTML4 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" + - "<input type=\"hidden\" name=\"reviewText\" value=\"hoi\"/>\n" + - "<input type=\"hidden\" name=\"starts\" value=\"3\"/>\n" + - "<input type=\"hidden\" name=\"validateReq\" value=\"2aa14227b9a13d0bede0388a7fba9aa9\"/>\n" + - "<input type=\"submit\" name=\"submit\" value=\"assignment 4\"/>\n" + - "</form>\n" + - "</body></html>"; + private static final String trickHTML4 = + "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" + + "<input type=\"hidden\" name=\"reviewText\" value=\"hoi\"/>\n" + + "<input type=\"hidden\" name=\"starts\" value=\"3\"/>\n" + + "<input type=\"hidden\" name=\"validateReq\"" + + " value=\"2aa14227b9a13d0bede0388a7fba9aa9\"/>\n" + + "<input type=\"submit\" name=\"submit\" value=\"assignment 4\"/>\n" + + "</form>\n" + + "</body></html>"; - private static final String trickHTML7 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" enctype='text/plain' method=\"POST\">\n" + - "<input type=\"hidden\" name='{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!' value='\"}' />\n" + - "<input type=\"submit\" value=\"assignment 7\"/>\n" + - "</form></body></html>"; + private static final String trickHTML7 = + "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" enctype='text/plain'" + + " method=\"POST\">\n" + + "<input type=\"hidden\"" + + " name='{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat" + + " is the best!!' value='\"}' />\n" + + "<input type=\"submit\" value=\"assignment 7\"/>\n" + + "</form></body></html>"; - private static final String trickHTML8 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" + - "<input type=\"hidden\" name=\"username\" value=\"csrf-USERNAME\"/>\n" + - "<input type=\"hidden\" name=\"password\" value=\"password\"/>\n" + - "<input type=\"hidden\" name=\"matchingPassword\" value=\"password\"/>\n" + - "<input type=\"hidden\" name=\"agree\" value=\"agree\"/>\n" + - "<input type=\"submit\" value=\"assignment 8\"/>\n" + - "</form></body></html>"; + private static final String trickHTML8 = + "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" + + "<input type=\"hidden\" name=\"username\" value=\"csrf-USERNAME\"/>\n" + + "<input type=\"hidden\" name=\"password\" value=\"password\"/>\n" + + "<input type=\"hidden\" name=\"matchingPassword\" value=\"password\"/>\n" + + "<input type=\"hidden\" name=\"agree\" value=\"agree\"/>\n" + + "<input type=\"submit\" value=\"assignment 8\"/>\n" + + "</form></body></html>"; - private String webwolfFileDir; + private String webwolfFileDir; - @BeforeEach - @SneakyThrows - public void init() { - startLesson("CSRF"); - webwolfFileDir = getWebWolfFileServerLocation(); - uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("/csrf/basic-get-flag"))); - uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("/csrf/review"))); - uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("/csrf/feedback/message"))); - uploadTrickHtml("csrf8.html", trickHTML8.replace("WEBGOATURL", url("/login")).replace("USERNAME", this.getUser())); + @BeforeEach + @SneakyThrows + public void init() { + startLesson("CSRF"); + webwolfFileDir = getWebWolfFileServerLocation(); + uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("/csrf/basic-get-flag"))); + uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("/csrf/review"))); + uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("/csrf/feedback/message"))); + uploadTrickHtml( + "csrf8.html", + trickHTML8.replace("WEBGOATURL", url("/login")).replace("USERNAME", this.getUser())); + } + + @TestFactory + Iterable<DynamicTest> testCSRFLesson() { + return Arrays.asList( + dynamicTest("assignment 3", () -> checkAssignment3(callTrickHtml("csrf3.html"))), + dynamicTest("assignment 4", () -> checkAssignment4(callTrickHtml("csrf4.html"))), + dynamicTest("assignment 7", () -> checkAssignment7(callTrickHtml("csrf7.html"))), + dynamicTest("assignment 8", () -> checkAssignment8(callTrickHtml("csrf8.html")))); + } + + @AfterEach + public void shutdown() throws IOException { + // logout(); + login(); // because old cookie got replaced and invalidated + startLesson("CSRF", false); + checkResults("/csrf"); + } + + private void uploadTrickHtml(String htmlName, String htmlContent) throws IOException { + + // remove any left over html + Path webWolfFilePath = Paths.get(webwolfFileDir); + if (webWolfFilePath.resolve(Paths.get(this.getUser(), htmlName)).toFile().exists()) { + Files.delete(webWolfFilePath.resolve(Paths.get(this.getUser(), htmlName))); } - @TestFactory - Iterable<DynamicTest> testCSRFLesson() { - return Arrays.asList( - dynamicTest("assignment 3", () -> checkAssignment3(callTrickHtml("csrf3.html"))), - dynamicTest("assignment 4", () -> checkAssignment4(callTrickHtml("csrf4.html"))), - dynamicTest("assignment 7", () -> checkAssignment7(callTrickHtml("csrf7.html"))), - dynamicTest("assignment 8", () -> checkAssignment8(callTrickHtml("csrf8.html"))) - ); - } + // upload trick html + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("WEBWOLFSESSION", getWebWolfCookie()) + .multiPart("file", htmlName, htmlContent.getBytes()) + .post(webWolfUrl("/WebWolf/fileupload")) + .then() + .extract() + .response() + .getBody() + .asString(); + } - @AfterEach - public void shutdown() throws IOException { - //logout(); - login();//because old cookie got replaced and invalidated - startLesson("CSRF", false); - checkResults("/csrf"); - } - - private void uploadTrickHtml(String htmlName, String htmlContent) throws IOException { - - //remove any left over html - Path webWolfFilePath = Paths.get(webwolfFileDir); - if (webWolfFilePath.resolve(Paths.get(this.getUser(), htmlName)).toFile().exists()) { - Files.delete(webWolfFilePath.resolve(Paths.get(this.getUser(), htmlName))); - } - - //upload trick html + private String callTrickHtml(String htmlName) { + String result = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("WEBWOLFSESSION", getWebWolfCookie()) - .multiPart("file", htmlName, htmlContent.getBytes()) - .post(webWolfUrl("/WebWolf/fileupload")) - .then() - .extract().response().getBody().asString(); - } + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .cookie("WEBWOLFSESSION", getWebWolfCookie()) + .get(webWolfUrl("/files/" + this.getUser() + "/" + htmlName)) + .then() + .extract() + .response() + .getBody() + .asString(); + result = result.substring(8 + result.indexOf("action=\"")); + result = result.substring(0, result.indexOf("\"")); - private String callTrickHtml(String htmlName) { - String result = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .cookie("WEBWOLFSESSION", getWebWolfCookie()) - .get(webWolfUrl("/files/" + this.getUser() + "/" + htmlName)) - .then() - .extract().response().getBody().asString(); - result = result.substring(8 + result.indexOf("action=\"")); - result = result.substring(0, result.indexOf("\"")); + return result; + } - return result; - } - - private void checkAssignment3(String goatURL) { - String flag = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .header("Referer", webWolfUrl("/files/fake.html")) - .post(goatURL) - .then() - .extract().path("flag").toString(); - - Map<String, Object> params = new HashMap<>(); - params.clear(); - params.put("confirmFlagVal", flag); - checkAssignment(url("/WebGoat/csrf/confirm-flag-1"), params, true); - } - - private void checkAssignment4(String goatURL) { - - Map<String, Object> params = new HashMap<>(); - params.clear(); - params.put("reviewText", "test review"); - params.put("stars", "5"); - params.put("validateReq", "2aa14227b9a13d0bede0388a7fba9aa9");//always the same token is the weakness - - boolean result = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .header("Referer", webWolfUrl("/files/fake.html")) - .formParams(params) - .post(goatURL) - .then() - .extract().path("lessonCompleted"); - assertEquals(true, result); - - } - - private void checkAssignment7(String goatURL) { - Map<String, Object> params = new HashMap<>(); - params.put("{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!", "\"}"); - - String flag = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .header("Referer", webWolfUrl("/files/fake.html")) - .contentType(ContentType.TEXT) - .body("{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!" + "=\"}") - .post(goatURL) - .then() - .extract().asString(); - flag = flag.substring(9 + flag.indexOf("flag is:")); - flag = flag.substring(0, flag.indexOf("\"")); - - params.clear(); - params.put("confirmFlagVal", flag); - checkAssignment(url("/WebGoat/csrf/feedback"), params, true); - - } - - private void checkAssignment8(String goatURL) { - - //first make sure there is an attack csrf- user - registerCSRFUser(); - - Map<String, Object> params = new HashMap<>(); - params.clear(); - params.put("username", "csrf-" + this.getUser()); - params.put("password", "password"); - - //login and get the new cookie - String newCookie = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .header("Referer", webWolfUrl("/files/fake.html")) - .params(params) - .post(goatURL) - .then() - .extract().cookie("JSESSIONID"); - - //select the lesson + private void checkAssignment3(String goatURL) { + String flag = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", newCookie) - .get(url("CSRF.lesson.lesson")) - .then() - .statusCode(200); + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .header("Referer", webWolfUrl("/files/fake.html")) + .post(goatURL) + .then() + .extract() + .path("flag") + .toString(); - //click on the assignment - boolean result = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", newCookie) - .post(url("/csrf/login")) - .then() - .statusCode(200) - .extract().path("lessonCompleted"); + Map<String, Object> params = new HashMap<>(); + params.clear(); + params.put("confirmFlagVal", flag); + checkAssignment(url("/WebGoat/csrf/confirm-flag-1"), params, true); + } - assertThat(result).isTrue(); + private void checkAssignment4(String goatURL) { - login(); - startLesson("CSRF", false); - - Overview[] assignments = RestAssured.given() - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("/service/lessonoverview.mvc")) - .then() - .extract() - .jsonPath() - .getObject("$", Overview[].class); -// assertThat(assignments) -// .filteredOn(a -> a.getAssignment().getName().equals("CSRFLogin")) -// .extracting(o -> o.solved) -// .containsExactly(true); - } - - @Data - private static class Overview { - Assignment assignment; - boolean solved; - } - - /** - * Try to register the new user. Ignore the result. - */ - private void registerCSRFUser() { + Map<String, Object> params = new HashMap<>(); + params.clear(); + params.put("reviewText", "test review"); + params.put("stars", "5"); + params.put( + "validateReq", "2aa14227b9a13d0bede0388a7fba9aa9"); // always the same token is the weakness + boolean result = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .formParam("username", "csrf-" + this.getUser()) - .formParam("password", "password") - .formParam("matchingPassword", "password") - .formParam("agree", "agree") - .post(url("register.mvc")); + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .header("Referer", webWolfUrl("/files/fake.html")) + .formParams(params) + .post(goatURL) + .then() + .extract() + .path("lessonCompleted"); + assertEquals(true, result); + } - } + private void checkAssignment7(String goatURL) { + Map<String, Object> params = new HashMap<>(); + params.put( + "{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the" + + " best!!", + "\"}"); + String flag = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .header("Referer", webWolfUrl("/files/fake.html")) + .contentType(ContentType.TEXT) + .body( + "{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is" + + " the best!!=\"}") + .post(goatURL) + .then() + .extract() + .asString(); + flag = flag.substring(9 + flag.indexOf("flag is:")); + flag = flag.substring(0, flag.indexOf("\"")); + + params.clear(); + params.put("confirmFlagVal", flag); + checkAssignment(url("/WebGoat/csrf/feedback"), params, true); + } + + private void checkAssignment8(String goatURL) { + + // first make sure there is an attack csrf- user + registerCSRFUser(); + + Map<String, Object> params = new HashMap<>(); + params.clear(); + params.put("username", "csrf-" + this.getUser()); + params.put("password", "password"); + + // login and get the new cookie + String newCookie = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .header("Referer", webWolfUrl("/files/fake.html")) + .params(params) + .post(goatURL) + .then() + .extract() + .cookie("JSESSIONID"); + + // select the lesson + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", newCookie) + .get(url("CSRF.lesson.lesson")) + .then() + .statusCode(200); + + // click on the assignment + boolean result = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", newCookie) + .post(url("/csrf/login")) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"); + + assertThat(result).isTrue(); + + login(); + startLesson("CSRF", false); + + Overview[] assignments = + RestAssured.given() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("/service/lessonoverview.mvc")) + .then() + .extract() + .jsonPath() + .getObject("$", Overview[].class); + // assertThat(assignments) + // .filteredOn(a -> a.getAssignment().getName().equals("CSRFLogin")) + // .extracting(o -> o.solved) + // .containsExactly(true); + } + + @Data + private static class Overview { + Assignment assignment; + boolean solved; + } + + /** Try to register the new user. Ignore the result. */ + private void registerCSRFUser() { + + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .formParam("username", "csrf-" + this.getUser()) + .formParam("password", "password") + .formParam("matchingPassword", "password") + .formParam("agree", "agree") + .post(url("register.mvc")); + } } diff --git a/src/it/java/org/owasp/webgoat/ChallengeIntegrationTest.java b/src/it/java/org/owasp/webgoat/ChallengeIntegrationTest.java index cc9cd397d..133721eee 100644 --- a/src/it/java/org/owasp/webgoat/ChallengeIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/ChallengeIntegrationTest.java @@ -1,7 +1,5 @@ package org.owasp.webgoat; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.hamcrest.Matchers.lessThan; import static org.junit.jupiter.api.Assertions.assertTrue; import io.restassured.RestAssured; diff --git a/src/it/java/org/owasp/webgoat/CryptoIntegrationTest.java b/src/it/java/org/owasp/webgoat/CryptoIntegrationTest.java index 21caef469..ad9d6f625 100644 --- a/src/it/java/org/owasp/webgoat/CryptoIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/CryptoIntegrationTest.java @@ -2,6 +2,7 @@ package org.owasp.webgoat; import static org.junit.jupiter.api.Assertions.fail; +import io.restassured.RestAssured; import java.nio.charset.Charset; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; @@ -10,125 +11,146 @@ import java.security.spec.InvalidKeySpecException; import java.util.Base64; import java.util.HashMap; import java.util.Map; - import javax.xml.bind.DatatypeConverter; - import org.junit.jupiter.api.Test; import org.owasp.webgoat.lessons.cryptography.CryptoUtil; import org.owasp.webgoat.lessons.cryptography.HashingAssignment; -import io.restassured.RestAssured; - public class CryptoIntegrationTest extends IntegrationTest { - @Test - public void runTests() { - startLesson("Cryptography"); + @Test + public void runTests() { + startLesson("Cryptography"); - checkAssignment2(); - checkAssignment3(); + checkAssignment2(); + checkAssignment3(); - // Assignment 4 - try { - checkAssignment4(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - fail(); - } - - try { - checkAssignmentSigning(); - } catch (Exception e) { - e.printStackTrace(); - fail(); - } - - checkAssignmentDefaults(); - - checkResults("/crypto"); - - } - - private void checkAssignment2() { - - String basicEncoding = RestAssured.given().when().relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()).get(url("/crypto/encoding/basic")).then().extract() - .asString(); - basicEncoding = basicEncoding.substring("Authorization: Basic ".length()); - String decodedString = new String(Base64.getDecoder().decode(basicEncoding.getBytes())); - String answer_user = decodedString.split(":")[0]; - String answer_pwd = decodedString.split(":")[1]; - Map<String, Object> params = new HashMap<>(); - params.clear(); - params.put("answer_user", answer_user); - params.put("answer_pwd", answer_pwd); - checkAssignment(url("/crypto/encoding/basic-auth"), params, true); - } - - private void checkAssignment3() { - String answer_1 = "databasepassword"; - Map<String, Object> params = new HashMap<>(); - params.clear(); - params.put("answer_pwd1", answer_1); - checkAssignment(url("/crypto/encoding/xor"), params, true); - } - - private void checkAssignment4() throws NoSuchAlgorithmException { - - String md5Hash = RestAssured.given().when().relaxedHTTPSValidation().cookie("JSESSIONID", getWebGoatCookie()) - .get(url("/crypto/hashing/md5")).then().extract().asString(); - - String sha256Hash = RestAssured.given().when().relaxedHTTPSValidation().cookie("JSESSIONID", getWebGoatCookie()) - .get(url("/crypto/hashing/sha256")).then().extract().asString(); - - String answer_1 = "unknown"; - String answer_2 = "unknown"; - for (String secret : HashingAssignment.SECRETS) { - if (md5Hash.equals(HashingAssignment.getHash(secret, "MD5"))) { - answer_1 = secret; - } - if (sha256Hash.equals(HashingAssignment.getHash(secret, "SHA-256"))) { - answer_2 = secret; - } - } - - Map<String, Object> params = new HashMap<>(); - params.clear(); - params.put("answer_pwd1", answer_1); - params.put("answer_pwd2", answer_2); - checkAssignment(url("/WebGoat/crypto/hashing"), params, true); - } - - private void checkAssignmentSigning() throws NoSuchAlgorithmException, InvalidKeySpecException { - - String privatePEM = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("/crypto/signing/getprivate")) - .then() - .extract().asString(); - PrivateKey privateKey = CryptoUtil.getPrivateKeyFromPEM(privatePEM); - - RSAPrivateKey privk = (RSAPrivateKey) privateKey; - String modulus = DatatypeConverter.printHexBinary(privk.getModulus().toByteArray()); - String signature = CryptoUtil.signMessage(modulus, privateKey); - Map<String, Object> params = new HashMap<>(); - params.clear(); - params.put("modulus", modulus); - params.put("signature", signature); - checkAssignment(url("/crypto/signing/verify"), params, true); + // Assignment 4 + try { + checkAssignment4(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + fail(); } - - private void checkAssignmentDefaults() { - - String text = new String(Base64.getDecoder().decode("TGVhdmluZyBwYXNzd29yZHMgaW4gZG9ja2VyIGltYWdlcyBpcyBub3Qgc28gc2VjdXJl".getBytes(Charset.forName("UTF-8")))); - Map<String, Object> params = new HashMap<>(); - params.clear(); - params.put("secretText", text); - params.put("secretFileName", "default_secret"); - checkAssignment(url("/crypto/secure/defaults"), params, true); + try { + checkAssignmentSigning(); + } catch (Exception e) { + e.printStackTrace(); + fail(); } - + + checkAssignmentDefaults(); + + checkResults("/crypto"); + } + + private void checkAssignment2() { + + String basicEncoding = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("/crypto/encoding/basic")) + .then() + .extract() + .asString(); + basicEncoding = basicEncoding.substring("Authorization: Basic ".length()); + String decodedString = new String(Base64.getDecoder().decode(basicEncoding.getBytes())); + String answer_user = decodedString.split(":")[0]; + String answer_pwd = decodedString.split(":")[1]; + Map<String, Object> params = new HashMap<>(); + params.clear(); + params.put("answer_user", answer_user); + params.put("answer_pwd", answer_pwd); + checkAssignment(url("/crypto/encoding/basic-auth"), params, true); + } + + private void checkAssignment3() { + String answer_1 = "databasepassword"; + Map<String, Object> params = new HashMap<>(); + params.clear(); + params.put("answer_pwd1", answer_1); + checkAssignment(url("/crypto/encoding/xor"), params, true); + } + + private void checkAssignment4() throws NoSuchAlgorithmException { + + String md5Hash = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("/crypto/hashing/md5")) + .then() + .extract() + .asString(); + + String sha256Hash = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("/crypto/hashing/sha256")) + .then() + .extract() + .asString(); + + String answer_1 = "unknown"; + String answer_2 = "unknown"; + for (String secret : HashingAssignment.SECRETS) { + if (md5Hash.equals(HashingAssignment.getHash(secret, "MD5"))) { + answer_1 = secret; + } + if (sha256Hash.equals(HashingAssignment.getHash(secret, "SHA-256"))) { + answer_2 = secret; + } + } + + Map<String, Object> params = new HashMap<>(); + params.clear(); + params.put("answer_pwd1", answer_1); + params.put("answer_pwd2", answer_2); + checkAssignment(url("/WebGoat/crypto/hashing"), params, true); + } + + private void checkAssignmentSigning() throws NoSuchAlgorithmException, InvalidKeySpecException { + + String privatePEM = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("/crypto/signing/getprivate")) + .then() + .extract() + .asString(); + PrivateKey privateKey = CryptoUtil.getPrivateKeyFromPEM(privatePEM); + + RSAPrivateKey privk = (RSAPrivateKey) privateKey; + String modulus = DatatypeConverter.printHexBinary(privk.getModulus().toByteArray()); + String signature = CryptoUtil.signMessage(modulus, privateKey); + Map<String, Object> params = new HashMap<>(); + params.clear(); + params.put("modulus", modulus); + params.put("signature", signature); + checkAssignment(url("/crypto/signing/verify"), params, true); + } + + private void checkAssignmentDefaults() { + + String text = + new String( + Base64.getDecoder() + .decode( + "TGVhdmluZyBwYXNzd29yZHMgaW4gZG9ja2VyIGltYWdlcyBpcyBub3Qgc28gc2VjdXJl" + .getBytes(Charset.forName("UTF-8")))); + + Map<String, Object> params = new HashMap<>(); + params.clear(); + params.put("secretText", text); + params.put("secretFileName", "default_secret"); + checkAssignment(url("/crypto/secure/defaults"), params, true); + } } diff --git a/src/it/java/org/owasp/webgoat/DeserializationIntegrationTest.java b/src/it/java/org/owasp/webgoat/DeserializationIntegrationTest.java index 496d6cfa8..29572be45 100644 --- a/src/it/java/org/owasp/webgoat/DeserializationIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/DeserializationIntegrationTest.java @@ -1,34 +1,33 @@ package org.owasp.webgoat; -import org.dummy.insecure.framework.VulnerableTaskHolder; -import org.junit.jupiter.api.Test; -import org.owasp.webgoat.lessons.deserialization.SerializationHelper; - import java.io.IOException; import java.util.HashMap; import java.util.Map; +import org.dummy.insecure.framework.VulnerableTaskHolder; +import org.junit.jupiter.api.Test; +import org.owasp.webgoat.lessons.deserialization.SerializationHelper; public class DeserializationIntegrationTest extends IntegrationTest { - private static String OS = System.getProperty("os.name").toLowerCase(); + private static String OS = System.getProperty("os.name").toLowerCase(); - @Test - public void runTests() throws IOException { - startLesson("InsecureDeserialization"); + @Test + public void runTests() throws IOException { + startLesson("InsecureDeserialization"); - Map<String, Object> params = new HashMap<>(); - params.clear(); - - if (OS.indexOf("win") > -1) { - params.put("token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "ping localhost -n 5"))); - } else { - params.put("token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "sleep 5"))); - } - checkAssignment(url("/WebGoat/InsecureDeserialization/task"), params, true); - - checkResults("/InsecureDeserialization/"); + Map<String, Object> params = new HashMap<>(); + params.clear(); + if (OS.indexOf("win") > -1) { + params.put( + "token", + SerializationHelper.toString(new VulnerableTaskHolder("wait", "ping localhost -n 5"))); + } else { + params.put( + "token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "sleep 5"))); } + checkAssignment(url("/WebGoat/InsecureDeserialization/task"), params, true); - + checkResults("/InsecureDeserialization/"); + } } diff --git a/src/it/java/org/owasp/webgoat/GeneralLessonIntegrationTest.java b/src/it/java/org/owasp/webgoat/GeneralLessonIntegrationTest.java index 8522681a5..274ce639c 100644 --- a/src/it/java/org/owasp/webgoat/GeneralLessonIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/GeneralLessonIntegrationTest.java @@ -61,7 +61,8 @@ public class GeneralLessonIntegrationTest extends IntegrationTest { 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."); + "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."); diff --git a/src/it/java/org/owasp/webgoat/IDORIntegrationTest.java b/src/it/java/org/owasp/webgoat/IDORIntegrationTest.java index 56308d92d..dca27650b 100644 --- a/src/it/java/org/owasp/webgoat/IDORIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/IDORIntegrationTest.java @@ -1,13 +1,14 @@ package org.owasp.webgoat; - import static org.junit.jupiter.api.DynamicTest.dynamicTest; +import io.restassured.RestAssured; +import io.restassured.http.ContentType; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.Map; - +import lombok.SneakyThrows; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; import org.junit.jupiter.api.AfterEach; @@ -15,84 +16,81 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; -import io.restassured.RestAssured; -import io.restassured.http.ContentType; -import lombok.SneakyThrows; - public class IDORIntegrationTest extends IntegrationTest { - - @BeforeEach - @SneakyThrows - public void init() { - startLesson("IDOR"); - } - @TestFactory - Iterable<DynamicTest> testIDORLesson() { - return Arrays.asList( - dynamicTest("login",()-> loginIDOR()), - dynamicTest("profile", () -> profile()) - ); - } - - @AfterEach - public void shutdown() throws IOException { - checkResults("/IDOR"); - } - - private void loginIDOR() throws IOException { - - Map<String, Object> params = new HashMap<>(); - params.clear(); - params.put("username", "tom"); - params.put("password", "cat"); - - - checkAssignment(url("/WebGoat/IDOR/login"), params, true); - - } - - private void profile() { - MatcherAssert.assertThat( - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("/WebGoat/IDOR/profile")) - .then() - .statusCode(200) - .extract().path("userId"), CoreMatchers.is("2342384")); - Map<String, Object> params = new HashMap<>(); - params.clear(); - params.put("attributes", "userId,role"); - checkAssignment(url("/WebGoat/IDOR/diff-attributes"), params, true); - params.clear(); - params.put("url", "WebGoat/IDOR/profile/2342384"); - checkAssignment(url("/WebGoat/IDOR/profile/alt-path"), params, true); - - MatcherAssert.assertThat( - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("/WebGoat/IDOR/profile/2342388")) - .then() - .statusCode(200) - .extract().path("lessonCompleted"), CoreMatchers.is(true)); - - MatcherAssert.assertThat( - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .contentType(ContentType.JSON) //part of the lesson - .body("{\"role\":\"1\", \"color\":\"red\", \"size\":\"large\", \"name\":\"Buffalo Bill\", \"userId\":\"2342388\"}") - .put(url("/WebGoat/IDOR/profile/2342388")) - .then() - .statusCode(200) - .extract().path("lessonCompleted"), CoreMatchers.is(true)); - - - } - + @BeforeEach + @SneakyThrows + public void init() { + startLesson("IDOR"); + } + + @TestFactory + Iterable<DynamicTest> testIDORLesson() { + return Arrays.asList( + dynamicTest("login", () -> loginIDOR()), dynamicTest("profile", () -> profile())); + } + + @AfterEach + public void shutdown() throws IOException { + checkResults("/IDOR"); + } + + private void loginIDOR() throws IOException { + + Map<String, Object> params = new HashMap<>(); + params.clear(); + params.put("username", "tom"); + params.put("password", "cat"); + + checkAssignment(url("/WebGoat/IDOR/login"), params, true); + } + + private void profile() { + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("/WebGoat/IDOR/profile")) + .then() + .statusCode(200) + .extract() + .path("userId"), + CoreMatchers.is("2342384")); + Map<String, Object> params = new HashMap<>(); + params.clear(); + params.put("attributes", "userId,role"); + checkAssignment(url("/WebGoat/IDOR/diff-attributes"), params, true); + params.clear(); + params.put("url", "WebGoat/IDOR/profile/2342384"); + checkAssignment(url("/WebGoat/IDOR/profile/alt-path"), params, true); + + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("/WebGoat/IDOR/profile/2342388")) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"), + CoreMatchers.is(true)); + + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .contentType(ContentType.JSON) // part of the lesson + .body( + "{\"role\":\"1\", \"color\":\"red\", \"size\":\"large\", \"name\":\"Buffalo Bill\"," + + " \"userId\":\"2342388\"}") + .put(url("/WebGoat/IDOR/profile/2342388")) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"), + CoreMatchers.is(true)); + } } diff --git a/src/it/java/org/owasp/webgoat/IntegrationTest.java b/src/it/java/org/owasp/webgoat/IntegrationTest.java index c3fb3d9ff..db551afeb 100644 --- a/src/it/java/org/owasp/webgoat/IntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/IntegrationTest.java @@ -1,231 +1,255 @@ package org.owasp.webgoat; +import static io.restassured.RestAssured.given; + import io.restassured.RestAssured; import io.restassured.http.ContentType; +import java.util.Map; +import java.util.Objects; import lombok.Getter; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import java.util.Map; -import java.util.Objects; - -import static io.restassured.RestAssured.given; - public abstract class IntegrationTest { - private static String webGoatPort = Objects.requireNonNull(System.getProperty("webgoatport")); - @Getter - private static String webWolfPort = Objects.requireNonNull(System.getProperty("webwolfport")); - private static boolean useSSL = false; - private static String webgoatUrl = (useSSL ? "https:" : "http:") + "//localhost:" + webGoatPort + "/WebGoat/"; - private static String webWolfUrl = (useSSL ? "https:" : "http:") + "//localhost:" + webWolfPort + "/"; - @Getter - private String webGoatCookie; - @Getter - private String webWolfCookie; - @Getter - private final String user = "webgoat"; + private static String webGoatPort = Objects.requireNonNull(System.getProperty("webgoatport")); - protected String url(String url) { - url = url.replaceFirst("/WebGoat/", ""); - url = url.replaceFirst("/WebGoat", ""); - url = url.startsWith("/") ? url.replaceFirst("/", "") : url; - return webgoatUrl + url; + @Getter + private static String webWolfPort = Objects.requireNonNull(System.getProperty("webwolfport")); + + private static boolean useSSL = false; + private static String webgoatUrl = + (useSSL ? "https:" : "http:") + "//localhost:" + webGoatPort + "/WebGoat/"; + private static String webWolfUrl = + (useSSL ? "https:" : "http:") + "//localhost:" + webWolfPort + "/"; + @Getter private String webGoatCookie; + @Getter private String webWolfCookie; + @Getter private final String user = "webgoat"; + + protected String url(String url) { + url = url.replaceFirst("/WebGoat/", ""); + url = url.replaceFirst("/WebGoat", ""); + url = url.startsWith("/") ? url.replaceFirst("/", "") : url; + return webgoatUrl + url; + } + + protected String webWolfUrl(String url) { + url = url.replaceFirst("/WebWolf/", ""); + url = url.replaceFirst("/WebWolf", ""); + url = url.startsWith("/") ? url.replaceFirst("/", "") : url; + return webWolfUrl + url; + } + + @BeforeEach + public void login() { + String location = + given() + .when() + .relaxedHTTPSValidation() + .formParam("username", user) + .formParam("password", "password") + .post(url("login")) + .then() + .cookie("JSESSIONID") + .statusCode(302) + .extract() + .header("Location"); + if (location.endsWith("?error")) { + webGoatCookie = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .formParam("username", user) + .formParam("password", "password") + .formParam("matchingPassword", "password") + .formParam("agree", "agree") + .post(url("register.mvc")) + .then() + .cookie("JSESSIONID") + .statusCode(302) + .extract() + .cookie("JSESSIONID"); + } else { + webGoatCookie = + given() + .when() + .relaxedHTTPSValidation() + .formParam("username", user) + .formParam("password", "password") + .post(url("login")) + .then() + .cookie("JSESSIONID") + .statusCode(302) + .extract() + .cookie("JSESSIONID"); } - protected String webWolfUrl(String url) { - url = url.replaceFirst("/WebWolf/", ""); - url = url.replaceFirst("/WebWolf", ""); - url = url.startsWith("/") ? url.replaceFirst("/", "") : url; - return webWolfUrl + url; - } - - @BeforeEach - public void login() { - String location = given() - .when() - .relaxedHTTPSValidation() - .formParam("username", user) - .formParam("password", "password") - .post(url("login")).then() - .cookie("JSESSIONID") - .statusCode(302) - .extract().header("Location"); - if (location.endsWith("?error")) { - webGoatCookie = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .formParam("username", user) - .formParam("password", "password") - .formParam("matchingPassword", "password") - .formParam("agree", "agree") - .post(url("register.mvc")) - .then() - .cookie("JSESSIONID") - .statusCode(302) - .extract() - .cookie("JSESSIONID"); - } else { - webGoatCookie = given() - .when() - .relaxedHTTPSValidation() - .formParam("username", user) - .formParam("password", "password") - .post(url("login")).then() - .cookie("JSESSIONID") - .statusCode(302) - .extract().cookie("JSESSIONID"); - } - - webWolfCookie = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .formParam("username", user) - .formParam("password", "password") - .post(webWolfUrl("login")) - .then() - .statusCode(302) - .cookie("WEBWOLFSESSION") - .extract() - .cookie("WEBWOLFSESSION"); - } - - @AfterEach - public void logout() { + webWolfCookie = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .get(url("logout")) - .then() - .statusCode(200); - } + .when() + .relaxedHTTPSValidation() + .formParam("username", user) + .formParam("password", "password") + .post(webWolfUrl("login")) + .then() + .statusCode(302) + .cookie("WEBWOLFSESSION") + .extract() + .cookie("WEBWOLFSESSION"); + } - public void startLesson(String lessonName) { - startLesson(lessonName, false); - } + @AfterEach + public void logout() { + RestAssured.given().when().relaxedHTTPSValidation().get(url("logout")).then().statusCode(200); + } - public void startLesson(String lessonName, boolean restart) { + public void startLesson(String lessonName) { + startLesson(lessonName, false); + } + + public void startLesson(String lessonName, boolean restart) { + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url(lessonName + ".lesson.lesson")) + .then() + .statusCode(200); + + if (restart) { + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("service/restartlesson.mvc")) + .then() + .statusCode(200); + } + } + + public void checkAssignment(String url, Map<String, ?> params, boolean expectedResult) { + MatcherAssert.assertThat( RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url(lessonName + ".lesson.lesson")) - .then() - .statusCode(200); + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .formParams(params) + .post(url) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"), + CoreMatchers.is(expectedResult)); + } - if (restart) { - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("service/restartlesson.mvc")) - .then() - .statusCode(200); - } - } + public void checkAssignmentWithPUT(String url, Map<String, ?> params, boolean expectedResult) { + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .formParams(params) + .put(url) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"), + CoreMatchers.is(expectedResult)); + } - public void checkAssignment(String url, Map<String, ?> params, boolean expectedResult) { - MatcherAssert.assertThat( - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .formParams(params) - .post(url) - .then() - .statusCode(200) - .extract().path("lessonCompleted"), CoreMatchers.is(expectedResult)); - } + // TODO is prefix useful? not every lesson endpoint needs to start with a certain prefix (they are + // only required to be in the same package) + public void checkResults(String prefix) { + checkResults(); - public void checkAssignmentWithPUT(String url, Map<String, ?> params, boolean expectedResult) { - MatcherAssert.assertThat( - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .formParams(params) - .put(url) - .then() - .statusCode(200) - .extract().path("lessonCompleted"), CoreMatchers.is(expectedResult)); - } + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("service/lessonoverview.mvc")) + .then() + .statusCode(200) + .extract() + .jsonPath() + .getList("assignment.path"), + CoreMatchers.everyItem(CoreMatchers.startsWith(prefix))); + } - //TODO is prefix useful? not every lesson endpoint needs to start with a certain prefix (they are only required to be in the same package) - public void checkResults(String prefix) { - checkResults(); + public void checkResults() { + var result = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("service/lessonoverview.mvc")) + .andReturn(); - MatcherAssert.assertThat(RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("service/lessonoverview.mvc")) - .then() - .statusCode(200).extract().jsonPath().getList("assignment.path"), CoreMatchers.everyItem(CoreMatchers.startsWith(prefix))); + MatcherAssert.assertThat( + result.then().statusCode(200).extract().jsonPath().getList("solved"), + CoreMatchers.everyItem(CoreMatchers.is(true))); + } - } + public void checkAssignment( + String url, ContentType contentType, String body, boolean expectedResult) { + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .contentType(contentType) + .cookie("JSESSIONID", getWebGoatCookie()) + .body(body) + .post(url) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"), + CoreMatchers.is(expectedResult)); + } - public void checkResults() { - var result = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("service/lessonoverview.mvc")) - .andReturn(); + public void checkAssignmentWithGet(String url, Map<String, ?> params, boolean expectedResult) { + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .queryParams(params) + .get(url) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"), + CoreMatchers.is(expectedResult)); + } - MatcherAssert.assertThat(result.then() - .statusCode(200).extract().jsonPath().getList("solved"), CoreMatchers.everyItem(CoreMatchers.is(true))); - } - - public void checkAssignment(String url, ContentType contentType, String body, boolean expectedResult) { - MatcherAssert.assertThat( - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .contentType(contentType) - .cookie("JSESSIONID", getWebGoatCookie()) - .body(body) - .post(url) - .then() - .statusCode(200) - .extract().path("lessonCompleted"), CoreMatchers.is(expectedResult)); - } - - public void checkAssignmentWithGet(String url, Map<String, ?> params, boolean expectedResult) { - MatcherAssert.assertThat( - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .queryParams(params) - .get(url) - .then() - .statusCode(200) - .extract().path("lessonCompleted"), CoreMatchers.is(expectedResult)); - } - - public String getWebWolfFileServerLocation() { - String result = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("WEBWOLFSESSION", getWebWolfCookie()) - .get(webWolfUrl("/file-server-location")) - .then() - .extract().response().getBody().asString(); - result = result.replace("%20", " "); - return result; - } - - public String webGoatServerDirectory() { - return RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("/server-directory")) - .then() - .extract().response().getBody().asString(); - } + public String getWebWolfFileServerLocation() { + String result = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("WEBWOLFSESSION", getWebWolfCookie()) + .get(webWolfUrl("/file-server-location")) + .then() + .extract() + .response() + .getBody() + .asString(); + result = result.replace("%20", " "); + return result; + } + public String webGoatServerDirectory() { + return RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("/server-directory")) + .then() + .extract() + .response() + .getBody() + .asString(); + } } - diff --git a/src/it/java/org/owasp/webgoat/JWTLessonIntegrationTest.java b/src/it/java/org/owasp/webgoat/JWTLessonIntegrationTest.java index 536eec117..58b981470 100644 --- a/src/it/java/org/owasp/webgoat/JWTLessonIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/JWTLessonIntegrationTest.java @@ -1,5 +1,16 @@ package org.owasp.webgoat; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import io.jsonwebtoken.Header; +import io.jsonwebtoken.JwsHeader; +import io.jsonwebtoken.Jwt; +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.impl.TextCodec; +import io.restassured.RestAssured; import java.io.IOException; import java.nio.charset.Charset; import java.security.InvalidKeyException; @@ -10,207 +21,230 @@ import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; - import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; import org.junit.jupiter.api.Test; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import io.jsonwebtoken.Header; -import io.jsonwebtoken.JwsHeader; -import io.jsonwebtoken.Jwt; -import io.jsonwebtoken.JwtException; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import io.jsonwebtoken.impl.TextCodec; -import io.restassured.RestAssured; import org.owasp.webgoat.lessons.jwt.JWTSecretKeyEndpoint; public class JWTLessonIntegrationTest extends IntegrationTest { - - @Test - public void solveAssignment() throws IOException, InvalidKeyException, NoSuchAlgorithmException { - startLesson("JWT"); - decodingToken(); - - resetVotes(); - - findPassword(); - - buyAsTom(); - - deleteTom(); + @Test + public void solveAssignment() throws IOException, InvalidKeyException, NoSuchAlgorithmException { + startLesson("JWT"); - quiz(); - - checkResults("/JWT/"); - } - - private String generateToken(String key) { - - return Jwts.builder() - .setIssuer("WebGoat Token Builder") - .setAudience("webgoat.org") - .setIssuedAt(Calendar.getInstance().getTime()) - .setExpiration(Date.from(Instant.now().plusSeconds(60))) - .setSubject("tom@webgoat.org") - .claim("username", "WebGoat") - .claim("Email", "tom@webgoat.org") - .claim("Role", new String[] {"Manager", "Project Administrator"}) - .signWith(SignatureAlgorithm.HS256, key).compact(); - } - - private String getSecretToken(String token) { - for (String key : JWTSecretKeyEndpoint.SECRETS) { - try { - Jwt jwt = Jwts.parser().setSigningKey(TextCodec.BASE64.encode(key)).parse(token); - } catch (JwtException e) { - continue; - } - return TextCodec.BASE64.encode(key); - } - return null; + decodingToken(); + + resetVotes(); + + findPassword(); + + buyAsTom(); + + deleteTom(); + + quiz(); + + checkResults("/JWT/"); + } + + private String generateToken(String key) { + + return Jwts.builder() + .setIssuer("WebGoat Token Builder") + .setAudience("webgoat.org") + .setIssuedAt(Calendar.getInstance().getTime()) + .setExpiration(Date.from(Instant.now().plusSeconds(60))) + .setSubject("tom@webgoat.org") + .claim("username", "WebGoat") + .claim("Email", "tom@webgoat.org") + .claim("Role", new String[] {"Manager", "Project Administrator"}) + .signWith(SignatureAlgorithm.HS256, key) + .compact(); + } + + private String getSecretToken(String token) { + for (String key : JWTSecretKeyEndpoint.SECRETS) { + try { + Jwt jwt = Jwts.parser().setSigningKey(TextCodec.BASE64.encode(key)).parse(token); + } catch (JwtException e) { + continue; + } + return TextCodec.BASE64.encode(key); } + return null; + } - private void decodingToken() { - MatcherAssert.assertThat( - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .formParam("jwt-encode-user", "user") - .post(url("/WebGoat/JWT/decode")) - .then() - .statusCode(200) - .extract().path("lessonCompleted"), CoreMatchers.is(true)); + private void decodingToken() { + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .formParam("jwt-encode-user", "user") + .post(url("/WebGoat/JWT/decode")) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"), + CoreMatchers.is(true)); + } - } - - private void findPassword() throws IOException, NoSuchAlgorithmException, InvalidKeyException { - - String accessToken = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("/WebGoat/JWT/secret/gettoken")) - .then() - .extract().response().asString(); - - String secret = getSecretToken(accessToken); - - MatcherAssert.assertThat( - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .formParam("token", generateToken(secret)) - .post(url("/WebGoat/JWT/secret")) - .then() - .statusCode(200) - .extract().path("lessonCompleted"), CoreMatchers.is(true)); - - } - - private void resetVotes() throws IOException { - String accessToken = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("/WebGoat/JWT/votings/login?user=Tom")) - .then() - .extract().cookie("access_token"); + private void findPassword() throws IOException, NoSuchAlgorithmException, InvalidKeyException { - String header = accessToken.substring(0, accessToken.indexOf(".")); - header = new String(Base64.getUrlDecoder().decode(header.getBytes(Charset.defaultCharset()))); - - String body = accessToken.substring(1+accessToken.indexOf("."), accessToken.lastIndexOf(".")); - body = new String(Base64.getUrlDecoder().decode(body.getBytes(Charset.defaultCharset()))); + String accessToken = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("/WebGoat/JWT/secret/gettoken")) + .then() + .extract() + .response() + .asString(); - ObjectMapper mapper = new ObjectMapper(); - JsonNode headerNode = mapper.readTree(header); - headerNode = ((ObjectNode) headerNode).put("alg","NONE"); + String secret = getSecretToken(accessToken); - JsonNode bodyObject = mapper.readTree(body); - bodyObject = ((ObjectNode) bodyObject).put("admin","true"); - - String replacedToken = new String(Base64.getUrlEncoder().encode(headerNode.toString().getBytes())) - .concat(".") - .concat(new String(Base64.getUrlEncoder().encode(bodyObject.toString().getBytes())).toString()) - .concat(".").replace("=", ""); - - MatcherAssert.assertThat( - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .cookie("access_token", replacedToken) - .post(url("/WebGoat/JWT/votings")) - .then() - .statusCode(200) - .extract().path("lessonCompleted"), CoreMatchers.is(true)); - } - - private void buyAsTom() throws IOException { - - String header = new String(Base64.getUrlDecoder().decode("eyJhbGciOiJIUzUxMiJ9".getBytes(Charset.defaultCharset()))); + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .formParam("token", generateToken(secret)) + .post(url("/WebGoat/JWT/secret")) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"), + CoreMatchers.is(true)); + } - String body = new String(Base64.getUrlDecoder().decode("eyJhZG1pbiI6ImZhbHNlIiwidXNlciI6IkplcnJ5In0".getBytes(Charset.defaultCharset()))); + private void resetVotes() throws IOException { + String accessToken = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("/WebGoat/JWT/votings/login?user=Tom")) + .then() + .extract() + .cookie("access_token"); - body = body.replace("Jerry", "Tom"); - - ObjectMapper mapper = new ObjectMapper(); - JsonNode headerNode = mapper.readTree(header); - headerNode = ((ObjectNode) headerNode).put("alg", "NONE"); + String header = accessToken.substring(0, accessToken.indexOf(".")); + header = new String(Base64.getUrlDecoder().decode(header.getBytes(Charset.defaultCharset()))); - String replacedToken = new String(Base64.getUrlEncoder().encode(headerNode.toString().getBytes())).concat(".") - .concat(new String(Base64.getUrlEncoder().encode(body.getBytes())).toString()) - .concat(".").replace("=", ""); + String body = accessToken.substring(1 + accessToken.indexOf("."), accessToken.lastIndexOf(".")); + body = new String(Base64.getUrlDecoder().decode(body.getBytes(Charset.defaultCharset()))); - MatcherAssert.assertThat(RestAssured.given() - .when().relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .header("Authorization","Bearer "+replacedToken) - .post(url("/WebGoat/JWT/refresh/checkout")) - .then().statusCode(200) - .extract().path("lessonCompleted"), CoreMatchers.is(true)); - } - - private void deleteTom() { - - Map<String, Object> header = new HashMap(); - header.put(Header.TYPE, Header.JWT_TYPE); - header.put(JwsHeader.KEY_ID, "hacked' UNION select 'deletingTom' from INFORMATION_SCHEMA.SYSTEM_USERS --"); - String token = Jwts.builder() - .setHeader(header) - .setIssuer("WebGoat Token Builder") - .setAudience("webgoat.org") - .setIssuedAt(Calendar.getInstance().getTime()) - .setExpiration(Date.from(Instant.now().plusSeconds(60))) - .setSubject("tom@webgoat.org") - .claim("username", "Tom") - .claim("Email", "tom@webgoat.org") - .claim("Role", new String[] {"Manager", "Project Administrator"}) - .signWith(SignatureAlgorithm.HS256, "deletingTom").compact(); - - MatcherAssert.assertThat(RestAssured.given() - .when().relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .post(url("/WebGoat/JWT/final/delete?token="+token)) - .then() - .statusCode(200) - .extract().path("lessonCompleted"), CoreMatchers.is(true)); - } + ObjectMapper mapper = new ObjectMapper(); + JsonNode headerNode = mapper.readTree(header); + headerNode = ((ObjectNode) headerNode).put("alg", "NONE"); - private void quiz() { - Map<String, Object> params = new HashMap<>(); - params.put("question_0_solution", "Solution 1"); - params.put("question_1_solution", "Solution 2"); + JsonNode bodyObject = mapper.readTree(body); + bodyObject = ((ObjectNode) bodyObject).put("admin", "true"); - checkAssignment(url("/WebGoat/JWT/quiz"), params, true); - } - + String replacedToken = + new String(Base64.getUrlEncoder().encode(headerNode.toString().getBytes())) + .concat(".") + .concat( + new String(Base64.getUrlEncoder().encode(bodyObject.toString().getBytes())) + .toString()) + .concat(".") + .replace("=", ""); + + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .cookie("access_token", replacedToken) + .post(url("/WebGoat/JWT/votings")) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"), + CoreMatchers.is(true)); + } + + private void buyAsTom() throws IOException { + + String header = + new String( + Base64.getUrlDecoder() + .decode("eyJhbGciOiJIUzUxMiJ9".getBytes(Charset.defaultCharset()))); + + String body = + new String( + Base64.getUrlDecoder() + .decode( + "eyJhZG1pbiI6ImZhbHNlIiwidXNlciI6IkplcnJ5In0" + .getBytes(Charset.defaultCharset()))); + + body = body.replace("Jerry", "Tom"); + + ObjectMapper mapper = new ObjectMapper(); + JsonNode headerNode = mapper.readTree(header); + headerNode = ((ObjectNode) headerNode).put("alg", "NONE"); + + String replacedToken = + new String(Base64.getUrlEncoder().encode(headerNode.toString().getBytes())) + .concat(".") + .concat(new String(Base64.getUrlEncoder().encode(body.getBytes())).toString()) + .concat(".") + .replace("=", ""); + + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .header("Authorization", "Bearer " + replacedToken) + .post(url("/WebGoat/JWT/refresh/checkout")) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"), + CoreMatchers.is(true)); + } + + private void deleteTom() { + + Map<String, Object> header = new HashMap(); + header.put(Header.TYPE, Header.JWT_TYPE); + header.put( + JwsHeader.KEY_ID, + "hacked' UNION select 'deletingTom' from INFORMATION_SCHEMA.SYSTEM_USERS --"); + String token = + Jwts.builder() + .setHeader(header) + .setIssuer("WebGoat Token Builder") + .setAudience("webgoat.org") + .setIssuedAt(Calendar.getInstance().getTime()) + .setExpiration(Date.from(Instant.now().plusSeconds(60))) + .setSubject("tom@webgoat.org") + .claim("username", "Tom") + .claim("Email", "tom@webgoat.org") + .claim("Role", new String[] {"Manager", "Project Administrator"}) + .signWith(SignatureAlgorithm.HS256, "deletingTom") + .compact(); + + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .post(url("/WebGoat/JWT/final/delete?token=" + token)) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"), + CoreMatchers.is(true)); + } + + private void quiz() { + Map<String, Object> params = new HashMap<>(); + params.put("question_0_solution", "Solution 1"); + params.put("question_1_solution", "Solution 2"); + + checkAssignment(url("/WebGoat/JWT/quiz"), params, true); + } } diff --git a/src/it/java/org/owasp/webgoat/LabelAndHintIntegrationTest.java b/src/it/java/org/owasp/webgoat/LabelAndHintIntegrationTest.java index 1f99c15e7..ae6feb803 100644 --- a/src/it/java/org/owasp/webgoat/LabelAndHintIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/LabelAndHintIntegrationTest.java @@ -3,168 +3,228 @@ package org.owasp.webgoat; import io.restassured.RestAssured; import io.restassured.http.ContentType; import io.restassured.path.json.JsonPath; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - import java.io.FileInputStream; import java.io.InputStream; import java.util.List; import java.util.Properties; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class LabelAndHintIntegrationTest extends IntegrationTest { - final static String ESCAPE_JSON_PATH_CHAR = "\'"; + static final String ESCAPE_JSON_PATH_CHAR = "\'"; - @Test - public void testSingleLabel() { - Assertions.assertTrue(true); - JsonPath jsonPath = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .contentType(ContentType.JSON) - .header("Accept-Language","en") - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("service/labels.mvc")).then().statusCode(200).extract().jsonPath(); + @Test + public void testSingleLabel() { + Assertions.assertTrue(true); + JsonPath jsonPath = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .contentType(ContentType.JSON) + .header("Accept-Language", "en") + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("service/labels.mvc")) + .then() + .statusCode(200) + .extract() + .jsonPath(); - Assertions.assertEquals("Try again: but this time enter a value before hitting go.", jsonPath.getString(ESCAPE_JSON_PATH_CHAR+"http-basics.close"+ESCAPE_JSON_PATH_CHAR)); + Assertions.assertEquals( + "Try again: but this time enter a value before hitting go.", + jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "http-basics.close" + ESCAPE_JSON_PATH_CHAR)); - // check if lang parameter overrules Accept-Language parameter - jsonPath = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .contentType(ContentType.JSON) - .header("Accept-Language","en") - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("service/labels.mvc?lang=nl")).then().statusCode(200).extract().jsonPath(); - Assertions.assertEquals("Gebruikersnaam", jsonPath.getString(ESCAPE_JSON_PATH_CHAR+"username"+ESCAPE_JSON_PATH_CHAR)); + // check if lang parameter overrules Accept-Language parameter + jsonPath = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .contentType(ContentType.JSON) + .header("Accept-Language", "en") + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("service/labels.mvc?lang=nl")) + .then() + .statusCode(200) + .extract() + .jsonPath(); + Assertions.assertEquals( + "Gebruikersnaam", + jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR)); - jsonPath = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .contentType(ContentType.JSON) - .header("Accept-Language","en") - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("service/labels.mvc?lang=de")).then().statusCode(200).extract().jsonPath(); - Assertions.assertEquals("Benutzername", jsonPath.getString(ESCAPE_JSON_PATH_CHAR+"username"+ESCAPE_JSON_PATH_CHAR)); + jsonPath = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .contentType(ContentType.JSON) + .header("Accept-Language", "en") + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("service/labels.mvc?lang=de")) + .then() + .statusCode(200) + .extract() + .jsonPath(); + Assertions.assertEquals( + "Benutzername", + jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR)); - // check if invalid language returns english - jsonPath = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .contentType(ContentType.JSON) - .header("Accept-Language","nl") - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("service/labels.mvc?lang=xx")).then().statusCode(200).extract().jsonPath(); - Assertions.assertEquals("Username", jsonPath.getString(ESCAPE_JSON_PATH_CHAR+"username"+ESCAPE_JSON_PATH_CHAR)); + // check if invalid language returns english + jsonPath = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .contentType(ContentType.JSON) + .header("Accept-Language", "nl") + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("service/labels.mvc?lang=xx")) + .then() + .statusCode(200) + .extract() + .jsonPath(); + Assertions.assertEquals( + "Username", jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR)); - // check if invalid language returns english - jsonPath = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .contentType(ContentType.JSON) - .header("Accept-Language","xx_YY") - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("service/labels.mvc")).then().statusCode(200).extract().jsonPath(); - Assertions.assertEquals("Username", jsonPath.getString(ESCAPE_JSON_PATH_CHAR+"username"+ESCAPE_JSON_PATH_CHAR)); + // check if invalid language returns english + jsonPath = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .contentType(ContentType.JSON) + .header("Accept-Language", "xx_YY") + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("service/labels.mvc")) + .then() + .statusCode(200) + .extract() + .jsonPath(); + Assertions.assertEquals( + "Username", jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR)); + } + @Test + public void testHints() { + JsonPath jsonPathLabels = getLabels("en"); + List<String> allLessons = + List.of( + "HttpBasics", + "HttpProxies", + "CIA", + "InsecureLogin", + "Cryptography", + "PathTraversal", + "XXE", + "JWT", + "IDOR", + "SSRF", + "WebWolfIntroduction", + "CrossSiteScripting", + "CSRF", + "HijackSession", + "SqlInjection", + "SqlInjectionMitigations", + "SqlInjectionAdvanced", + "Challenge1"); + for (String lesson : allLessons) { + startLesson(lesson); + List<String> hintKeys = getHints(); + for (String key : hintKeys) { + String keyValue = + jsonPathLabels.getString(ESCAPE_JSON_PATH_CHAR + key + ESCAPE_JSON_PATH_CHAR); + // System.out.println("key: " + key + " ,value: " + keyValue); + Assertions.assertNotNull(keyValue); + Assertions.assertNotEquals(key, keyValue); + } } + // Assertions.assertEquals("http-basics.hints.http_basics_lesson.1", + // ""+jsonPath.getList("hint").get(0)); + } - @Test - public void testHints() { - JsonPath jsonPathLabels = getLabels("en"); - List<String> allLessons = List.of( - "HttpBasics", - "HttpProxies", "CIA", "InsecureLogin", "Cryptography", "PathTraversal", - "XXE", "JWT", "IDOR", "SSRF", "WebWolfIntroduction", "CrossSiteScripting", "CSRF", "HijackSession", - "SqlInjection", "SqlInjectionMitigations" ,"SqlInjectionAdvanced", - "Challenge1"); - for (String lesson: allLessons) { - startLesson(lesson); - List<String> hintKeys = getHints(); - for (String key : hintKeys) { - String keyValue = jsonPathLabels.getString(ESCAPE_JSON_PATH_CHAR + key + ESCAPE_JSON_PATH_CHAR); - //System.out.println("key: " + key + " ,value: " + keyValue); - Assertions.assertNotNull(keyValue); - Assertions.assertNotEquals(key, keyValue); - } - } - //Assertions.assertEquals("http-basics.hints.http_basics_lesson.1", ""+jsonPath.getList("hint").get(0)); + @Test + public void testLabels() { + + JsonPath jsonPathLabels = getLabels("en"); + Properties propsDefault = getProperties(""); + for (String key : propsDefault.stringPropertyNames()) { + String keyValue = + jsonPathLabels.getString(ESCAPE_JSON_PATH_CHAR + key + ESCAPE_JSON_PATH_CHAR); + Assertions.assertNotNull(keyValue); } + checkLang(propsDefault, "nl"); + checkLang(propsDefault, "de"); + checkLang(propsDefault, "fr"); + checkLang(propsDefault, "ru"); + } - @Test - public void testLabels() { - - JsonPath jsonPathLabels = getLabels("en"); - Properties propsDefault = getProperties(""); - for (String key: propsDefault.stringPropertyNames()) { - String keyValue = jsonPathLabels.getString(ESCAPE_JSON_PATH_CHAR+key+ESCAPE_JSON_PATH_CHAR); - Assertions.assertNotNull(keyValue); - } - checkLang(propsDefault,"nl"); - checkLang(propsDefault,"de"); - checkLang(propsDefault,"fr"); - checkLang(propsDefault,"ru"); - + private Properties getProperties(String lang) { + Properties prop = null; + if (lang == null || lang.equals("")) { + lang = ""; + } else { + lang = "_" + lang; } + try (InputStream input = + new FileInputStream("src/main/resources/i18n/messages" + lang + ".properties")) { - private Properties getProperties(String lang) { - Properties prop = null; - if (lang == null || lang.equals("")) { lang = ""; } else { lang = "_"+lang; } - try (InputStream input = new FileInputStream("src/main/resources/i18n/messages"+lang+".properties")) { - - prop = new Properties(); - // load a properties file - prop.load(input); - } catch (Exception e) { - e.printStackTrace(); - } - return prop; + prop = new Properties(); + // load a properties file + prop.load(input); + } catch (Exception e) { + e.printStackTrace(); } + return prop; + } - private void checkLang(Properties propsDefault, String lang) { - JsonPath jsonPath = getLabels(lang); - Properties propsLang = getProperties(lang); + private void checkLang(Properties propsDefault, String lang) { + JsonPath jsonPath = getLabels(lang); + Properties propsLang = getProperties(lang); - for (String key: propsLang.stringPropertyNames()) { - if (!propsDefault.containsKey(key)) { - System.err.println("key: " + key + " in (" +lang+") is missing from default properties"); - Assertions.fail(); - } - if (!jsonPath.getString(ESCAPE_JSON_PATH_CHAR+key+ESCAPE_JSON_PATH_CHAR).equals(propsLang.get(key))) { - System.out.println("key: " + key + " in (" +lang+") has incorrect translation in label service"); - System.out.println("actual:"+jsonPath.getString(ESCAPE_JSON_PATH_CHAR+key+ESCAPE_JSON_PATH_CHAR)); - System.out.println("expected: "+propsLang.getProperty(key)); - System.out.println(); - Assertions.fail(); - } - } + for (String key : propsLang.stringPropertyNames()) { + if (!propsDefault.containsKey(key)) { + System.err.println("key: " + key + " in (" + lang + ") is missing from default properties"); + Assertions.fail(); + } + if (!jsonPath + .getString(ESCAPE_JSON_PATH_CHAR + key + ESCAPE_JSON_PATH_CHAR) + .equals(propsLang.get(key))) { + System.out.println( + "key: " + key + " in (" + lang + ") has incorrect translation in label service"); + System.out.println( + "actual:" + jsonPath.getString(ESCAPE_JSON_PATH_CHAR + key + ESCAPE_JSON_PATH_CHAR)); + System.out.println("expected: " + propsLang.getProperty(key)); + System.out.println(); + Assertions.fail(); + } } + } - private JsonPath getLabels(String lang) { - return RestAssured.given() - .when() - .relaxedHTTPSValidation() - .contentType(ContentType.JSON) - .header("Accept-Language",lang) - .cookie("JSESSIONID", getWebGoatCookie()) - //.log().headers() - .get(url("service/labels.mvc")) - .then() - //.log().all() - .statusCode(200).extract().jsonPath(); - } - - private List<String> getHints() { - JsonPath jsonPath = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .contentType(ContentType.JSON) - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("service/hint.mvc")) - .then() - //.log().all() - .statusCode(200).extract().jsonPath(); - return jsonPath.getList("hint"); - } + private JsonPath getLabels(String lang) { + return RestAssured.given() + .when() + .relaxedHTTPSValidation() + .contentType(ContentType.JSON) + .header("Accept-Language", lang) + .cookie("JSESSIONID", getWebGoatCookie()) + // .log().headers() + .get(url("service/labels.mvc")) + .then() + // .log().all() + .statusCode(200) + .extract() + .jsonPath(); + } + private List<String> getHints() { + JsonPath jsonPath = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .contentType(ContentType.JSON) + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("service/hint.mvc")) + .then() + // .log().all() + .statusCode(200) + .extract() + .jsonPath(); + return jsonPath.getList("hint"); + } } diff --git a/src/it/java/org/owasp/webgoat/PasswordResetLessonIntegrationTest.java b/src/it/java/org/owasp/webgoat/PasswordResetLessonIntegrationTest.java index 6e030d039..e791634ea 100644 --- a/src/it/java/org/owasp/webgoat/PasswordResetLessonIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/PasswordResetLessonIntegrationTest.java @@ -1,8 +1,11 @@ package org.owasp.webgoat; -import io.restassured.RestAssured; -import lombok.SneakyThrows; +import static org.junit.jupiter.api.DynamicTest.dynamicTest; +import io.restassured.RestAssured; +import java.util.Arrays; +import java.util.Map; +import lombok.SneakyThrows; import org.apache.commons.lang3.StringUtils; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.AfterEach; @@ -10,109 +13,137 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; -import static org.junit.jupiter.api.DynamicTest.dynamicTest; - -import java.util.Arrays; -import java.util.Map; - public class PasswordResetLessonIntegrationTest extends IntegrationTest { - @BeforeEach - @SneakyThrows - public void init() { - startLesson("/PasswordReset"); - } - - @TestFactory - Iterable<DynamicTest> passwordResetLesson() { - return Arrays.asList( - dynamicTest("assignment 6 - check email link",()-> sendEmailShouldBeAvailableInWebWolf()), - dynamicTest("assignment 6 - solve assignment",()-> solveAssignment()), - dynamicTest("assignment 2 - simple reset",()-> assignment2()), - dynamicTest("assignment 4 - guess questions",()-> assignment4()), - dynamicTest("assignment 5 - simple questions",()-> assignment5()) - ); - } - public void assignment2() { - checkAssignment(url("PasswordReset/simple-mail/reset"), Map.of("emailReset", this.getUser()+"@webgoat.org"), false); - checkAssignment(url("PasswordReset/simple-mail"), Map.of("email", this.getUser()+"@webgoat.org", "password", StringUtils.reverse(this.getUser())), true); - } - - public void assignment4() { - checkAssignment(url("PasswordReset/questions"), Map.of("username", "tom", "securityQuestion", "purple"), true); - } - - public void assignment5() { - checkAssignment(url("PasswordReset/SecurityQuestions"), Map.of("question", "What is your favorite animal?"), false); - checkAssignment(url("PasswordReset/SecurityQuestions"), Map.of("question", "What is your favorite color?"), true); - } + @BeforeEach + @SneakyThrows + public void init() { + startLesson("/PasswordReset"); + } - - public void solveAssignment() { - //WebGoat - clickForgotEmailLink("tom@webgoat-cloud.org"); + @TestFactory + Iterable<DynamicTest> passwordResetLesson() { + return Arrays.asList( + dynamicTest("assignment 6 - check email link", () -> sendEmailShouldBeAvailableInWebWolf()), + dynamicTest("assignment 6 - solve assignment", () -> solveAssignment()), + dynamicTest("assignment 2 - simple reset", () -> assignment2()), + dynamicTest("assignment 4 - guess questions", () -> assignment4()), + dynamicTest("assignment 5 - simple questions", () -> assignment5())); + } - //WebWolf - var link = getPasswordResetLinkFromLandingPage(); + public void assignment2() { + checkAssignment( + url("PasswordReset/simple-mail/reset"), + Map.of("emailReset", this.getUser() + "@webgoat.org"), + false); + checkAssignment( + url("PasswordReset/simple-mail"), + Map.of( + "email", + this.getUser() + "@webgoat.org", + "password", + StringUtils.reverse(this.getUser())), + true); + } - //WebGoat - changePassword(link); - checkAssignment(url("PasswordReset/reset/login"), Map.of("email", "tom@webgoat-cloud.org", "password", "123456"), true); - } + public void assignment4() { + checkAssignment( + url("PasswordReset/questions"), + Map.of("username", "tom", "securityQuestion", "purple"), + true); + } - public void sendEmailShouldBeAvailableInWebWolf() { - clickForgotEmailLink(this.getUser() + "@webgoat.org"); + public void assignment5() { + checkAssignment( + url("PasswordReset/SecurityQuestions"), + Map.of("question", "What is your favorite animal?"), + false); + checkAssignment( + url("PasswordReset/SecurityQuestions"), + Map.of("question", "What is your favorite color?"), + true); + } - var responseBody = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("WEBWOLFSESSION", getWebWolfCookie()) - .get(webWolfUrl("/WebWolf/mail")) - .then() - .extract().response().getBody().asString(); + public void solveAssignment() { + // WebGoat + clickForgotEmailLink("tom@webgoat-cloud.org"); - Assertions.assertThat(responseBody).contains("Hi, you requested a password reset link"); - } - - @AfterEach - public void shutdown() { - //this will run only once after the list of dynamic tests has run, this is to test if the lesson is marked complete - checkResults("/PasswordReset"); - } + // WebWolf + var link = getPasswordResetLinkFromLandingPage(); - private void changePassword(String link) { + // WebGoat + changePassword(link); + checkAssignment( + url("PasswordReset/reset/login"), + Map.of("email", "tom@webgoat-cloud.org", "password", "123456"), + true); + } + + public void sendEmailShouldBeAvailableInWebWolf() { + clickForgotEmailLink(this.getUser() + "@webgoat.org"); + + var responseBody = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .formParams("resetLink", link, "password", "123456") - .post(url("PasswordReset/reset/change-password")) - .then() - .statusCode(200); - } + .when() + .relaxedHTTPSValidation() + .cookie("WEBWOLFSESSION", getWebWolfCookie()) + .get(webWolfUrl("/WebWolf/mail")) + .then() + .extract() + .response() + .getBody() + .asString(); - private String getPasswordResetLinkFromLandingPage() { - var responseBody = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("WEBWOLFSESSION", getWebWolfCookie()) - .get(webWolfUrl("/WebWolf/requests")) - .then() - .extract().response().getBody().asString(); - int startIndex = responseBody.lastIndexOf("/PasswordReset/reset/reset-password/"); - var link = responseBody.substring(startIndex + "/PasswordReset/reset/reset-password/".length(), responseBody.indexOf(",", startIndex) - 1); - return link; - } + Assertions.assertThat(responseBody).contains("Hi, you requested a password reset link"); + } - private void clickForgotEmailLink(String user) { + @AfterEach + public void shutdown() { + // this will run only once after the list of dynamic tests has run, this is to test if the + // lesson is marked complete + checkResults("/PasswordReset"); + } + + private void changePassword(String link) { + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .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() - .header("host", String.format("%s:%s", "localhost", getWebWolfPort())) - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .formParams("email", user) - .post(url("PasswordReset/ForgotPassword/create-password-reset-link")) - .then() - .statusCode(200); - } + .when() + .relaxedHTTPSValidation() + .cookie("WEBWOLFSESSION", getWebWolfCookie()) + .get(webWolfUrl("/WebWolf/requests")) + .then() + .extract() + .response() + .getBody() + .asString(); + int startIndex = responseBody.lastIndexOf("/PasswordReset/reset/reset-password/"); + var link = + responseBody.substring( + startIndex + "/PasswordReset/reset/reset-password/".length(), + responseBody.indexOf(",", startIndex) - 1); + return link; + } + + private void clickForgotEmailLink(String user) { + RestAssured.given() + .when() + .header("host", String.format("%s:%s", "localhost", getWebWolfPort())) + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .formParams("email", user) + .post(url("PasswordReset/ForgotPassword/create-password-reset-link")) + .then() + .statusCode(200); + } } diff --git a/src/it/java/org/owasp/webgoat/PathTraversalIntegrationTest.java b/src/it/java/org/owasp/webgoat/PathTraversalIntegrationTest.java index 3eb53ee8e..cc00818f8 100644 --- a/src/it/java/org/owasp/webgoat/PathTraversalIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/PathTraversalIntegrationTest.java @@ -1,16 +1,8 @@ package org.owasp.webgoat; -import io.restassured.RestAssured; -import lombok.SneakyThrows; -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DynamicTest; -import org.junit.jupiter.api.TestFactory; -import org.junit.jupiter.api.io.TempDir; -import org.springframework.security.core.token.Sha512DigestUtils; +import static org.junit.jupiter.api.DynamicTest.dynamicTest; +import io.restassured.RestAssured; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -21,117 +13,138 @@ import java.util.Arrays; import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; - -import static org.junit.jupiter.api.DynamicTest.dynamicTest; +import lombok.SneakyThrows; +import org.hamcrest.CoreMatchers; +import org.hamcrest.MatcherAssert; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.TestFactory; +import org.junit.jupiter.api.io.TempDir; +import org.springframework.security.core.token.Sha512DigestUtils; class PathTraversalIT extends IntegrationTest { - @TempDir - Path tempDir; + @TempDir Path tempDir; - private File fileToUpload = null; + private File fileToUpload = null; - @BeforeEach - @SneakyThrows - public void init() { - fileToUpload = Files.createFile(tempDir.resolve("test.jpg")).toFile(); - Files.write(fileToUpload.toPath(), "This is a test".getBytes()); - startLesson("PathTraversal"); + @BeforeEach + @SneakyThrows + public void init() { + fileToUpload = Files.createFile(tempDir.resolve("test.jpg")).toFile(); + Files.write(fileToUpload.toPath(), "This is a test".getBytes()); + startLesson("PathTraversal"); + } + + @TestFactory + Iterable<DynamicTest> testPathTraversal() { + return Arrays.asList( + dynamicTest("assignment 1 - profile upload", () -> assignment1()), + dynamicTest("assignment 2 - profile upload fix", () -> assignment2()), + dynamicTest("assignment 3 - profile upload remove user input", () -> assignment3()), + dynamicTest("assignment 4 - profile upload random pic", () -> assignment4()), + dynamicTest("assignment 5 - zip slip", () -> assignment5())); + } + + private void assignment1() throws IOException { + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .multiPart("uploadedFile", "test.jpg", Files.readAllBytes(fileToUpload.toPath())) + .param("fullName", "../John Doe") + .post(url("/WebGoat/PathTraversal/profile-upload")) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"), + CoreMatchers.is(true)); + } + + private void assignment2() throws IOException { + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .multiPart("uploadedFileFix", "test.jpg", Files.readAllBytes(fileToUpload.toPath())) + .param("fullNameFix", "..././John Doe") + .post(url("/WebGoat/PathTraversal/profile-upload-fix")) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"), + CoreMatchers.is(true)); + } + + private void assignment3() throws IOException { + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .multiPart( + "uploadedFileRemoveUserInput", + "../test.jpg", + Files.readAllBytes(fileToUpload.toPath())) + .post(url("/WebGoat/PathTraversal/profile-upload-remove-user-input")) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"), + CoreMatchers.is(true)); + } + + private void assignment4() throws IOException { + var uri = "/WebGoat/PathTraversal/random-picture?id=%2E%2E%2F%2E%2E%2Fpath-traversal-secret"; + RestAssured.given() + .urlEncodingEnabled(false) + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url(uri)) + .then() + .statusCode(200) + .body(CoreMatchers.is("You found it submit the SHA-512 hash of your username as answer")); + + checkAssignment( + url("/WebGoat/PathTraversal/random"), + Map.of("secret", Sha512DigestUtils.shaHex(this.getUser())), + true); + } + + private void assignment5() throws IOException { + var webGoatHome = webGoatServerDirectory() + "PathTraversal/" + this.getUser(); + webGoatHome = + webGoatHome.replaceAll("^[a-zA-Z]:", ""); // Remove C: from the home directory on Windows + + var webGoatDirectory = new File(webGoatHome); + var zipFile = new File(tempDir.toFile(), "upload.zip"); + try (var zos = new ZipOutputStream(new FileOutputStream(zipFile))) { + ZipEntry e = new ZipEntry("../../../../../../../../../../" + webGoatDirectory + "/image.jpg"); + zos.putNextEntry(e); + zos.write("test".getBytes(StandardCharsets.UTF_8)); } + MatcherAssert.assertThat( + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .multiPart("uploadedFileZipSlip", "upload.zip", Files.readAllBytes(zipFile.toPath())) + .post(url("/WebGoat/PathTraversal/zip-slip")) + .then() + .statusCode(200) + .extract() + .path("lessonCompleted"), + CoreMatchers.is(true)); + } - @TestFactory - Iterable<DynamicTest> testPathTraversal() { - return Arrays.asList( - dynamicTest("assignment 1 - profile upload", () -> assignment1()), - dynamicTest("assignment 2 - profile upload fix", () -> assignment2()), - dynamicTest("assignment 3 - profile upload remove user input", () -> assignment3()), - dynamicTest("assignment 4 - profile upload random pic", () -> assignment4()), - dynamicTest("assignment 5 - zip slip", () -> assignment5()) - ); - } - - private void assignment1() throws IOException { - MatcherAssert.assertThat( - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .multiPart("uploadedFile", "test.jpg", Files.readAllBytes(fileToUpload.toPath())) - .param("fullName", "../John Doe") - .post(url("/WebGoat/PathTraversal/profile-upload")) - .then() - .statusCode(200) - .extract().path("lessonCompleted"), CoreMatchers.is(true)); - } - - private void assignment2() throws IOException { - MatcherAssert.assertThat( - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .multiPart("uploadedFileFix", "test.jpg", Files.readAllBytes(fileToUpload.toPath())) - .param("fullNameFix", "..././John Doe") - .post(url("/WebGoat/PathTraversal/profile-upload-fix")) - .then() - .statusCode(200) - .extract().path("lessonCompleted"), CoreMatchers.is(true)); - } - - private void assignment3() throws IOException { - MatcherAssert.assertThat( - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .multiPart("uploadedFileRemoveUserInput", "../test.jpg", Files.readAllBytes(fileToUpload.toPath())) - .post(url("/WebGoat/PathTraversal/profile-upload-remove-user-input")) - .then() - .statusCode(200) - .extract().path("lessonCompleted"), CoreMatchers.is(true)); - } - - private void assignment4() throws IOException { - var uri = "/WebGoat/PathTraversal/random-picture?id=%2E%2E%2F%2E%2E%2Fpath-traversal-secret"; - RestAssured.given().urlEncodingEnabled(false) - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url(uri)) - .then() - .statusCode(200) - .body(CoreMatchers.is("You found it submit the SHA-512 hash of your username as answer")); - - checkAssignment(url("/WebGoat/PathTraversal/random"), Map.of("secret", - Sha512DigestUtils.shaHex(this.getUser())), true); - } - - private void assignment5() throws IOException { - var webGoatHome = webGoatServerDirectory() + "PathTraversal/" + this.getUser(); - webGoatHome = webGoatHome.replaceAll("^[a-zA-Z]:", ""); //Remove C: from the home directory on Windows - - var webGoatDirectory = new File(webGoatHome); - var zipFile = new File(tempDir.toFile(), "upload.zip"); - try (var zos = new ZipOutputStream(new FileOutputStream(zipFile))) { - ZipEntry e = new ZipEntry("../../../../../../../../../../" + webGoatDirectory + "/image.jpg"); - zos.putNextEntry(e); - zos.write("test".getBytes(StandardCharsets.UTF_8)); - } - MatcherAssert.assertThat( - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .multiPart("uploadedFileZipSlip", "upload.zip", Files.readAllBytes(zipFile.toPath())) - .post(url("/WebGoat/PathTraversal/zip-slip")) - .then() - .statusCode(200) - .extract().path("lessonCompleted"), CoreMatchers.is(true)); - } - - @AfterEach - void shutdown() { - //this will run only once after the list of dynamic tests has run, this is to test if the lesson is marked complete - checkResults("/PathTraversal"); - } + @AfterEach + void shutdown() { + // this will run only once after the list of dynamic tests has run, this is to test if the + // lesson is marked complete + checkResults("/PathTraversal"); + } } diff --git a/src/it/java/org/owasp/webgoat/ProgressRaceConditionIntegrationTest.java b/src/it/java/org/owasp/webgoat/ProgressRaceConditionIntegrationTest.java index 8b8b870ea..016f6b35d 100644 --- a/src/it/java/org/owasp/webgoat/ProgressRaceConditionIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/ProgressRaceConditionIntegrationTest.java @@ -2,10 +2,6 @@ package org.owasp.webgoat; import io.restassured.RestAssured; import io.restassured.response.Response; - -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.Test; - import java.util.List; import java.util.Map; import java.util.concurrent.Callable; @@ -14,40 +10,48 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.Collectors; import java.util.stream.IntStream; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; public class ProgressRaceConditionIntegrationTest extends IntegrationTest { - @Test - public void runTests() throws InterruptedException { - int NUMBER_OF_CALLS = 40; - int NUMBER_OF_PARALLEL_THREADS = 5; - startLesson("Challenge1"); - - Callable<Response> call = () -> { - //System.out.println("thread "+Thread.currentThread().getName()); - return RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .formParams(Map.of("flag", "test")) - .post(url("/challenge/flag/")); + @Test + public void runTests() throws InterruptedException { + int NUMBER_OF_CALLS = 40; + int NUMBER_OF_PARALLEL_THREADS = 5; + startLesson("Challenge1"); + Callable<Response> call = + () -> { + // System.out.println("thread "+Thread.currentThread().getName()); + return RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .formParams(Map.of("flag", "test")) + .post(url("/challenge/flag/")); }; - ExecutorService executorService = Executors.newWorkStealingPool(NUMBER_OF_PARALLEL_THREADS); - List<? extends Callable<Response>> flagCalls = IntStream.range(0, NUMBER_OF_CALLS).mapToObj(i -> call).collect(Collectors.toList()); - var responses = executorService.invokeAll(flagCalls); + ExecutorService executorService = Executors.newWorkStealingPool(NUMBER_OF_PARALLEL_THREADS); + List<? extends Callable<Response>> flagCalls = + IntStream.range(0, NUMBER_OF_CALLS).mapToObj(i -> call).collect(Collectors.toList()); + var responses = executorService.invokeAll(flagCalls); - //A certain amount of parallel calls should fail as optimistic locking in DB is applied - long countStatusCode500 = responses.stream().filter(r -> { - try { - //System.err.println(r.get().getStatusCode()); - return r.get().getStatusCode() != 200; - } catch (InterruptedException | ExecutionException e) { - //System.err.println(e); - throw new IllegalStateException(e); - } - }).count(); - System.err.println("counted status 500: "+countStatusCode500); - Assertions.assertThat(countStatusCode500).isLessThanOrEqualTo((NUMBER_OF_CALLS - (NUMBER_OF_CALLS/NUMBER_OF_PARALLEL_THREADS))); - } + // A certain amount of parallel calls should fail as optimistic locking in DB is applied + long countStatusCode500 = + responses.stream() + .filter( + r -> { + try { + // System.err.println(r.get().getStatusCode()); + return r.get().getStatusCode() != 200; + } catch (InterruptedException | ExecutionException e) { + // System.err.println(e); + throw new IllegalStateException(e); + } + }) + .count(); + System.err.println("counted status 500: " + countStatusCode500); + Assertions.assertThat(countStatusCode500) + .isLessThanOrEqualTo((NUMBER_OF_CALLS - (NUMBER_OF_CALLS / NUMBER_OF_PARALLEL_THREADS))); + } } diff --git a/src/it/java/org/owasp/webgoat/SSRFIntegrationTest.java b/src/it/java/org/owasp/webgoat/SSRFIntegrationTest.java index e59499108..0bdd74e1f 100644 --- a/src/it/java/org/owasp/webgoat/SSRFIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/SSRFIntegrationTest.java @@ -3,28 +3,24 @@ package org.owasp.webgoat; import java.io.IOException; import java.util.HashMap; import java.util.Map; - import org.junit.jupiter.api.Test; public class SSRFIntegrationTest extends IntegrationTest { - - @Test - public void runTests() throws IOException { - startLesson("SSRF"); - - Map<String, Object> params = new HashMap<>(); - params.clear(); - params.put("url", "images/jerry.png"); - - checkAssignment(url("/WebGoat/SSRF/task1"),params,true); - params.clear(); - params.put("url", "http://ifconfig.pro"); - - checkAssignment(url("/WebGoat/SSRF/task2"),params,true); - - checkResults("/SSRF/"); - - } - - + + @Test + public void runTests() throws IOException { + startLesson("SSRF"); + + Map<String, Object> params = new HashMap<>(); + params.clear(); + params.put("url", "images/jerry.png"); + + checkAssignment(url("/WebGoat/SSRF/task1"), params, true); + params.clear(); + params.put("url", "http://ifconfig.pro"); + + checkAssignment(url("/WebGoat/SSRF/task2"), params, true); + + checkResults("/SSRF/"); + } } diff --git a/src/it/java/org/owasp/webgoat/SessionManagementIntegrationTest.java b/src/it/java/org/owasp/webgoat/SessionManagementIntegrationTest.java index ad641212b..127490106 100644 --- a/src/it/java/org/owasp/webgoat/SessionManagementIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/SessionManagementIntegrationTest.java @@ -24,24 +24,22 @@ package org.owasp.webgoat; import java.util.Map; - import org.junit.jupiter.api.Test; /** - * * @author Angel Olle Blazquez - * */ - class SessionManagementIT extends IntegrationTest { - - private static final String HIJACK_LOGIN_CONTEXT_PATH = "/WebGoat/HijackSession/login"; + private static final String HIJACK_LOGIN_CONTEXT_PATH = "/WebGoat/HijackSession/login"; - @Test - void hijackSessionTest() { - startLesson("HijackSession"); - - checkAssignment(url(HIJACK_LOGIN_CONTEXT_PATH), Map.of("username", "webgoat", "password", "webgoat"), false); - } + @Test + void hijackSessionTest() { + startLesson("HijackSession"); + + checkAssignment( + url(HIJACK_LOGIN_CONTEXT_PATH), + Map.of("username", "webgoat", "password", "webgoat"), + false); + } } diff --git a/src/it/java/org/owasp/webgoat/SqlInjectionAdvancedIntegrationTest.java b/src/it/java/org/owasp/webgoat/SqlInjectionAdvancedIntegrationTest.java index 6ae9f838b..64caf659d 100644 --- a/src/it/java/org/owasp/webgoat/SqlInjectionAdvancedIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/SqlInjectionAdvancedIntegrationTest.java @@ -2,48 +2,60 @@ package org.owasp.webgoat; import java.util.HashMap; import java.util.Map; - import org.junit.jupiter.api.Test; public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest { - @Test - public void runTests() { - startLesson("SqlInjectionAdvanced"); + @Test + public void runTests() { + startLesson("SqlInjectionAdvanced"); - Map<String, Object> 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); + Map<String, Object> 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("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", "'; 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_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("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); + 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/"); - } + checkResults("/SqlInjectionAdvanced/"); + } } diff --git a/src/it/java/org/owasp/webgoat/SqlInjectionLessonIntegrationTest.java b/src/it/java/org/owasp/webgoat/SqlInjectionLessonIntegrationTest.java index 6c8c446af..c18fb8b0e 100644 --- a/src/it/java/org/owasp/webgoat/SqlInjectionLessonIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/SqlInjectionLessonIntegrationTest.java @@ -2,77 +2,77 @@ package org.owasp.webgoat; import java.util.HashMap; import java.util.Map; - import org.junit.jupiter.api.Test; public class SqlInjectionLessonIntegrationTest extends IntegrationTest { - public static final String sql_2 = "select department from employees where last_name='Franco'"; - public static final String sql_3 = "update employees set department='Sales' where last_name='Barnett'"; - public static final String sql_4_drop = "alter table employees drop column phone"; - public static final String sql_4_add = "alter table employees add column phone varchar(20)"; - public static final String sql_5 = "grant select on grant_rights to unauthorized_user"; - public static final String sql_9_account = " ' "; - public static final String sql_9_operator = "or"; - public static final String sql_9_injection = "'1'='1"; - public static final String sql_10_login_count = "2"; - public static final String sql_10_userid = "1 or 1=1"; + public static final String sql_2 = "select department from employees where last_name='Franco'"; + public static final String sql_3 = + "update employees set department='Sales' where last_name='Barnett'"; + public static final String sql_4_drop = "alter table employees drop column phone"; + public static final String sql_4_add = "alter table employees add column phone varchar(20)"; + public static final String sql_5 = "grant select on grant_rights to unauthorized_user"; + public static final String sql_9_account = " ' "; + public static final String sql_9_operator = "or"; + public static final String sql_9_injection = "'1'='1"; + public static final String sql_10_login_count = "2"; + public static final String sql_10_userid = "1 or 1=1"; - public static final String sql_11_a = "Smith' or '1' = '1"; - public static final String sql_11_b = "3SL99A' or '1'='1"; + public static final String sql_11_a = "Smith' or '1' = '1"; + public static final String sql_11_b = "3SL99A' or '1'='1"; - public static final String sql_12_a = "Smith"; - public static final String sql_12_b = "3SL99A' ; update employees set salary= '100000' where last_name='Smith"; + public static final String sql_12_a = "Smith"; + public static final String sql_12_b = + "3SL99A' ; update employees set salary= '100000' where last_name='Smith"; - public static final String sql_13 = "%update% '; drop table access_log ; --'"; + public static final String sql_13 = "%update% '; drop table access_log ; --'"; - @Test - public void runTests() { - startLesson("SqlInjection"); + @Test + public void runTests() { + startLesson("SqlInjection"); - Map<String, Object> params = new HashMap<>(); - params.clear(); - params.put("query", sql_2); - checkAssignment(url("/WebGoat/SqlInjection/attack2"), params, true); + Map<String, Object> 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_3); + checkAssignment(url("/WebGoat/SqlInjection/attack3"), params, true); - params.clear(); - params.put("query", sql_4_add); - checkAssignment(url("/WebGoat/SqlInjection/attack4"), params, true); + 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("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("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("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_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("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); + params.clear(); + params.put("action_string", sql_13); + checkAssignment(url("/WebGoat/SqlInjection/attack10"), params, true); - checkResults("/SqlInjection/"); - - } + checkResults("/SqlInjection/"); + } } diff --git a/src/it/java/org/owasp/webgoat/SqlInjectionMitigationIntegrationTest.java b/src/it/java/org/owasp/webgoat/SqlInjectionMitigationIntegrationTest.java index 6d9394674..b09bbc4d4 100644 --- a/src/it/java/org/owasp/webgoat/SqlInjectionMitigationIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/SqlInjectionMitigationIntegrationTest.java @@ -1,70 +1,85 @@ package org.owasp.webgoat; -import io.restassured.RestAssured; -import io.restassured.http.ContentType; - -import java.util.HashMap; -import java.util.Map; - -import org.junit.jupiter.api.Test; - import static org.hamcrest.CoreMatchers.containsString; +import io.restassured.RestAssured; +import io.restassured.http.ContentType; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.Test; + public class SqlInjectionMitigationIntegrationTest extends IntegrationTest { - @Test - public void runTests() { - startLesson("SqlInjectionMitigations"); + @Test + public void runTests() { + startLesson("SqlInjectionMitigations"); - Map<String, Object> 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); + Map<String, Object> 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); + 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); - params.clear(); - params.put("userid_sql_only_input_validation", "Smith';SELECT/**/*/**/from/**/user_system_data;--"); - checkAssignment(url("/WebGoat/SqlOnlyInputValidation/attack"), params, true); + params.clear(); + params.put( + "userid_sql_only_input_validation", "Smith';SELECT/**/*/**/from/**/user_system_data;--"); + checkAssignment(url("/WebGoat/SqlOnlyInputValidation/attack"), params, true); - params.clear(); - params.put("userid_sql_only_input_validation_on_keywords", "Smith';SESELECTLECT/**/*/**/FRFROMOM/**/user_system_data;--"); - checkAssignment(url("/WebGoat/SqlOnlyInputValidationOnKeywords/attack"), params, true); + params.clear(); + params.put( + "userid_sql_only_input_validation_on_keywords", + "Smith';SESELECTLECT/**/*/**/FRFROMOM/**/user_system_data;--"); + checkAssignment(url("/WebGoat/SqlOnlyInputValidationOnKeywords/attack"), params, true); - RestAssured.given() - .when().relaxedHTTPSValidation().cookie("JSESSIONID", getWebGoatCookie()) - .contentType(ContentType.JSON) - .get(url("/WebGoat/SqlInjectionMitigations/servers?column=(case when (true) then hostname else id end)")) - .then() - .statusCode(200); + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .contentType(ContentType.JSON) + .get( + url( + "/WebGoat/SqlInjectionMitigations/servers?column=(case when (true) then hostname" + + " else id end)")) + .then() + .statusCode(200); - RestAssured.given() - .when().relaxedHTTPSValidation().cookie("JSESSIONID", getWebGoatCookie()) - .contentType(ContentType.JSON) - .get(url("/WebGoat/SqlInjectionMitigations/servers?column=unknown")) - .then() - .statusCode(500) - .body("trace", containsString("select id, hostname, ip, mac, status, description from SERVERS where status <> 'out of order' order by")); + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .contentType(ContentType.JSON) + .get(url("/WebGoat/SqlInjectionMitigations/servers?column=unknown")) + .then() + .statusCode(500) + .body( + "trace", + containsString( + "select id, hostname, ip, mac, status, description from SERVERS where status <>" + + " 'out of order' order by")); - params.clear(); - params.put("ip", "104.130.219.202"); - checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack12a"), params, true); + params.clear(); + params.put("ip", "104.130.219.202"); + checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack12a"), params, true); - checkResults(); - } + checkResults(); + } } diff --git a/src/it/java/org/owasp/webgoat/WebWolfIntegrationTest.java b/src/it/java/org/owasp/webgoat/WebWolfIntegrationTest.java index 041f5157f..6c01aa361 100644 --- a/src/it/java/org/owasp/webgoat/WebWolfIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/WebWolfIntegrationTest.java @@ -2,71 +2,78 @@ package org.owasp.webgoat; import static org.junit.jupiter.api.Assertions.assertTrue; +import io.restassured.RestAssured; import java.io.IOException; import java.util.HashMap; import java.util.Map; - import org.junit.jupiter.api.Test; -import io.restassured.RestAssured; - public class WebWolfIntegrationTest extends IntegrationTest { - - @Test - public void runTests() throws IOException { - startLesson("WebWolfIntroduction"); - - //Assignment 3 - Map<String, Object> params = new HashMap<>(); - params.clear(); - params.put("email", this.getUser()+"@webgoat.org"); - checkAssignment(url("/WebGoat/WebWolf/mail/send"), params, false); - - String responseBody = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("WEBWOLFSESSION", getWebWolfCookie()) - .get(webWolfUrl("/WebWolf/mail")) - .then() - .extract().response().getBody().asString(); - - String uniqueCode = responseBody.replace("%20", " "); - uniqueCode = uniqueCode.substring(21+uniqueCode.lastIndexOf("your unique code is: "),uniqueCode.lastIndexOf("your unique code is: ")+(21+ this.getUser().length())); - params.clear(); - params.put("uniqueCode", uniqueCode); - checkAssignment(url("/WebGoat/WebWolf/mail"), params, true); - - //Assignment 4 - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .queryParams(params) - .get(url("/WebGoat/WebWolf/landing/password-reset")) - .then() - .statusCode(200); + + @Test + public void runTests() throws IOException { + startLesson("WebWolfIntroduction"); + + // Assignment 3 + Map<String, Object> params = new HashMap<>(); + params.clear(); + params.put("email", this.getUser() + "@webgoat.org"); + checkAssignment(url("/WebGoat/WebWolf/mail/send"), params, false); + + String responseBody = RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("WEBWOLFSESSION", getWebWolfCookie()) + .get(webWolfUrl("/WebWolf/mail")) + .then() + .extract() + .response() + .getBody() + .asString(); + + String uniqueCode = responseBody.replace("%20", " "); + uniqueCode = + uniqueCode.substring( + 21 + uniqueCode.lastIndexOf("your unique code is: "), + uniqueCode.lastIndexOf("your unique code is: ") + (21 + this.getUser().length())); + params.clear(); + params.put("uniqueCode", uniqueCode); + checkAssignment(url("/WebGoat/WebWolf/mail"), params, true); + + // Assignment 4 + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .queryParams(params) + .get(url("/WebGoat/WebWolf/landing/password-reset")) + .then() + .statusCode(200); + RestAssured.given() .when() .relaxedHTTPSValidation() .cookie("WEBWOLFSESSION", getWebWolfCookie()) .queryParams(params) - .get(webWolfUrl("/landing")) + .get(webWolfUrl("/landing")) .then() .statusCode(200); - responseBody = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("WEBWOLFSESSION", getWebWolfCookie()) - .get(webWolfUrl("/WebWolf/requests")) - .then() - .extract().response().getBody().asString(); - assertTrue(responseBody.contains(uniqueCode)); - params.clear(); - params.put("uniqueCode", uniqueCode); - checkAssignment(url("/WebGoat/WebWolf/landing"), params, true); - - checkResults("/WebWolf"); - - } - + responseBody = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("WEBWOLFSESSION", getWebWolfCookie()) + .get(webWolfUrl("/WebWolf/requests")) + .then() + .extract() + .response() + .getBody() + .asString(); + assertTrue(responseBody.contains(uniqueCode)); + params.clear(); + params.put("uniqueCode", uniqueCode); + checkAssignment(url("/WebGoat/WebWolf/landing"), params, true); + + checkResults("/WebWolf"); + } } diff --git a/src/it/java/org/owasp/webgoat/XSSIntegrationTest.java b/src/it/java/org/owasp/webgoat/XSSIntegrationTest.java index adae15d2c..64fc792d9 100644 --- a/src/it/java/org/owasp/webgoat/XSSIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/XSSIntegrationTest.java @@ -1,68 +1,80 @@ package org.owasp.webgoat; import io.restassured.RestAssured; - import java.util.HashMap; import java.util.Map; - import org.junit.jupiter.api.Test; public class XSSIntegrationTest extends IntegrationTest { - - @Test - public void crossSiteScriptingAssignments() { - startLesson("CrossSiteScripting"); + @Test + public void crossSiteScriptingAssignments() { + startLesson("CrossSiteScripting"); - Map<String, Object> params = new HashMap<>(); - params.clear(); - params.put("checkboxAttack1", "value"); - checkAssignment(url("/CrossSiteScripting/attack1"), params, true); + Map<String, Object> params = new HashMap<>(); + params.clear(); + params.put("checkboxAttack1", "value"); + checkAssignment(url("/CrossSiteScripting/attack1"), params, true); - params.clear(); - params.put("QTY1", "1"); - params.put("QTY2", "1"); - params.put("QTY3", "1"); - params.put("QTY4", "1"); - params.put("field1", "<script>alert('XSS+Test')</script>"); - params.put("field2", "111"); - checkAssignmentWithGet(url("/CrossSiteScripting/attack5a"), params, true); + params.clear(); + params.put("QTY1", "1"); + params.put("QTY2", "1"); + params.put("QTY3", "1"); + params.put("QTY4", "1"); + params.put("field1", "<script>alert('XSS+Test')</script>"); + params.put("field2", "111"); + checkAssignmentWithGet(url("/CrossSiteScripting/attack5a"), params, true); - params.clear(); - params.put("DOMTestRoute", "start.mvc#test"); - checkAssignment(url("/CrossSiteScripting/attack6a"), params, true); - - params.clear(); - params.put("param1", "42"); - params.put("param2", "24"); + params.clear(); + params.put("DOMTestRoute", "start.mvc#test"); + checkAssignment(url("/CrossSiteScripting/attack6a"), params, true); - String result = - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .header("webgoat-requested-by", "dom-xss-vuln") - .header("X-Requested-With", "XMLHttpRequest") - .formParams(params) - .post(url("/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("/CrossSiteScripting/dom-follow-up"), params, true); - - params.clear(); - params.put("question_0_solution", "Solution 4: No because the browser trusts the website if it is acknowledged trusted, then the browser does not know that the script is malicious."); - params.put("question_1_solution", "Solution 3: The data is included in dynamic content that is sent to a web user without being validated for malicious content."); - params.put("question_2_solution", "Solution 1: The script is permanently stored on the server and the victim gets the malicious script when requesting information from the server."); - params.put("question_3_solution", "Solution 2: They reflect the injected script off the web server. That occurs when input sent to the web server is part of the request."); - params.put("question_4_solution", "Solution 4: No there are many other ways. Like HTML, Flash or any other type of code that the browser executes."); - checkAssignment(url("/CrossSiteScripting/quiz"), params, true); + params.clear(); + params.put("param1", "42"); + params.put("param2", "24"); - checkResults("/CrossSiteScripting/"); + String result = + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .header("webgoat-requested-by", "dom-xss-vuln") + .header("X-Requested-With", "XMLHttpRequest") + .formParams(params) + .post(url("/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("/CrossSiteScripting/dom-follow-up"), params, true); + + params.clear(); + params.put( + "question_0_solution", + "Solution 4: No because the browser trusts the website if it is acknowledged trusted, then" + + " the browser does not know that the script is malicious."); + params.put( + "question_1_solution", + "Solution 3: The data is included in dynamic content that is sent to a web user without" + + " being validated for malicious content."); + params.put( + "question_2_solution", + "Solution 1: The script is permanently stored on the server and the victim gets the" + + " malicious script when requesting information from the server."); + params.put( + "question_3_solution", + "Solution 2: They reflect the injected script off the web server. That occurs when input" + + " sent to the web server is part of the request."); + params.put( + "question_4_solution", + "Solution 4: No there are many other ways. Like HTML, Flash or any other type of code that" + + " the browser executes."); + checkAssignment(url("/CrossSiteScripting/quiz"), params, true); + + checkResults("/CrossSiteScripting/"); + } } diff --git a/src/it/java/org/owasp/webgoat/XXEIntegrationTest.java b/src/it/java/org/owasp/webgoat/XXEIntegrationTest.java index e7c2a5497..fdb06d8ee 100644 --- a/src/it/java/org/owasp/webgoat/XXEIntegrationTest.java +++ b/src/it/java/org/owasp/webgoat/XXEIntegrationTest.java @@ -2,98 +2,125 @@ package org.owasp.webgoat; import io.restassured.RestAssured; import io.restassured.http.ContentType; -import org.junit.jupiter.api.Test; - import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import org.junit.jupiter.api.Test; public class XXEIntegrationTest extends IntegrationTest { - private static final String xxe3 = """ - <?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment>"""; - private static final String xxe4 = """ - <?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment>"""; - private static final String dtd7 = """ - <?xml version="1.0" encoding="UTF-8"?><!ENTITY % file SYSTEM "file:SECRET"><!ENTITY % all "<!ENTITY send SYSTEM 'WEBWOLFURL?text=%file;'>">%all;"""; - private static final String xxe7 = """ - <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE comment [<!ENTITY % remote SYSTEM "WEBWOLFURL/USERNAME/blind.dtd">%remote;]><comment><text>test&send;</text></comment>"""; + private static final String xxe3 = + """ + <?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment> + """; + private static final String xxe4 = + """ + <?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment> + """; + private static final String dtd7 = + """ + <?xml version="1.0" encoding="UTF-8"?><!ENTITY % file SYSTEM "file:SECRET"><!ENTITY % all "<!ENTITY send SYSTEM 'WEBWOLFURL?text=%file;'>">%all; + """; + private static final String xxe7 = + """ + <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE comment [<!ENTITY % remote SYSTEM "WEBWOLFURL/USERNAME/blind.dtd">%remote;]><comment><text>test&send;</text></comment> + """; - private String webGoatHomeDirectory; - private String webWolfFileServerLocation; + private String webGoatHomeDirectory; + private String webWolfFileServerLocation; - /* - * This test is to verify that all is secure when XXE security patch is applied. - */ - @Test - public void xxeSecure() throws IOException { - startLesson("XXE"); - webGoatHomeDirectory = webGoatServerDirectory(); - webWolfFileServerLocation = getWebWolfFileServerLocation(); + /* + * This test is to verify that all is secure when XXE security patch is applied. + */ + @Test + public void xxeSecure() throws IOException { + startLesson("XXE"); + webGoatHomeDirectory = webGoatServerDirectory(); + webWolfFileServerLocation = getWebWolfFileServerLocation(); + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("service/enable-security.mvc")) + .then() + .statusCode(200); + checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, false); + checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, false); + checkAssignment( + url("/WebGoat/xxe/blind"), + ContentType.XML, + "<comment><text>" + getSecret() + "</text></comment>", + false); + } + + /** + * This performs the steps of the exercise before the secret can be committed in the final step. + * + * @return + * @throws IOException + */ + private String getSecret() throws IOException { + // remove any left over DTD + Path webWolfFilePath = Paths.get(webWolfFileServerLocation); + if (webWolfFilePath.resolve(Paths.get(this.getUser(), "blind.dtd")).toFile().exists()) { + Files.delete(webWolfFilePath.resolve(Paths.get(this.getUser(), "blind.dtd"))); + } + String secretFile = webGoatHomeDirectory.concat("/XXE/" + getUser() + "/secret.txt"); + String dtd7String = + dtd7.replace("WEBWOLFURL", webWolfUrl("/landing")).replace("SECRET", secretFile); + + // upload DTD + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("WEBWOLFSESSION", getWebWolfCookie()) + .multiPart("file", "blind.dtd", dtd7String.getBytes()) + .post(webWolfUrl("/fileupload")) + .then() + .extract() + .response() + .getBody() + .asString(); + // upload attack + String xxe7String = + xxe7.replace("WEBWOLFURL", webWolfUrl("/files")).replace("USERNAME", this.getUser()); + checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, xxe7String, false); + + // read results from WebWolf + String result = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .get(url("service/enable-security.mvc")) - .then() - .statusCode(200); - checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, false); - checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, false); - checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, "<comment><text>" + getSecret() + "</text></comment>", false); + .when() + .relaxedHTTPSValidation() + .cookie("WEBWOLFSESSION", getWebWolfCookie()) + .get(webWolfUrl("/WebWolf/requests")) + .then() + .extract() + .response() + .getBody() + .asString(); + result = result.replace("%20", " "); + if (-1 != result.lastIndexOf("WebGoat 8.0 rocks... (")) { + result = + result.substring( + result.lastIndexOf("WebGoat 8.0 rocks... ("), + result.lastIndexOf("WebGoat 8.0 rocks... (") + 33); } + return result; + } - /** - * This performs the steps of the exercise before the secret can be committed in the final step. - * - * @return - * @throws IOException - */ - private String getSecret() throws IOException { - //remove any left over DTD - Path webWolfFilePath = Paths.get(webWolfFileServerLocation); - if (webWolfFilePath.resolve(Paths.get(this.getUser(), "blind.dtd")).toFile().exists()) { - Files.delete(webWolfFilePath.resolve(Paths.get(this.getUser(), "blind.dtd"))); - } - String secretFile = webGoatHomeDirectory.concat("/XXE/" + getUser() + "/secret.txt"); - String dtd7String = dtd7.replace("WEBWOLFURL", webWolfUrl("/landing")).replace("SECRET", secretFile); - - //upload DTD - RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("WEBWOLFSESSION", getWebWolfCookie()) - .multiPart("file", "blind.dtd", dtd7String.getBytes()) - .post(webWolfUrl("/fileupload")) - .then() - .extract().response().getBody().asString(); - //upload attack - String xxe7String = xxe7.replace("WEBWOLFURL", webWolfUrl("/files")).replace("USERNAME", this.getUser()); - checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, xxe7String, false); - - //read results from WebWolf - String result = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("WEBWOLFSESSION", getWebWolfCookie()) - .get(webWolfUrl("/WebWolf/requests")) - .then() - .extract().response().getBody().asString(); - result = result.replace("%20", " "); - if (-1 != result.lastIndexOf("WebGoat 8.0 rocks... (")) { - result = result.substring(result.lastIndexOf("WebGoat 8.0 rocks... ("), result.lastIndexOf("WebGoat 8.0 rocks... (") + 33); - } - return result; - } - - @Test - public void runTests() throws IOException { - startLesson("XXE", true); - webGoatHomeDirectory = webGoatServerDirectory(); - webWolfFileServerLocation = getWebWolfFileServerLocation(); - checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, true); - checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, true); - checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, "<comment><text>" + getSecret() + "</text></comment>", true); - checkResults("xxe/"); - } + @Test + public void runTests() throws IOException { + startLesson("XXE", true); + webGoatHomeDirectory = webGoatServerDirectory(); + webWolfFileServerLocation = getWebWolfFileServerLocation(); + checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, true); + checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, true); + checkAssignment( + url("/WebGoat/xxe/blind"), + ContentType.XML, + "<comment><text>" + getSecret() + "</text></comment>", + true); + checkResults("xxe/"); + } }