#846: add extra test to verify whether the solution is solved for the original user as well
This commit is contained in:
parent
37e9359c9e
commit
753a2db958
@ -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,178 +66,197 @@ 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
|
||||||
.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);
|
params.put("confirmFlagVal", flag);
|
||||||
checkAssignment(url("/WebGoat/csrf/feedback"), params, true);
|
checkAssignment(url("/WebGoat/csrf/feedback"), params, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to register the new user. Ignore the result.
|
* Try to register the new user. Ignore the result.
|
||||||
*/
|
*/
|
||||||
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"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user