#846: add extra test to verify whether the solution is solved for the original user as well

This commit is contained in:
Nanne Baars 2020-10-23 14:06:14 +02:00 committed by Nanne Baars
parent 37e9359c9e
commit 753a2db958
2 changed files with 201 additions and 177 deletions

View File

@ -1,8 +1,15 @@
package org.owasp.webgoat; package org.owasp.webgoat;
import static org.junit.jupiter.api.Assertions.assertEquals; import io.restassured.RestAssured;
import static org.junit.jupiter.api.DynamicTest.dynamicTest; 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.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
@ -12,49 +19,44 @@ import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.junit.jupiter.api.AfterEach; import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.BeforeEach; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.DynamicTest; import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import org.junit.jupiter.api.TestFactory;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import lombok.SneakyThrows;
public class CSRFTest extends IntegrationTest { public class CSRFTest extends IntegrationTest {
private static final String trickHTML3 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" + 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=\"hidden\" name=\"csrf\" value=\"thisisnotchecked\"/>\n" +
"<input type=\"submit\" name=\"submit\" value=\"assignment 3\"/>\n" + "<input type=\"submit\" name=\"submit\" value=\"assignment 3\"/>\n" +
"</form></body></html>"; "</form></body></html>";
private static final String trickHTML4 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" + 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=\"reviewText\" value=\"hoi\"/>\n" +
"<input type=\"hidden\" name=\"starts\" value=\"3\"/>\n" + "<input type=\"hidden\" name=\"starts\" value=\"3\"/>\n" +
"<input type=\"hidden\" name=\"validateReq\" value=\"2aa14227b9a13d0bede0388a7fba9aa9\"/>\n" + "<input type=\"hidden\" name=\"validateReq\" value=\"2aa14227b9a13d0bede0388a7fba9aa9\"/>\n" +
"<input type=\"submit\" name=\"submit\" value=\"assignment 4\"/>\n" + "<input type=\"submit\" name=\"submit\" value=\"assignment 4\"/>\n" +
"</form>\n" + "</form>\n" +
"</body></html>"; "</body></html>";
private static final String trickHTML7 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" enctype='text/plain' method=\"POST\">\n" + 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=\"hidden\" name='{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!' value='\"}' />\n" +
"<input type=\"submit\" value=\"assignment 7\"/>\n" + "<input type=\"submit\" value=\"assignment 7\"/>\n" +
"</form></body></html>"; "</form></body></html>";
private static final String trickHTML8 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" + 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=\"username\" value=\"csrf-USERNAME\"/>\n" +
"<input type=\"hidden\" name=\"password\" value=\"password\"/>\n" + "<input type=\"hidden\" name=\"password\" value=\"password\"/>\n" +
"<input type=\"hidden\" name=\"matchingPassword\" value=\"password\"/>\n" + "<input type=\"hidden\" name=\"matchingPassword\" value=\"password\"/>\n" +
"<input type=\"hidden\" name=\"agree\" value=\"agree\"/>\n" + "<input type=\"hidden\" name=\"agree\" value=\"agree\"/>\n" +
"<input type=\"submit\" value=\"assignment 8\"/>\n" + "<input type=\"submit\" value=\"assignment 8\"/>\n" +
"</form></body></html>"; "</form></body></html>";
private String webwolfFileDir; private String webwolfFileDir;
@BeforeEach @BeforeEach
@SneakyThrows @SneakyThrows
public void init() { public void init() {
startLesson("CSRF"); startLesson("CSRF");
webwolfFileDir = getWebWolfServerPath(); webwolfFileDir = getWebWolfServerPath();
uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("/csrf/basic-get-flag"))); uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("/csrf/basic-get-flag")));
uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("/csrf/review"))); uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("/csrf/review")));
@ -64,17 +66,17 @@ public class CSRFTest extends IntegrationTest {
@TestFactory @TestFactory
Iterable<DynamicTest> testCSRFLesson() { Iterable<DynamicTest> testCSRFLesson() {
return Arrays.asList( return Arrays.asList(
dynamicTest("assignement 3",()-> checkAssignment3(callTrickHtml("csrf3.html"))), dynamicTest("assignement 3", () -> checkAssignment3(callTrickHtml("csrf3.html"))),
dynamicTest("assignement 4",()-> checkAssignment4(callTrickHtml("csrf4.html"))), dynamicTest("assignement 4", () -> checkAssignment4(callTrickHtml("csrf4.html"))),
dynamicTest("assignement 7",()-> checkAssignment7(callTrickHtml("csrf7.html"))), dynamicTest("assignement 7", () -> checkAssignment7(callTrickHtml("csrf7.html"))),
dynamicTest("assignement 8",()-> checkAssignment8(callTrickHtml("csrf8.html"))) dynamicTest("assignement 8", () -> checkAssignment8(callTrickHtml("csrf8.html")))
); );
} }
@AfterEach @AfterEach
public void shutdown() throws IOException { public void shutdown() throws IOException {
//logout(); //logout();
login();//because old cookie got replaced and invalidated login();//because old cookie got replaced and invalidated
startLesson("CSRF", false); startLesson("CSRF", false);
checkResults("/csrf"); checkResults("/csrf");
@ -82,50 +84,50 @@ public class CSRFTest extends IntegrationTest {
private void uploadTrickHtml(String htmlName, String htmlContent) throws IOException { private void uploadTrickHtml(String htmlName, String htmlContent) throws IOException {
//remove any left over html //remove any left over html
Path webWolfFilePath = Paths.get(webwolfFileDir); Path webWolfFilePath = Paths.get(webwolfFileDir);
if (webWolfFilePath.resolve(Paths.get(getWebgoatUser(),htmlName)).toFile().exists()) { if (webWolfFilePath.resolve(Paths.get(getWebgoatUser(), htmlName)).toFile().exists()) {
Files.delete(webWolfFilePath.resolve(Paths.get(getWebgoatUser(),htmlName))); Files.delete(webWolfFilePath.resolve(Paths.get(getWebgoatUser(), htmlName)));
} }
//upload trick html //upload trick html
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", htmlName, htmlContent.getBytes()) .multiPart("file", htmlName, htmlContent.getBytes())
.post(webWolfUrl("/WebWolf/fileupload")) .post(webWolfUrl("/WebWolf/fileupload"))
.then() .then()
.extract().response().getBody().asString(); .extract().response().getBody().asString();
} }
private String callTrickHtml(String htmlName) { private String callTrickHtml(String htmlName) {
String result = RestAssured.given() String result = RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/files/"+getWebgoatUser()+"/"+htmlName)) .get(webWolfUrl("/files/" + getWebgoatUser() + "/" + htmlName))
.then() .then()
.extract().response().getBody().asString(); .extract().response().getBody().asString();
result = result.substring(8+result.indexOf("action=\"")); result = result.substring(8 + result.indexOf("action=\""));
result = result.substring(0, result.indexOf("\"")); result = result.substring(0, result.indexOf("\""));
return result; return result;
} }
private void checkAssignment3(String goatURL) { private void checkAssignment3(String goatURL) {
String flag = RestAssured.given() String flag = RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("/files/fake.html")) .header("Referer", webWolfUrl("/files/fake.html"))
.post(goatURL) .post(goatURL)
.then() .then()
.extract().path("flag").toString(); .extract().path("flag").toString();
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear(); params.clear();
params.put("confirmFlagVal", flag); params.put("confirmFlagVal", flag);
checkAssignment(url("/WebGoat/csrf/confirm-flag-1"), params, true); checkAssignment(url("/WebGoat/csrf/confirm-flag-1"), params, true);
@ -133,45 +135,45 @@ public class CSRFTest extends IntegrationTest {
private void checkAssignment4(String goatURL) { private void checkAssignment4(String goatURL) {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear(); params.clear();
params.put("reviewText", "test review"); params.put("reviewText", "test review");
params.put("stars", "5"); params.put("stars", "5");
params.put("validateReq", "2aa14227b9a13d0bede0388a7fba9aa9");//always the same token is the weakness params.put("validateReq", "2aa14227b9a13d0bede0388a7fba9aa9");//always the same token is the weakness
boolean result = RestAssured.given() boolean result = RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("/files/fake.html")) .header("Referer", webWolfUrl("/files/fake.html"))
.formParams(params) .formParams(params)
.post(goatURL) .post(goatURL)
.then() .then()
.extract().path("lessonCompleted"); .extract().path("lessonCompleted");
assertEquals(true, result); assertEquals(true, result);
} }
private void checkAssignment7(String goatURL) { private void checkAssignment7(String goatURL) {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear(); params.clear();
params.put("{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!", "\"}"); params.put("{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!", "\"}");
String flag = RestAssured.given() String flag = RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("/files/fake.html")) .header("Referer", webWolfUrl("/files/fake.html"))
.contentType(ContentType.TEXT) .contentType(ContentType.TEXT)
.body("{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!"+ "=\"}") .body("{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!" + "=\"}")
.post(goatURL) .post(goatURL)
.then() .then()
.extract().asString(); .extract().asString();
flag = flag.substring(9+flag.indexOf("flag is:")); flag = flag.substring(9 + flag.indexOf("flag is:"));
flag = flag.substring(0, flag.indexOf("\"")); flag = flag.substring(0, flag.indexOf("\""));
params.clear(); params.clear();
params.put("confirmFlagVal", flag); params.put("confirmFlagVal", flag);
checkAssignment(url("/WebGoat/csrf/feedback"), params, true); checkAssignment(url("/WebGoat/csrf/feedback"), params, true);
@ -179,47 +181,66 @@ public class CSRFTest extends IntegrationTest {
private void checkAssignment8(String goatURL) { private void checkAssignment8(String goatURL) {
//first make sure there is an attack csrf- user //first make sure there is an attack csrf- user
registerCSRFUser(); registerCSRFUser();
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear(); params.clear();
params.put("username", "csrf-"+getWebgoatUser()); params.put("username", "csrf-" + getWebgoatUser());
params.put("password","password"); params.put("password", "password");
//login and get the new cookie //login and get the new cookie
String newCookie = RestAssured.given() String newCookie = RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("/files/fake.html")) .header("Referer", webWolfUrl("/files/fake.html"))
.params(params) .params(params)
.post(goatURL) .post(goatURL)
.then() .then()
.extract().cookie("JSESSIONID"); .extract().cookie("JSESSIONID");
//select the lesson //select the lesson
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", newCookie) .cookie("JSESSIONID", newCookie)
.get(url("CSRF.lesson.lesson")) .get(url("CSRF.lesson.lesson"))
.then() .then()
.statusCode(200); .statusCode(200);
//click on the assignment //click on the assignment
boolean result = RestAssured.given() boolean result = RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", newCookie) .cookie("JSESSIONID", newCookie)
.post(url("/csrf/login")) .post(url("/csrf/login"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract().path("lessonCompleted"); .extract().path("lessonCompleted");
//vaidate the result assertThat(result).isTrue();
assertEquals(true, result);
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;
} }
/** /**
@ -227,14 +248,14 @@ public class CSRFTest extends IntegrationTest {
*/ */
private void registerCSRFUser() { private void registerCSRFUser() {
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.formParam("username", "csrf-"+getWebgoatUser()) .formParam("username", "csrf-" + getWebgoatUser())
.formParam("password", "password") .formParam("password", "password")
.formParam("matchingPassword", "password") .formParam("matchingPassword", "password")
.formParam("agree", "agree") .formParam("agree", "agree")
.post(url("register.mvc")); .post(url("register.mvc"));
} }

View File

@ -42,8 +42,11 @@ import org.springframework.web.bind.annotation.RestController;
@AssignmentHints({"csrf-login-hint1", "csrf-login-hint2", "csrf-login-hint3"}) @AssignmentHints({"csrf-login-hint1", "csrf-login-hint2", "csrf-login-hint3"})
public class CSRFLogin extends AssignmentEndpoint { public class CSRFLogin extends AssignmentEndpoint {
@Autowired private final UserTrackerRepository userTrackerRepository;
private UserTrackerRepository userTrackerRepository;
public CSRFLogin(UserTrackerRepository userTrackerRepository) {
this.userTrackerRepository = userTrackerRepository;
}
@PostMapping(path = "/csrf/login", produces = {"application/json"}) @PostMapping(path = "/csrf/login", produces = {"application/json"})
@ResponseBody @ResponseBody