From 6f0f71b1312080cc7f64140abe9f4df4e7d3d03e Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Thu, 4 May 2017 06:25:11 +0200 Subject: [PATCH 01/41] Changed XXE lessons to use photo comment example --- .../plugin/BlindSendFileAssignment.java | 17 +- .../webgoat/plugin/CommentsEndpoint.java | 30 ++++ .../webgoat/plugin/ContentTypeAssignment.java | 60 +++++-- .../java/org/owasp/webgoat/plugin/Ping.java | 2 +- .../org/owasp/webgoat/plugin/SimpleXXE.java | 37 ++-- .../xxe/src/main/resources/html/XXE.html | 165 +++++++++--------- .../xxe/src/main/resources/images/avatar1.png | Bin 0 -> 28394 bytes .../xxe/src/main/resources/js/xxe.js | 79 +++++++-- .../resources/lessonPlans/en/XXE_blind.adoc | 15 +- 9 files changed, 250 insertions(+), 155 deletions(-) create mode 100644 webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/CommentsEndpoint.java create mode 100644 webgoat-lessons/xxe/src/main/resources/images/avatar1.png diff --git a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java index 1896cad1f..3214757c6 100644 --- a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java +++ b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java @@ -6,6 +6,8 @@ import org.apache.commons.lang.exception.ExceptionUtils; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AttackResult; +import org.owasp.webgoat.session.WebSession; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.ClassPathResource; import org.springframework.http.MediaType; @@ -51,11 +53,15 @@ import java.util.List; * @version $Id: $Id * @since November 18, 2016 */ -@AssignmentPath("XXE/blind") +@AssignmentPath("xxe/blind") public class BlindSendFileAssignment extends AssignmentEndpoint { @Value("${webgoat.user.directory}") private String webGoatHomeDirectory; + @Autowired + private WebSession webSession; + @Autowired + private Comments comments; @PostConstruct @SneakyThrows @@ -70,10 +76,11 @@ public class BlindSendFileAssignment extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST, consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody - public AttackResult createNewUser(@RequestBody String userInfo) throws Exception { + public AttackResult createNewUser(@RequestBody String commentStr) throws Exception { String error = "Parsing successful contents not send to server"; try { - //parseXml(userInfo); + Comment comment = comments.parseXml(commentStr); + comments.addComment(comment, false); } catch (Exception e) { error = ExceptionUtils.getFullStackTrace(e); } @@ -83,9 +90,9 @@ public class BlindSendFileAssignment extends AssignmentEndpoint { boolean solved = lines.stream().filter(l -> l.contains("WebGoat 8 rocks...")).findFirst().isPresent(); logFile.delete(); if (solved) { - return success().output("xxe.blind.output").outputArgs(Joiner.on('\n').join(lines)).build(); + return trackProgress(success().output("xxe.blind.output").outputArgs(Joiner.on('\n').join(lines)).build()); } else { - return failed().output(error).build(); + return trackProgress(failed().output(error).build()); } } diff --git a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/CommentsEndpoint.java b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/CommentsEndpoint.java new file mode 100644 index 000000000..a46326f44 --- /dev/null +++ b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/CommentsEndpoint.java @@ -0,0 +1,30 @@ +package org.owasp.webgoat.plugin; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collection; + +import static org.springframework.web.bind.annotation.RequestMethod.GET; + +/** + * @author nbaars + * @since 5/4/17. + */ +@RestController +@RequestMapping("xxe/comments") +public class CommentsEndpoint { + + @Autowired + private Comments comments; + + @RequestMapping(method = GET, produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public Collection retrieveComments() { + return comments.getComments(); + } + +} 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 be850944e..96d470c87 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 @@ -1,14 +1,17 @@ package org.owasp.webgoat.plugin; -import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.exec.OS; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentHints; import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AttackResult; +import org.owasp.webgoat.session.WebSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; -import java.io.IOException; +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; /** * ************************************************************************************************ @@ -39,37 +42,56 @@ import java.io.IOException; * @version $Id: $Id * @since November 17, 2016 */ -@AssignmentPath("XXE/content-type") +@AssignmentPath("xxe/content-type") @AssignmentHints({"xxe.hints.content.type.xxe.1", "xxe.hints.content.type.xxe.2"}) public class ContentTypeAssignment extends AssignmentEndpoint { + private final static String[] DEFAULT_LINUX_DIRECTORIES = {"usr", "opt", "var"}; + private final static String[] DEFAULT_WINDOWS_DIRECTORIES = {"Windows", "Program Files (x86)", "Program Files"}; + + + @Value("${webgoat.server.directory}") + private String webGoatHomeDirectory; + @Autowired + private WebSession webSession; + @Autowired + private Comments comments; + @RequestMapping(method = RequestMethod.POST, consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody - public AttackResult createNewUser(@RequestBody String userInfo, @RequestHeader("Content-Type") String contentType) throws Exception { - User user = new User(); + public AttackResult createNewUser(@RequestBody String commentStr, @RequestHeader("Content-Type") String contentType) throws Exception { AttackResult attackResult = failed().build(); - if (MediaType.APPLICATION_JSON_VALUE.equals(contentType)) { - user = parseJson(userInfo); + Comment comment = null; + if (APPLICATION_JSON_VALUE.equals(contentType)) { + comment = comments.parseJson(commentStr); + comments.addComment(comment, true); attackResult = failed().feedback("xxe.content.type.feedback.json").build(); } + if (MediaType.APPLICATION_XML_VALUE.equals(contentType)) { - // user = parseXml(userInfo); - attackResult = failed().feedback("xxe.content.type.feedback.xml").build(); + String error = ""; + try { + comment = comments.parseXml(commentStr); + comments.addComment(comment, false); + } catch (Exception e) { + error = org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(e); + } + attackResult = failed().feedback("xxe.content.type.feedback.xml").output(error).build(); } -// if (checkSolution(user)) { -// attackResult = success().output("xxe.content.output").outputArgs(user.getUsername()).build(); -// } - return attackResult; + if (checkSolution(comment)) { + attackResult = success().build(); + } + return trackProgress(attackResult); } - private User parseJson(String userInfo) { - ObjectMapper mapper = new ObjectMapper(); - try { - return mapper.readValue(userInfo, User.class); - } catch (IOException e) { - return new User(); + private boolean checkSolution(Comment comment) { + String[] directoriesToCheck = OS.isFamilyUnix() ? DEFAULT_LINUX_DIRECTORIES : DEFAULT_WINDOWS_DIRECTORIES; + boolean success = true; + for (String directory : directoriesToCheck) { + success &= comment.getText().contains(directory); } + return success; } } diff --git a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/Ping.java b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/Ping.java index 6ef28f863..ec37961f7 100644 --- a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/Ping.java +++ b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/Ping.java @@ -58,7 +58,7 @@ public class Ping extends Endpoint { 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(webGoatHomeDirectory, "/XXE/log.txt"); + File logFile = new File(webGoatHomeDirectory, "/XXE/log.tdxt"); try { try (PrintWriter pw = new PrintWriter(logFile)) { pw.println(logLine); diff --git a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/SimpleXXE.java b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/SimpleXXE.java index d5c6b6a82..f1f5bdfc3 100644 --- a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/SimpleXXE.java +++ b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/SimpleXXE.java @@ -1,24 +1,20 @@ package org.owasp.webgoat.plugin; import org.apache.commons.exec.OS; +import org.apache.commons.lang.exception.ExceptionUtils; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentHints; import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AttackResult; -import org.owasp.webgoat.session.WebSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; -import java.util.Collection; - import static org.springframework.http.MediaType.ALL_VALUE; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; -import static org.springframework.web.bind.annotation.RequestMethod.GET; import static org.springframework.web.bind.annotation.RequestMethod.POST; /** @@ -65,35 +61,22 @@ public class SimpleXXE extends AssignmentEndpoint { @Value("${webgoat.server.directory}") private String webGoatHomeDirectory; @Autowired - private WebSession webSession; - @Autowired private Comments comments; - @RequestMapping(method = GET, produces = MediaType.APPLICATION_JSON_VALUE) - @ResponseBody - public Collection retrieveComments() { - return comments.getComments(); - } - @RequestMapping(method = POST, consumes = ALL_VALUE, produces = APPLICATION_JSON_VALUE) @ResponseBody public AttackResult createNewComment(@RequestBody String commentStr, @RequestHeader("Content-Type") String contentType) throws Exception { - Comment comment = null; - if (APPLICATION_JSON_VALUE.equals(contentType)) { - comment = comments.parseJson(commentStr); - comments.addComment(comment, true); - } - if (MediaType.APPLICATION_XML_VALUE.equals(contentType)) { - //Do not show these comments to all users - comment = comments.parseXml(commentStr); + String error = ""; + try { + Comment comment = comments.parseXml(commentStr); comments.addComment(comment, false); + if (checkSolution(comment)) { + return trackProgress(success().build()); + } + } catch (Exception e) { + error = ExceptionUtils.getFullStackTrace(e); } - if (checkSolution(comment)) { - return trackProgress(success() - .output("xxe.simple.output") - .outputArgs(webSession.getUserName()).build()); - } - return trackProgress(failed().build()); + return trackProgress(failed().output(error).build()); } private boolean checkSolution(Comment comment) { diff --git a/webgoat-lessons/xxe/src/main/resources/html/XXE.html b/webgoat-lessons/xxe/src/main/resources/html/XXE.html index 7d79b58d3..2ad34cf5d 100644 --- a/webgoat-lessons/xxe/src/main/resources/html/XXE.html +++ b/webgoat-lessons/xxe/src/main/resources/html/XXE.html @@ -48,13 +48,13 @@ @@ -68,111 +68,112 @@
- -
- - - -
-
- Registration form - - - - - - - - - - - - - - - - - - -
Username
E-mail
Password
-
-
- -
-
+
+
+
+
+ user profile image +
+
+
+ John Doe + uploaded a photo. +
+
24 days ago
+
+
+ +
+ image post +
+ +
+ +
+
- +
+ +
+
+
- -
- -
- -
- - - -
-
- Registration form - - - - - - - - - - - - - - - - - - -
Username
E-mail
Password
-
-
- -
-
+
+
+
+
+ user profile image +
+
+
+ John Doe + uploaded a photo. +
+
24 days ago
+
+
+ +
+ image post +
+ +
+ +
+
- +
+ +
+
+
- -
diff --git a/webgoat-lessons/xxe/src/main/resources/images/avatar1.png b/webgoat-lessons/xxe/src/main/resources/images/avatar1.png new file mode 100644 index 0000000000000000000000000000000000000000..4ea864f90009013d7d30ea3fb8c70b1f49c7e4b8 GIT binary patch literal 28394 zcmeI(f5ENDT zB&p@Sc=YAQ>&<*i$#bO7-o&Gu?VKUsO?QUKLA9X!NhjL%0D`5Zr6Vlefig3uH=W86 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' + + ' ' + commentInput + '' + + ''; $.ajax({ type: 'POST', url: 'xxe/simple', - data: JSON.stringify({text: commentInput}), - contentType: "application/json", - dataType: 'json' + data: xml, + contentType: "application/xml", + dataType: 'xml', + complete: function (data) { + $("#commentInputSimple").val(''); + getComments('#commentsListSimple') + } + }) + }); + getComments('#commentsListSimple'); +}); + +$(document).ready(function () { + $("#postCommentBlind").unbind(); + $("#postCommentBlind").on("click", function () { + var commentInput = $("#commentInput").val(); + var xml = '' + + '' + + ' ' + commentInput + '' + + ''; + $.ajax({ + type: 'POST', + url: 'xxe/blind', + data: xml, + contentType: "application/xml", + dataType: 'xml' }).then( function () { - getComments(); + getComments('#commentsListBlind'); $("#commentInput").val(''); } ) - }) + }); + getComments('#commentsListBlind'); +}); + +$(document).ready(function () { + $("#postCommentContentType").unbind(); + $("#postCommentContentType").on("click", function () { + var commentInput = $("#commentInputContentType").val(); + $.ajax({ + type: 'POST', + url: 'xxe/content-type', + data: JSON.stringify({text: commentInput}), + contentType: "application/json", + dataType: 'xml' + }).then( + function () { + getComments('#commentsListContentType'); + $("#commentInputContentType").val(''); + } + ) + }); + getComments('#commentsListContentType'); +}); + +$(document).ready(function () { getComments(); -}) +}); var html = '
  • ' + '
    ' + @@ -31,15 +82,15 @@ var html = '
  • ' + '
  • ' + ''; -function getComments() { - $.get("xxe/simple", function (result, status) { - $("#comments_list").empty(); +function getComments(field) { + $.get("xxe/comments", function (result, status) { + $(field).empty(); for (var i = 0; i < result.length; i++) { var comment = html.replace('USER', result[i].user); comment = comment.replace('DATETIME', result[i].dateTime); comment = comment.replace('COMMENT', result[i].text); - $("#comments_list").append(comment); + $(field).append(comment); } }); -} \ No newline at end of file +} diff --git a/webgoat-lessons/xxe/src/main/resources/lessonPlans/en/XXE_blind.adoc b/webgoat-lessons/xxe/src/main/resources/lessonPlans/en/XXE_blind.adoc index cd615ee26..0d7e110e4 100644 --- a/webgoat-lessons/xxe/src/main/resources/lessonPlans/en/XXE_blind.adoc +++ b/webgoat-lessons/xxe/src/main/resources/lessonPlans/en/XXE_blind.adoc @@ -8,11 +8,11 @@ Our WebGoat server by default has an /xxe/ping endpoint which we can use. *This [source] ---- -curl -i http://localhost:8080/WebGoat/XXE/ping +curl -i http://localhost:8080/WebGoat/XXE/ping?text=HelloWorld will result in: -GET curl/7.45.0 +GET curl/7.45.0 HelloWorld ---- at the server side. @@ -33,12 +33,12 @@ Now submit the form and change the xml to: ---- + %remote; ]> - - test&ping; - + + test&ping; + ---- Now if we check our server log we will see: @@ -48,7 +48,8 @@ Now if we check our server log we will see: 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. +So with the XXE we are able to ping our own server which means XXE injection is possible. So with the XXE injection +we are basically able to reach the same effect as we did in the beginning with the curl command. [NOTE] In this case we use http://localhost:8080/WebGoat/plugin_lessons/XXE/test.dtd to fetch the dtd but in reality this will From cb9503d4a34c3dad5c6aeb3ed80055d3ee624894 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Sun, 21 May 2017 11:04:13 +0200 Subject: [PATCH 02/41] Upgraded to Spring Boot 1.5.3 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index af60fd088..79c12a753 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.5.3.RELEASE From 877de6ebd48c1a2d64dc743aa3bd7e2b037f019f Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Sun, 21 May 2017 12:24:42 +0200 Subject: [PATCH 03/41] Updated XXE lessons with challenge screens --- webgoat-container/pom.xml | 6 + .../owasp/webgoat/controller/StartLesson.java | 5 +- .../owasp/webgoat/lessons/AbstractLesson.java | 10 +- .../src/main/resources/application.properties | 1 + .../org/owasp/webgoat/plugins/LessonTest.java | 42 ++++ .../org/owasp/webgoat/plugins/TestConfig.java | 23 +++ webgoat-lessons/pom.xml | 32 +++- .../plugin/BlindSendFileAssignment.java | 19 +- .../java/org/owasp/webgoat/plugin/Ping.java | 12 +- .../xxe/src/main/resources/html/XXE.html | 180 ++++++++++-------- .../xxe/src/main/resources/js/xxe.js | 22 +-- .../plugin/BlindSendFileAssignmentTest.java | 90 +++++++++ 12 files changed, 323 insertions(+), 119 deletions(-) create mode 100644 webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java create mode 100644 webgoat-container/src/test/java/org/owasp/webgoat/plugins/TestConfig.java create mode 100644 webgoat-lessons/xxe/src/test/java/org/owasp/webgoat/plugin/BlindSendFileAssignmentTest.java diff --git a/webgoat-container/pom.xml b/webgoat-container/pom.xml index f9e4f76ae..d2f86a151 100644 --- a/webgoat-container/pom.xml +++ b/webgoat-container/pom.xml @@ -242,6 +242,12 @@ ${junit.version} jar + + com.github.fakemongo + fongo + 2.1.0 + test + diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/controller/StartLesson.java b/webgoat-container/src/main/java/org/owasp/webgoat/controller/StartLesson.java index 6af1770f3..28d0524fb 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/controller/StartLesson.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/controller/StartLesson.java @@ -33,7 +33,6 @@ package org.owasp.webgoat.controller; import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.session.Course; import org.owasp.webgoat.session.WebSession; -import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; @@ -77,8 +76,8 @@ public class StartLesson { // I will set here the thymeleaf fragment location based on the resource requested. ModelAndView model = new ModelAndView(); SecurityContext context = SecurityContextHolder.getContext(); //TODO this should work with the security roles of Spring - GrantedAuthority authority = context.getAuthentication().getAuthorities().iterator().next(); - String path = request.getServletPath(); // we now got /a/b/c/AccessControlMatrix.lesson + //GrantedAuthority authority = context.getAuthentication().getAuthorities().iterator().next(); + String path = request.getRequestURL().toString(); // we now got /a/b/c/AccessControlMatrix.lesson String lessonName = path.substring(path.lastIndexOf('/') + 1, path.indexOf(".lesson")); List lessons = course.getLessons(); Optional lesson = lessons.stream() diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java index eb200b354..1336fa326 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java @@ -1,6 +1,6 @@ package org.owasp.webgoat.lessons; -import lombok.Getter; +import com.google.common.collect.Lists; import lombok.Setter; import org.owasp.webgoat.session.Screen; @@ -44,10 +44,16 @@ public abstract class AbstractLesson extends Screen implements Comparable assignments; + public List getAssignments() { + if (assignments == null) { + return Lists.newArrayList(); + } + return assignments; + } + /** * Constructor for the Lesson object */ diff --git a/webgoat-container/src/main/resources/application.properties b/webgoat-container/src/main/resources/application.properties index 4119f9887..5ac2c63c3 100644 --- a/webgoat-container/src/main/resources/application.properties +++ b/webgoat-container/src/main/resources/application.properties @@ -29,6 +29,7 @@ webgoat.database.driver=org.hsqldb.jdbcDriver webgoat.database.connection.string=jdbc:hsqldb:mem:{USER} webgoat.default.language=en + spring.data.mongodb.database=webgoat spring.mongodb.embedded.storage.databaseDir=${webgoat.user.directory}/mongodb/ diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java new file mode 100644 index 000000000..049d38697 --- /dev/null +++ b/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java @@ -0,0 +1,42 @@ +package org.owasp.webgoat.plugins; + +import org.junit.Before; +import org.owasp.webgoat.i18n.Language; +import org.owasp.webgoat.i18n.Messages; +import org.owasp.webgoat.session.WebSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.web.context.WebApplicationContext; + +import java.util.Locale; + +import static org.mockito.Mockito.when; + +/** + * @author nbaars + * @since 5/20/17. + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public abstract class LessonTest { + + @LocalServerPort + protected int localPort; + protected MockMvc mockMvc; + @Autowired + protected WebApplicationContext wac; + @Autowired + protected Messages messages; + @MockBean + protected WebSession webSession; + @MockBean + private Language language; + + @Before + public void init() { + when(language.getLocale()).thenReturn(Locale.US); + } + +} diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/plugins/TestConfig.java b/webgoat-container/src/test/java/org/owasp/webgoat/plugins/TestConfig.java new file mode 100644 index 000000000..5946104b4 --- /dev/null +++ b/webgoat-container/src/test/java/org/owasp/webgoat/plugins/TestConfig.java @@ -0,0 +1,23 @@ +package org.owasp.webgoat.plugins; + +import com.github.fakemongo.Fongo; +import com.mongodb.MongoClient; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.config.AbstractMongoConfiguration; + +/** + * Using Fongo for embedded in memory MongoDB testing + */ +@Configuration +public class TestConfig extends AbstractMongoConfiguration { + + @Override + protected String getDatabaseName() { + return "test"; + } + + @Override + public MongoClient mongo() throws Exception { + return new Fongo(getDatabaseName()).getMongo(); + } +} \ No newline at end of file diff --git a/webgoat-lessons/pom.xml b/webgoat-lessons/pom.xml index 51babeab6..f19b0ba3c 100644 --- a/webgoat-lessons/pom.xml +++ b/webgoat-lessons/pom.xml @@ -33,11 +33,19 @@ ${project.version} provided jar + + + + de.flapdoodle.embed + de.flapdoodle.embed.mongo + + - - - + + + org.owasp.webgoat @@ -45,6 +53,14 @@ ${project.version} tests test + + + + de.flapdoodle.embed + de.flapdoodle.embed.mongo + + junit @@ -70,6 +86,12 @@ 4.1.3.RELEASE test + + com.github.fakemongo + fongo + 2.1.0 + test + org.owasp.encoder encoder @@ -119,6 +141,6 @@ - - + + diff --git a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java index 3214757c6..3a3ddb74f 100644 --- a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java +++ b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java @@ -1,8 +1,9 @@ package org.owasp.webgoat.plugin; +import com.beust.jcommander.internal.Lists; import com.google.common.base.Joiner; import lombok.SneakyThrows; -import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.commons.lang3.StringEscapeUtils; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AttackResult; @@ -59,9 +60,9 @@ public class BlindSendFileAssignment extends AssignmentEndpoint { @Value("${webgoat.user.directory}") private String webGoatHomeDirectory; @Autowired - private WebSession webSession; - @Autowired private Comments comments; + @Autowired + private WebSession webSession; @PostConstruct @SneakyThrows @@ -76,20 +77,20 @@ public class BlindSendFileAssignment extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST, consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody - public AttackResult createNewUser(@RequestBody String commentStr) throws Exception { - String error = "Parsing successful contents not send to server"; + public AttackResult addComment(@RequestBody String commentStr) throws Exception { + String error = "Parsing successful contents not send to attacker"; try { Comment comment = comments.parseXml(commentStr); comments.addComment(comment, false); } catch (Exception e) { - error = ExceptionUtils.getFullStackTrace(e); + error = StringEscapeUtils.escapeJson(e.toString()); } - File logFile = new File(webGoatHomeDirectory, "/XXE/log.txt"); - List lines = Files.readAllLines(Paths.get(logFile.toURI())); + File logFile = new File(webGoatHomeDirectory, "/XXE/log" + webSession.getUserName() + ".txt"); + List lines = logFile.exists() ? Files.readAllLines(Paths.get(logFile.toURI())) : Lists.newArrayList(); boolean solved = lines.stream().filter(l -> l.contains("WebGoat 8 rocks...")).findFirst().isPresent(); - logFile.delete(); if (solved) { + logFile.delete(); return trackProgress(success().output("xxe.blind.output").outputArgs(Joiner.on('\n').join(lines)).build()); } else { return trackProgress(failed().output(error).build()); diff --git a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/Ping.java b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/Ping.java index ec37961f7..c09fa0377 100644 --- a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/Ping.java +++ b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/Ping.java @@ -2,12 +2,10 @@ package org.owasp.webgoat.plugin; import lombok.extern.slf4j.Slf4j; import org.owasp.webgoat.assignments.Endpoint; +import org.owasp.webgoat.session.WebSession; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -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 org.springframework.web.bind.annotation.*; import java.io.File; import java.io.FileNotFoundException; @@ -47,6 +45,8 @@ public class Ping extends Endpoint { @Value("${webgoat.user.directory}") private String webGoatHomeDirectory; + @Autowired + private WebSession webSession; @Override public String getPath() { @@ -58,7 +58,7 @@ public class Ping extends Endpoint { 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(webGoatHomeDirectory, "/XXE/log.tdxt"); + File logFile = new File(webGoatHomeDirectory, "/XXE/log" + webSession.getUserName() + ".txt"); try { try (PrintWriter pw = new PrintWriter(logFile)) { pw.println(logLine); diff --git a/webgoat-lessons/xxe/src/main/resources/html/XXE.html b/webgoat-lessons/xxe/src/main/resources/html/XXE.html index 2ad34cf5d..21b4aa916 100644 --- a/webgoat-lessons/xxe/src/main/resources/html/XXE.html +++ b/webgoat-lessons/xxe/src/main/resources/html/XXE.html @@ -2,7 +2,6 @@ -
    -
    - -
    +
    - -
    +
    - -
    +
    - -
    +
    - -
    +
    - -
    - - - - -
    -
    -
    +
    - -
    - - - -
    - -
    -
    +
    - -
    +
    - -
    - - - -
    - -
    -
    - - - -
    - -
    -
    - -
    +
    - -
    +
    - -
    +
    - -
    +
    - -
    +
    - -
    +
    - -
    diff --git a/webgoat-lessons/sql-injection/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/sql-injection/src/main/resources/i18n/WebGoatLabels.properties index 407f5367a..e63a9fb5c 100644 --- a/webgoat-lessons/sql-injection/src/main/resources/i18n/WebGoatLabels.properties +++ b/webgoat-lessons/sql-injection/src/main/resources/i18n/WebGoatLabels.properties @@ -1,12 +1,13 @@ #StringSqlInjection.java StringSqlInjectionSecondStage=Now that you have successfully performed an SQL injection, try the same type of attack on a parameterized query. Restart the lesson if you wish to return to the injectable query. EnterLastName=Enter your last name: -NoResultsMatched=No results matched. Try Again. +NoResultsMatched=No results matched. Try Again. SqlStringInjectionHint1=The application is taking your input and inserting it at the end of a pre-formed SQL command. SqlStringInjectionHint2=This is the code for the query being built and issued by WebGoat:

    "SELECT * FROM user_data WHERE last_name = "accountName" SqlStringInjectionHint3=Compound SQL statements can be made by joining multiple tests with keywords like AND and OR. Try appending a SQL statement that always resolves to true SqlStringInjectionHint4=Try entering [ smith' OR '1' = '1 ]. - +SqlStringInjectionHint5=Try adding a union to the query, the number of columns should match. +SqlStringInjectionHint6=Try entering [ Smith' union select userid,user_name, password,cookie,cookie, cookie,userid from user_system_data -- ]. sql-injection.5a.success=You have succeed: {0} sql-injection.5a.no.results=No results matched. Try Again. diff --git a/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/SqlInjectionLesson5aTest.java b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/SqlInjectionLesson5aTest.java new file mode 100644 index 000000000..54c99b481 --- /dev/null +++ b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/SqlInjectionLesson5aTest.java @@ -0,0 +1,81 @@ +package org.owasp.webgoat.plugin; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.owasp.webgoat.plugins.LessonTest; +import org.owasp.webgoat.session.WebgoatContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author nbaars + * @since 5/21/17. + */ +@RunWith(SpringJUnit4ClassRunner.class) +public class SqlInjectionLesson5aTest extends LessonTest { + + @Autowired + private WebgoatContext context; + + @Before + public void setup() throws Exception { + SqlInjection sql = new SqlInjection(); + when(webSession.getCurrentLesson()).thenReturn(sql); + when(webSession.getWebgoatContext()).thenReturn(context); + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void knownAccountShouldDisplayData() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a") + .param("account", "Smith")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("lessonCompleted", is(false))) + .andExpect(jsonPath("$.feedback", is(messages.getMessage("assignment.not.solved")))) + .andExpect(jsonPath("$.output", containsString("

    USERID, FIRST_NAME"))); + } + + @Test + public void unknownAccount() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a") + .param("account", "Smithh")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("lessonCompleted", is(false))) + .andExpect(jsonPath("$.feedback", is(messages.getMessage("NoResultsMatched")))) + .andExpect(jsonPath("$.output").doesNotExist()); + } + + @Test + public void sqlInjection() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a") + .param("account", "smith' OR '1' = '1")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("lessonCompleted", is(true))) + .andExpect(jsonPath("$.feedback", containsString("You have succeed"))) + .andExpect(jsonPath("$.output").doesNotExist()); + } + + @Test + public void sqlInjectionWrongShouldDisplayError() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a") + .param("account", "smith' OR '1' = '1'")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("lessonCompleted", is(false))) + .andExpect(jsonPath("$.feedback", containsString(messages.getMessage("assignment.not.solved")))) + .andExpect(jsonPath("$.output", is("malformed string: '1''"))); + } +} \ No newline at end of file diff --git a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java index 3a3ddb74f..f8792b06c 100644 --- a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java +++ b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java @@ -3,7 +3,6 @@ package org.owasp.webgoat.plugin; import com.beust.jcommander.internal.Lists; import com.google.common.base.Joiner; import lombok.SneakyThrows; -import org.apache.commons.lang3.StringEscapeUtils; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AttackResult; @@ -83,7 +82,7 @@ public class BlindSendFileAssignment extends AssignmentEndpoint { Comment comment = comments.parseXml(commentStr); comments.addComment(comment, false); } catch (Exception e) { - error = StringEscapeUtils.escapeJson(e.toString()); + error = e.toString(); } File logFile = new File(webGoatHomeDirectory, "/XXE/log" + webSession.getUserName() + ".txt"); From 19a4859e4f7093c584e6b62df7e8e875e430aef0 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Mon, 12 Jun 2017 13:03:14 +0200 Subject: [PATCH 22/41] Fix hint not being display correctly due to missing escaping --- .../xxe/src/main/resources/i18n/WebGoatLabels.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webgoat-lessons/xxe/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/xxe/src/main/resources/i18n/WebGoatLabels.properties index 864ae5afb..877a3774c 100644 --- a/webgoat-lessons/xxe/src/main/resources/i18n/WebGoatLabels.properties +++ b/webgoat-lessons/xxe/src/main/resources/i18n/WebGoatLabels.properties @@ -31,7 +31,7 @@ xxe.blind.output=Contents of the file is: {0} xxe.hints.simple.xxe.1=Try submitting the form and see what happens xxe.hints.simple.xxe.2=XXE stands for XML External Entity attack xxe.hints.simple.xxe.3=Try to include your own DTD -xxe.hints.simple.xxe.4=Try to include a doctype ( Date: Mon, 12 Jun 2017 15:08:55 +0200 Subject: [PATCH 23/41] XXE successfully completed message was no longer shown, fixed it by using form POST together with customjs functions. Introduced callback functionality which you can specify after the posting in order to be able to load the comments list again. --- .../js/goatApp/view/LessonContentView.js | 8 +++-- webgoat-lessons/sol.txt | 2 +- .../org/owasp/webgoat/plugin/SimpleXXE.java | 3 +- .../xxe/src/main/resources/html/XXE.html | 8 +++-- .../xxe/src/main/resources/js/xxe.js | 32 ++++++++----------- 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js index beb0f6fa6..dd96905cb 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js @@ -80,7 +80,9 @@ define(['jquery', var self = this; // TODO custom Data prep for submission var prepareDataFunctionName = $(curForm).attr('prepareData'); + var callbackFunctionName = $(curForm).attr('callback'); var submitData = (typeof webgoat.customjs[prepareDataFunctionName] === 'function') ? webgoat.customjs[prepareDataFunctionName]() : $(curForm).serialize(); + var callbackFunction = (typeof webgoat.customjs[callbackFunctionName] === 'function') ? webgoat.customjs[callbackFunctionName] : function() {}; // var submitData = this.$form.serialize(); this.curForm = curForm; this.$curFeedback = $(curForm).closest('.attack-container').find('.attack-feedback'); @@ -93,14 +95,16 @@ define(['jquery', url:formUrl, method:formMethod, contentType:contentType, - data: submitData + data: submitData, + complete: function (data) { + callbackFunction(); + } }).then(self.onSuccessResponse.bind(self), self.onErrorResponse.bind(self)); return false; }, onSuccessResponse: function(data) { this.renderFeedback(data.feedback); - this.renderOutput(data.output || ""); //TODO: refactor back assignmentCompleted in Java if (data.lessonCompleted || data.assignmentCompleted) { diff --git a/webgoat-lessons/sol.txt b/webgoat-lessons/sol.txt index c686e4396..d54494a64 100644 --- a/webgoat-lessons/sol.txt +++ b/webgoat-lessons/sol.txt @@ -11,7 +11,7 @@ Smith' union select userid,user_name, password,cookie,cookie, cookie,userid from ## XXE ## -Simple - ]> &root;test +Simple - ]>&root; Modern Rest Framework - change content type to: Content-Type: application/xml && ]> &root;test diff --git a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/SimpleXXE.java b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/SimpleXXE.java index f1f5bdfc3..4a3de9d8f 100644 --- a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/SimpleXXE.java +++ b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/SimpleXXE.java @@ -9,7 +9,6 @@ import org.owasp.webgoat.assignments.AttackResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @@ -65,7 +64,7 @@ public class SimpleXXE extends AssignmentEndpoint { @RequestMapping(method = POST, consumes = ALL_VALUE, produces = APPLICATION_JSON_VALUE) @ResponseBody - public AttackResult createNewComment(@RequestBody String commentStr, @RequestHeader("Content-Type") String contentType) throws Exception { + public AttackResult createNewComment(@RequestBody String commentStr) throws Exception { String error = ""; try { Comment comment = comments.parseXml(commentStr); diff --git a/webgoat-lessons/xxe/src/main/resources/html/XXE.html b/webgoat-lessons/xxe/src/main/resources/html/XXE.html index 21b4aa916..bbdc2e39a 100644 --- a/webgoat-lessons/xxe/src/main/resources/html/XXE.html +++ b/webgoat-lessons/xxe/src/main/resources/html/XXE.html @@ -24,8 +24,10 @@

    + prepareData="simpleXXE" + callback="simpleXXECallback" + contentType="application/xml" + action="/WebGoat/xxe/simple">
    @@ -54,7 +56,7 @@ - +
      diff --git a/webgoat-lessons/xxe/src/main/resources/js/xxe.js b/webgoat-lessons/xxe/src/main/resources/js/xxe.js index dc5b0ddcf..f0219af89 100644 --- a/webgoat-lessons/xxe/src/main/resources/js/xxe.js +++ b/webgoat-lessons/xxe/src/main/resources/js/xxe.js @@ -1,23 +1,17 @@ +webgoat.customjs.simpleXXE = function () { + var commentInput = $("#commentInputSimple").val(); + var xml = '' + + '' + + ' ' + commentInput + '' + + ''; + return xml; +} + +webgoat.customjs.simpleXXECallback = function() { + getComments('#commentsListSimple'); +} + $(document).ready(function () { - $("#postCommentSimple").unbind(); - $("#postCommentSimple").on("click", function () { - var commentInput = $("#commentInputSimple").val(); - var xml = '' + - '' + - ' ' + commentInput + '' + - ''; - $.ajax({ - type: 'POST', - url: 'xxe/simple', - data: xml, - contentType: "application/xml", - dataType: 'xml', - complete: function (data) { - $("#commentInputSimple").val(''); - getComments('#commentsListSimple') - } - }) - }); getComments('#commentsListSimple'); }); From 99f75a835c442661db73d7eb89a39666b130f40c Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Mon, 12 Jun 2017 20:02:21 +0200 Subject: [PATCH 24/41] #359 Fixed --- .../xxe/src/main/resources/html/XXE.html | 22 ++++--- .../xxe/src/main/resources/js/xxe.js | 61 ++++++++----------- 2 files changed, 37 insertions(+), 46 deletions(-) diff --git a/webgoat-lessons/xxe/src/main/resources/html/XXE.html b/webgoat-lessons/xxe/src/main/resources/html/XXE.html index bbdc2e39a..7b0d74867 100644 --- a/webgoat-lessons/xxe/src/main/resources/html/XXE.html +++ b/webgoat-lessons/xxe/src/main/resources/html/XXE.html @@ -53,10 +53,10 @@
    diff --git a/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_FrontendValidation.adoc b/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_FrontendValidation.adoc index 2f02262d0..67b4dd857 100644 --- a/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_FrontendValidation.adoc +++ b/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_FrontendValidation.adoc @@ -1,4 +1,5 @@ == Validation + Often, there is some mechanism in place to prevent users from sending altered field values to server, such as validation before sending. Most of popular browsers such as Chrome don't allow editing scripts during runtime. We will have to circumvent diff --git a/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_Intro.adoc b/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_Intro.adoc index 5743d6f9a..e75483bc8 100755 --- a/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_Intro.adoc +++ b/webgoat-lessons/bypass-restrictions/src/main/resources/lessonPlans/en/BypassRestrictions_Intro.adoc @@ -1,10 +1,11 @@ - == Concept + Users have a great degree of control over the front-end of the web application. They can alter HTML code, sometimes also scripts. This is why apps that require certain format of input should also validate on server-side. == Goals + * The user should have a basic knowledge of HTML * The user should be able to tamper a request before sending (with proxy or other tool) * The user will be able to tamper with field restrictions and bypass client-side validation diff --git a/webgoat-lessons/bypass-restrictions/src/test/java/org/owasp/webgoat/plugin/BypassRestrictionsFrontendValidationTest.java b/webgoat-lessons/bypass-restrictions/src/test/java/org/owasp/webgoat/plugin/BypassRestrictionsFrontendValidationTest.java new file mode 100644 index 000000000..8fb0657fa --- /dev/null +++ b/webgoat-lessons/bypass-restrictions/src/test/java/org/owasp/webgoat/plugin/BypassRestrictionsFrontendValidationTest.java @@ -0,0 +1,76 @@ +package org.owasp.webgoat.plugin; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.owasp.webgoat.plugins.LessonTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author nbaars + * @since 6/16/17. + */ +@RunWith(SpringJUnit4ClassRunner.class) +public class BypassRestrictionsFrontendValidationTest extends LessonTest { + + @Before + public void setup() throws Exception { + when(webSession.getCurrentLesson()).thenReturn(new BypassRestrictions()); + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void noChangesShouldNotPassTheLesson() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/BypassRestrictions/frontendValidation") + .param("field1", "abc") + .param("field2", "123") + .param("field3", "abc ABC 123") + .param("field4", "seven") + .param("field5", "01101") + .param("field6", "90201 1111") + .param("field7", "301-604-4882") + .param("error", "2")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false))); + } + + @Test + public void bypassAllFieldShouldPass() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/BypassRestrictions/frontendValidation") + .param("field1", "abcd") + .param("field2", "1234") + .param("field3", "abc $ABC 123") + .param("field4", "ten") + .param("field5", "01101AA") + .param("field6", "90201 1111AA") + .param("field7", "301-604-4882$$") + .param("error", "0")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true))); + } + + @Test + public void notBypassingAllFieldShouldNotPass() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/BypassRestrictions/frontendValidation") + .param("field1", "abc") + .param("field2", "1234") + .param("field3", "abc $ABC 123") + .param("field4", "ten") + .param("field5", "01101AA") + .param("field6", "90201 1111AA") + .param("field7", "301-604-4882AA") + .param("error", "0")) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false))); + } + + +} \ No newline at end of file From b304dbb55291923b2df1ea023e41776bb3ffd236 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Tue, 20 Jun 2017 09:44:12 +0200 Subject: [PATCH 39/41] Changed to develop for coverage --- README.MD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.MD b/README.MD index ddef184bb..3a5d469b3 100644 --- a/README.MD +++ b/README.MD @@ -1,7 +1,7 @@ # WebGoat: A deliberately insecure Web Application [![Build Status](https://travis-ci.org/WebGoat/WebGoat.svg?branch=develop)](https://travis-ci.org/WebGoat/WebGoat) -[![Coverage Status](https://coveralls.io/repos/WebGoat/WebGoat/badge.svg?branch=master&service=github)](https://coveralls.io/github/WebGoat/WebGoat?branch=master) +[![Coverage Status](https://coveralls.io/repos/WebGoat/WebGoat/badge.svg?branch=develop&service=github)](https://coveralls.io/github/WebGoat/WebGoat?branch=master) [![Codacy Badge](https://api.codacy.com/project/badge/b69ee3a86e3b4afcaf993f210fccfb1d)](https://www.codacy.com/app/dm/WebGoat) [![Dependency Status](https://www.versioneye.com/user/projects/562da95ae346d7000e0369aa/badge.svg?style=flat)](https://www.versioneye.com/user/projects/562da95ae346d7000e0369aa) [![OWASP Labs](https://img.shields.io/badge/owasp-labs-orange.svg)](https://www.owasp.org/index.php/OWASP_Project_Inventory#tab=Labs_Projects) From ccb4e3813b2d871740788e455736a3cba65e3ea6 Mon Sep 17 00:00:00 2001 From: Jason White Date: Fri, 23 Jun 2017 14:46:09 -0400 Subject: [PATCH 40/41] #353 - lesson template/guide --- .../org/owasp/webgoat/MvcConfiguration.java | 1 + webgoat-lessons/pom.xml | 2 + .../webgoat-lesson-template/.DS_Store | Bin 0 -> 8196 bytes .../getting-started.txt | 55 +++++++++++++++ .../webgoat-lesson-template/pom.xml | 12 ++++ .../webgoat-lesson-template/src/.DS_Store | Bin 0 -> 8196 bytes .../src/main/.DS_Store | Bin 0 -> 10244 bytes .../src/main/java/.DS_Store | Bin 0 -> 8196 bytes .../src/main/java/org/.DS_Store | Bin 0 -> 8196 bytes .../src/main/java/org/owasp/.DS_Store | Bin 0 -> 8196 bytes .../src/main/java/org/owasp/webgoat/.DS_Store | Bin 0 -> 8196 bytes .../owasp/webgoat/plugin/LessonTemplate.java | 65 ++++++++++++++++++ .../owasp/webgoat/plugin/SampleAttack.java | 62 +++++++++++++++++ .../src/main/resources/.DS_Store | Bin 0 -> 6148 bytes .../src/main/resources/html/.DS_Store | Bin 0 -> 6148 bytes .../main/resources/html/LessonTemplate.html | 54 +++++++++++++++ .../resources/i18n/WebGoatLabels.properties | 7 ++ .../resources/images/firefox-proxy-config.png | Bin 0 -> 204442 bytes .../src/main/resources/js/idor.js | 18 +++++ .../en/lesson-template-attack.adoc | 3 + .../lessonPlans/en/lesson-template-intro.adoc | 19 +++++ .../lessonPlans/en/lesson-template-video.adoc | 7 ++ .../src/main/resources/video/sample-video.m4v | Bin 0 -> 21278272 bytes webgoat-server/pom.xml | 7 ++ 24 files changed, 312 insertions(+) create mode 100644 webgoat-lessons/webgoat-lesson-template/.DS_Store create mode 100644 webgoat-lessons/webgoat-lesson-template/getting-started.txt create mode 100644 webgoat-lessons/webgoat-lesson-template/pom.xml create mode 100644 webgoat-lessons/webgoat-lesson-template/src/.DS_Store create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/.DS_Store create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/java/.DS_Store create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/java/org/.DS_Store create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/java/org/owasp/.DS_Store create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/java/org/owasp/webgoat/.DS_Store create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/java/org/owasp/webgoat/plugin/LessonTemplate.java create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/java/org/owasp/webgoat/plugin/SampleAttack.java create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/resources/.DS_Store create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/resources/html/.DS_Store create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/resources/html/LessonTemplate.html create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/resources/i18n/WebGoatLabels.properties create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/resources/images/firefox-proxy-config.png create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/resources/js/idor.js create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/resources/lessonPlans/en/lesson-template-attack.adoc create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/resources/lessonPlans/en/lesson-template-intro.adoc create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/resources/lessonPlans/en/lesson-template-video.adoc create mode 100644 webgoat-lessons/webgoat-lesson-template/src/main/resources/video/sample-video.m4v diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java b/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java index 1c949c85e..349904de9 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java @@ -124,6 +124,7 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter { registry.addResourceHandler("/images/**").addResourceLocations("classpath:/images/"); registry.addResourceHandler("/lesson_js/**").addResourceLocations("classpath:/js/"); registry.addResourceHandler("/lesson_css/**").addResourceLocations("classpath:/css/"); + registry.addResourceHandler("/video/**").addResourceLocations("classpath:/video/"); super.addResourceHandlers(registry); } diff --git a/webgoat-lessons/pom.xml b/webgoat-lessons/pom.xml index 5267c0099..5137709b1 100644 --- a/webgoat-lessons/pom.xml +++ b/webgoat-lessons/pom.xml @@ -27,6 +27,8 @@ xxe idor vulnerable-components + + diff --git a/webgoat-lessons/webgoat-lesson-template/.DS_Store b/webgoat-lessons/webgoat-lesson-template/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..0d597e3dbf596974fdd877729e0dab83badc8e41 GIT binary patch literal 8196 zcmeHLT}&KB9RL3hN_Y6M1BG%uY`qkbiidKAf@o6@xMCaH6g}X8qPTavz{X|wa=Uk+ zgos9?ZPcjI2VYFAAJx9-ix29HFE*{l_+U*+)ED1;GEpCV@WKD=EFb0Ltp~q-?YAOKVUD2m}b+k_d?PAxc@ugfEw*^p*}Pydwa~Qc`<~ z>RePvMtzy^<&uh=DSk^ikh0;mai{WjLUJ_(1>7=$}x~dpq?X_1pmy zQU+y!K!Ctz1jOE70uJOMo0(gGem4!rZEIV`P)X^IvYiSmuMiKfE`KaFW6z~r)h#%^ zYW|GZGBiEo*9TR1W~Dx4+vaLr&5RiO+$68@l5iDg@x95M`w2|8gIXUF&15jx3?dPMY|4n zEH3h26s6(r!#$_Qa*OBAzxVzJA71$A(q#z(`U?r{-T=y#HAFNgYi8&hgsTtI6zMjo z%;|V4YtOE~@$j8Zr#L8YL_&{bauU&NtBA6Sa8GS--z4V+M}Jf|Ro5u$N!8VzNxsV= zkWXZ7%m4Ot);0^X7FnvZs+ld2v)*HxDdTC~8Flq}SJcKGJMZ>+j-v*}3f&~H5!jv1 zxrS{yBYNH;$=Jopy2$>r)uHd$kfqM*GO9kjm+{Y(35|wx%GQLB=2^n^;eCp7M(F$UI+aq*qTvIKtICi= zLz7)Jv1Y~{HuNMBK!&!kn8GzSY^oXEl&bq!T;T&OU6kXO$`014RAY>d68N(;LPx5* z!w)L_vhuii_es@pPv>-NZB!2_%9yb9Xqv7mjfsPD_8Svzvckniv=?G<6#8KtvS7g+ zybQ0vtME3Qhl}tjd;wp>CAb3L!1r(smf~Q#JBJrydcLDTA^uDwpU90 zm}+Y@^Do{)>8)rM>92Y?`M=O?xl)j;x@LE6ozJ$O)!FiBw4NazDdensY*?A?4KsN? z+4c|xBMofdcH|u=cY)KDIB+;*|sEmmnilLd#lD3f;8*w^ z{w7+LA;&#fj}fBPKD-N?u?6oTVs#R!y72)#g2%8QkK+j(z#$@68b>{HX*h+`XkZ>4 zEMO7m@mYKhpT`&QMSKlk$2TP1HjwT33eBYS$mo-8)=nn1f|~{Sv1{gY&%SEWwz1@9 zwp$^Ksk~*{)-?4ah+YORsI(VNgAVTc)mM%qC~qhNC9=1$_y;(){r&$9eP_^FfIxu2 z&4mD#CR52?8q>U}^vv!p76O=^~eoIn%Ayiy<5kPJKIPUpI$yLN8e7Pj07fO0B Ul;nSO5fJSE!Tv7@c#Efh0lIMvPyhe` literal 0 HcmV?d00001 diff --git a/webgoat-lessons/webgoat-lesson-template/getting-started.txt b/webgoat-lessons/webgoat-lesson-template/getting-started.txt new file mode 100644 index 000000000..c0677c6b7 --- /dev/null +++ b/webgoat-lessons/webgoat-lesson-template/getting-started.txt @@ -0,0 +1,55 @@ +##### To include lesson template in build ##### +1. edit theh webgoat-server/pom.xml file and uncomment the section under ... + + +2. Also uncomment in webgoat-lessons/pom.xml where it says ... + + +##### To add a lesson to WebGoat ##### + +There are a number of moving parts and this sample lesson will help you navigate those parts. Most of your work will be done in two directories. To start though, you can copy this directory with the name of your-lesson in the webgoat-lessons directory. + +0. The POM file + a. change the ... + webgoat-lesson-template + ... line to give your lesson its own artifactId.That should be all you need to do there + +1. The Base Class ... + In webgoat-lessons/{your-lesson}/src/main/java, refactor the LessonTemplate.java class, changing ... + a. the category in which you want your lesson to be in. You can create a new category if you want, or put in an issue to have one added + b. The 'defaultRanking' will move your lesson up or down in the categories list + c. implement a new key name pair "lesson-template.title" (the key) and update the same key/value pair (your.key=your value) in src/main/resources/i18n/WebGoatLabels.properties + d. Implement a new value for the getId method, which leads us to ... + +2. The HTML content framing ... + a. Rename the provided file in src/main/resources/html using your value from the getId method in your lesson's base class (e.g. public String getId() { return "your-lesson"; } >> "your-lesson.html") + b. Modify that file following the commented instructions in there + c. In conjunction with this file you + +3. Assignment Endpoints + a. In the above html file, you will see an example of an 'attack form'. You can create endpoints to handle these attacks and provide the user feedback and simulated output. See the example file here as well as other existing lessons for ways to extend these. You will extend the AssignmentEndpoint as the example will show + b. You can also create supporting (non-assignment) endpoints, that are not evaluated/graded. + c. See other lesson examples for creating unit/integration tests for your project as well + + +4. Getting your lesson to show up + a. modify the webgoat-lessons/pom.xml to include your project in the section + + + webgoat-lesson-template + + + + b. modify the webgoat-server/pom.xml to add your project as a dependency in the section ... + + + +
    +
    + +
    + + +
    + +
    + + +
    +
    + + + + + +