diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/CSRFTest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/CSRFTest.java index ff0c29d67..8d9996481 100644 --- a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/CSRFTest.java +++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/CSRFTest.java @@ -1,8 +1,15 @@ package org.owasp.webgoat; -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 lombok.Data; +import lombok.SneakyThrows; +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.owasp.webgoat.lessons.Assignment; import java.io.IOException; import java.nio.file.Files; @@ -12,49 +19,44 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; -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 io.restassured.RestAssured; -import io.restassured.http.ContentType; -import lombok.SneakyThrows; +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 CSRFTest extends IntegrationTest { - - private static final String trickHTML3 = "
\n" + - "\n" + - "\n" + - "
"; - - private static final String trickHTML4 = "
\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
\n" + - ""; - - private static final String trickHTML7 = "
\n" + - "\n" + - "\n" + - "
"; - - private static final String trickHTML8 = "
\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
"; - + + private static final String trickHTML3 = "
\n" + + "\n" + + "\n" + + "
"; + + private static final String trickHTML4 = "
\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
\n" + + ""; + + private static final String trickHTML7 = "
\n" + + "\n" + + "\n" + + "
"; + + private static final String trickHTML8 = "
\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
"; + private String webwolfFileDir; - + @BeforeEach @SneakyThrows public void init() { - startLesson("CSRF"); + startLesson("CSRF"); webwolfFileDir = getWebWolfServerPath(); uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("/csrf/basic-get-flag"))); uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("/csrf/review"))); @@ -64,178 +66,197 @@ public class CSRFTest extends IntegrationTest { @TestFactory Iterable testCSRFLesson() { - return Arrays.asList( - dynamicTest("assignement 3",()-> checkAssignment3(callTrickHtml("csrf3.html"))), - dynamicTest("assignement 4",()-> checkAssignment4(callTrickHtml("csrf4.html"))), - dynamicTest("assignement 7",()-> checkAssignment7(callTrickHtml("csrf7.html"))), - dynamicTest("assignement 8",()-> checkAssignment8(callTrickHtml("csrf8.html"))) - ); + return Arrays.asList( + dynamicTest("assignement 3", () -> checkAssignment3(callTrickHtml("csrf3.html"))), + dynamicTest("assignement 4", () -> checkAssignment4(callTrickHtml("csrf4.html"))), + dynamicTest("assignement 7", () -> checkAssignment7(callTrickHtml("csrf7.html"))), + dynamicTest("assignement 8", () -> checkAssignment8(callTrickHtml("csrf8.html"))) + ); } - + @AfterEach - public void shutdown() throws IOException { - //logout(); + public void shutdown() throws IOException { + //logout(); login();//because old cookie got replaced and invalidated startLesson("CSRF", false); - checkResults("/csrf"); + 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(getWebgoatUser(),htmlName)).toFile().exists()) { - Files.delete(webWolfFilePath.resolve(Paths.get(getWebgoatUser(),htmlName))); + + //remove any left over html + Path webWolfFilePath = Paths.get(webwolfFileDir); + if (webWolfFilePath.resolve(Paths.get(getWebgoatUser(), htmlName)).toFile().exists()) { + Files.delete(webWolfFilePath.resolve(Paths.get(getWebgoatUser(), htmlName))); } - - //upload trick 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(); + .when() + .relaxedHTTPSValidation() + .cookie("WEBWOLFSESSION", getWebWolfCookie()) + .multiPart("file", htmlName, htmlContent.getBytes()) + .post(webWolfUrl("/WebWolf/fileupload")) + .then() + .extract().response().getBody().asString(); } - + private String callTrickHtml(String htmlName) { - String result = RestAssured.given() - .when() - .relaxedHTTPSValidation() - .cookie("JSESSIONID", getWebGoatCookie()) - .cookie("WEBWOLFSESSION", getWebWolfCookie()) - .get(webWolfUrl("/files/"+getWebgoatUser()+"/"+htmlName)) - .then() - .extract().response().getBody().asString(); - result = result.substring(8+result.indexOf("action=\"")); - result = result.substring(0, result.indexOf("\"")); - - return result; + String result = RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .cookie("WEBWOLFSESSION", getWebWolfCookie()) + .get(webWolfUrl("/files/" + getWebgoatUser() + "/" + htmlName)) + .then() + .extract().response().getBody().asString(); + result = result.substring(8 + result.indexOf("action=\"")); + result = result.substring(0, result.indexOf("\"")); + + 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 params = new HashMap<>(); + + String flag = RestAssured.given() + .when() + .relaxedHTTPSValidation() + .cookie("JSESSIONID", getWebGoatCookie()) + .header("Referer", webWolfUrl("/files/fake.html")) + .post(goatURL) + .then() + .extract().path("flag").toString(); + + Map params = new HashMap<>(); params.clear(); params.put("confirmFlagVal", flag); checkAssignment(url("/WebGoat/csrf/confirm-flag-1"), params, true); } - + private void checkAssignment4(String goatURL) { - - Map params = new HashMap<>(); + + Map 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); - + + 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 params = new HashMap<>(); + + Map params = new HashMap<>(); params.clear(); 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(); + 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 params = new HashMap<>(); + + //first make sure there is an attack csrf- user + registerCSRFUser(); + + Map params = new HashMap<>(); params.clear(); - params.put("username", "csrf-"+getWebgoatUser()); - params.put("password","password"); - + params.put("username", "csrf-" + getWebgoatUser()); + 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"); - - //vaidate the result - assertEquals(true, result); - + 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-"+getWebgoatUser()) - .formParam("password", "password") - .formParam("matchingPassword", "password") - .formParam("agree", "agree") - .post(url("register.mvc")); - + + RestAssured.given() + .when() + .relaxedHTTPSValidation() + .formParam("username", "csrf-" + getWebgoatUser()) + .formParam("password", "password") + .formParam("matchingPassword", "password") + .formParam("agree", "agree") + .post(url("register.mvc")); + } - + } diff --git a/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/csrf/CSRFLogin.java b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/csrf/CSRFLogin.java index 60fab462a..9cf2dc1c4 100644 --- a/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/csrf/CSRFLogin.java +++ b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/csrf/CSRFLogin.java @@ -42,8 +42,11 @@ import org.springframework.web.bind.annotation.RestController; @AssignmentHints({"csrf-login-hint1", "csrf-login-hint2", "csrf-login-hint3"}) public class CSRFLogin extends AssignmentEndpoint { - @Autowired - private UserTrackerRepository userTrackerRepository; + private final UserTrackerRepository userTrackerRepository; + + public CSRFLogin(UserTrackerRepository userTrackerRepository) { + this.userTrackerRepository = userTrackerRepository; + } @PostMapping(path = "/csrf/login", produces = {"application/json"}) @ResponseBody