diff --git a/.gitignore b/.gitignore index 2b12904c3..3a5839dac 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,4 @@ webgoat-container/src/main/webapp/users/guest.org.owasp.webgoat.plugin.*.props webgoat-container/src/main/webapp/plugin_lessons/dist-*.pom webgoat-lessons/**/target **/*.jar +**/.DS_Store diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java index 6f42e26b7..2b25b698e 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java @@ -41,6 +41,7 @@ public enum Category { INJECTION("Injection Flaws", new Integer(200)), AUTHENTICATION("Authentication Flaws", new Integer(300)), XSS("Cross-Site Scripting (XSS)", new Integer(400)), + REQ_FORGERIES("Request Forgeries", new Integer(450)), ACCESS_CONTROL("Access Control Flaws", new Integer(500)), INSECURE_CONFIGURATION("Insecure Configuration", new Integer(600)), INSECURE_COMMUNICATION("Insecure Communication", new Integer(700)), diff --git a/webgoat-lessons/csrf/src/.DS_Store b/webgoat-lessons/csrf/src/.DS_Store new file mode 100644 index 000000000..24317c318 Binary files /dev/null and b/webgoat-lessons/csrf/src/.DS_Store differ diff --git a/webgoat-lessons/csrf/src/main/.DS_Store b/webgoat-lessons/csrf/src/main/.DS_Store new file mode 100644 index 000000000..e2fe0824e Binary files /dev/null and b/webgoat-lessons/csrf/src/main/.DS_Store differ diff --git a/webgoat-lessons/csrf/src/main/java/.DS_Store b/webgoat-lessons/csrf/src/main/java/.DS_Store new file mode 100644 index 000000000..aed36ee17 Binary files /dev/null and b/webgoat-lessons/csrf/src/main/java/.DS_Store differ diff --git a/webgoat-lessons/csrf/src/main/java/org/.DS_Store b/webgoat-lessons/csrf/src/main/java/org/.DS_Store new file mode 100644 index 000000000..89210ac2d Binary files /dev/null and b/webgoat-lessons/csrf/src/main/java/org/.DS_Store differ diff --git a/webgoat-lessons/csrf/src/main/java/org/owasp/.DS_Store b/webgoat-lessons/csrf/src/main/java/org/owasp/.DS_Store new file mode 100644 index 000000000..301eb3133 Binary files /dev/null and b/webgoat-lessons/csrf/src/main/java/org/owasp/.DS_Store differ diff --git a/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/.DS_Store b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/.DS_Store new file mode 100644 index 000000000..b55427e3b Binary files /dev/null and b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/.DS_Store differ diff --git a/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRF.java b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRF.java new file mode 100644 index 000000000..b7016f3a6 --- /dev/null +++ b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRF.java @@ -0,0 +1,36 @@ +package org.owasp.webgoat.plugin; + +import com.beust.jcommander.internal.Lists; +import org.owasp.webgoat.lessons.Category; +import org.owasp.webgoat.lessons.NewLesson; + +import java.util.List; + +/** + * Created by jason on 9/29/17. + */ +public class CSRF extends NewLesson { + @Override + public Category getDefaultCategory() { + return Category.REQUEST_FORGERIES; + } + + @Override + public List getHints() { + return Lists.newArrayList(); + } + + @Override + public Integer getDefaultRanking() { + return 1; + } + + @Override + public String getTitle() { return "csrf.title"; } + + @Override + public String getId() { + return "CSRF"; + } + +} diff --git a/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFConfirmFlag1.java b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFConfirmFlag1.java new file mode 100644 index 000000000..03ca8d239 --- /dev/null +++ b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFConfirmFlag1.java @@ -0,0 +1,35 @@ +package org.owasp.webgoat.plugin; + +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.UserSessionData; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; + +/** + * Created by jason on 9/29/17. + */ + +@AssignmentPath("/csrf/confirm-flag-1") +@AssignmentHints({"csrf-get.hint1","csrf-get.hint2","csrf-get.hint3","csrf-get.hint4"}) +public class CSRFConfirmFlag1 extends AssignmentEndpoint { + + @Autowired + UserSessionData userSessionData; + + @PostMapping(produces = {"application/json"}) + public @ResponseBody AttackResult completed(String confirmFlagVal) { + + if (confirmFlagVal.equals(userSessionData.getValue("csrf-get-success").toString())) { + return success().feedback("csrf-get-null-referer.success").output("Correct, the flag was " + userSessionData.getValue("csrf-get-success")).build(); + } + + return failed().feedback("").build(); + } +} diff --git a/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFGetFlag.java b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFGetFlag.java new file mode 100644 index 000000000..56fdde8d6 --- /dev/null +++ b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFGetFlag.java @@ -0,0 +1,69 @@ +package org.owasp.webgoat.plugin; + +import org.owasp.webgoat.assignments.Endpoint; +import org.owasp.webgoat.i18n.PluginMessages; +import org.owasp.webgoat.session.UserSessionData; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +/** + * Created by jason on 9/30/17. + */ + +public class CSRFGetFlag extends Endpoint { + + @Autowired + UserSessionData userSessionData; + @Autowired + private PluginMessages pluginMessages; + + @RequestMapping(produces = {"application/json"}, method = RequestMethod.GET) + @ResponseBody + public Map invoke(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + + Map response = new HashMap<>(); + + String host = (req.getHeader("host") == null) ? "NULL" : req.getHeader("host"); +// String origin = (req.getHeader("origin") == null) ? "NULL" : req.getHeader("origin"); +// Integer serverPort = (req.getServerPort() < 1) ? 0 : req.getServerPort(); +// String serverName = (req.getServerName() == null) ? "NULL" : req.getServerName(); + String referer = (req.getHeader("referer") == null) ? "NULL" : req.getHeader("referer"); + String[] refererArr = referer.split("/"); + + if (referer.equals("NULL") && req.getParameter("csrf").equals("true")) { + Random random = new Random(); + userSessionData.setValue("csrf-get-success", random.nextInt(65536)); + response.put("success",true); + response.put("message",pluginMessages.getMessage("csrf-get-null-referer.success")); + response.put("flag",userSessionData.getValue("csrf-get-success")); + } else if (refererArr[2].equals(host)) { + response.put("success", false); + response.put("message", "Appears the request came from the original host"); + response.put("flag", null); + } else { + Random random = new Random(); + userSessionData.setValue("csrf-get-success", random.nextInt(65536)); + response.put("success",true); + response.put("message",pluginMessages.getMessage("csrf-get-other-referer.success")); + response.put("flag",userSessionData.getValue("csrf-get-success")); + } + + return response; + + } + + @Override + public String getPath() { + return "/csrf/basic-get-flag"; + } +} diff --git a/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFGetXhrFlag.java b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFGetXhrFlag.java new file mode 100644 index 000000000..f7f2e246d --- /dev/null +++ b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFGetXhrFlag.java @@ -0,0 +1,69 @@ +package org.owasp.webgoat.plugin; + +import org.owasp.webgoat.assignments.Endpoint; +import org.owasp.webgoat.i18n.PluginMessages; +import org.owasp.webgoat.session.UserSessionData; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +/** + * Created by jason on 9/30/17. + */ + +public class CSRFGetXhrFlag extends Endpoint { + + @Autowired + UserSessionData userSessionData; + @Autowired + private PluginMessages pluginMessages; + + @RequestMapping(produces = {"application/json"}, method = RequestMethod.GET) + @ResponseBody + public Map invoke(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + + Map response = new HashMap<>(); + + String host = (req.getHeader("host") == null) ? "NULL" : req.getHeader("host"); +// String origin = (req.getHeader("origin") == null) ? "NULL" : req.getHeader("origin"); +// Integer serverPort = (req.getServerPort() < 1) ? 0 : req.getServerPort(); +// String serverName = (req.getServerName() == null) ? "NULL" : req.getServerName(); + String referer = (req.getHeader("referer") == null) ? "NULL" : req.getHeader("referer"); + String[] refererArr = referer.split("/"); + + if (referer.equals("NULL") && req.getParameter("csrf").equals("true")) { + Random random = new Random(); + userSessionData.setValue("csrf-get-success", random.nextInt(65536)); + response.put("success",true); + response.put("message",pluginMessages.getMessage("csrf-get-null-referer.success")); + response.put("flag",userSessionData.getValue("csrf-get-success")); + } else if (refererArr[2].equals(host)) { + response.put("success", false); + response.put("message", "Appears the request came from the original host"); + response.put("flag", null); + } else { + Random random = new Random(); + userSessionData.setValue("csrf-get-success", random.nextInt(65536)); + response.put("success",true); + response.put("message",pluginMessages.getMessage("csrf-get-other-referer.success")); + response.put("flag",userSessionData.getValue("csrf-get-success")); + } + + return response; + + } + + @Override + public String getPath() { + return "/csrf/get-xhr-flag"; + } +} diff --git a/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/ForgedReviews.java b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/ForgedReviews.java new file mode 100644 index 000000000..b3305b415 --- /dev/null +++ b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/ForgedReviews.java @@ -0,0 +1,141 @@ +/*************************************************************************************************** + * + * + * This file is part of WebGoat, an Open Web Application Security Project utility. For details, + * please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 20014 Bruce Mayhew + * + * 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. + * + * 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. + * + * 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. + * + * Getting Source ============== + * + * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software + * projects. + * + * For details, please see http://webgoat.github.io + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ + +package org.owasp.webgoat.plugin; + +import com.beust.jcommander.internal.Lists; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.EvictingQueue; +import com.google.common.collect.Maps; +import org.apache.catalina.servlet4preview.http.HttpServletRequest; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; +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.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.IOException; +import java.util.Collection; +import java.util.Map; + +import static org.springframework.http.MediaType.ALL_VALUE; +import static org.springframework.web.bind.annotation.RequestMethod.GET; + +@AssignmentPath("/csrf/review") +@AssignmentHints({"csrf-review-hint1","csrf-review-hint2","csrf-review-hint3"}) +public class ForgedReviews extends AssignmentEndpoint { + + @Autowired + private WebSession webSession; + private static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd, HH:mm:ss"); + + private static final Map> userReviews = Maps.newHashMap(); + private static final EvictingQueue REVIEWS = EvictingQueue.create(100); + private static final String weakAntiCSRF = "2aa14227b9a13d0bede0388a7fba9aa9"; + + + static { + REVIEWS.add(new Review("secUriTy", DateTime.now().toString(fmt), "This is like swiss cheese", 0)); + REVIEWS.add(new Review("webgoat", DateTime.now().toString(fmt), "It works, sorta", 2)); + REVIEWS.add(new Review("guest", DateTime.now().toString(fmt), "Best, App, Ever", 5)); + REVIEWS.add(new Review("guest", DateTime.now().toString(fmt), "This app is so insecure, I didn't even post this review, can you pull that off too?",1)); + } + + @RequestMapping(method = GET, produces = MediaType.APPLICATION_JSON_VALUE,consumes = ALL_VALUE) + @ResponseBody + public Collection retrieveReviews() { + Collection allReviews = Lists.newArrayList(); + Collection newReviews = userReviews.get(webSession.getUserName()); + if (newReviews != null) { + allReviews.addAll(newReviews); + } + + allReviews.addAll(REVIEWS); + + return allReviews; + } + + @RequestMapping(method = RequestMethod.POST) + @ResponseBody + public AttackResult createNewReview (String reviewText, Integer stars, String validateReq, HttpServletRequest request) throws IOException { + + String host = (request.getHeader("host") == null) ? "NULL" : request.getHeader("host"); +// String origin = (req.getHeader("origin") == null) ? "NULL" : req.getHeader("origin"); +// Integer serverPort = (req.getServerPort() < 1) ? 0 : req.getServerPort(); +// String serverName = (req.getServerName() == null) ? "NULL" : req.getServerName(); + String referer = (request.getHeader("referer") == null) ? "NULL" : request.getHeader("referer"); + String[] refererArr = referer.split("/"); + + EvictingQueue reviews = userReviews.getOrDefault(webSession.getUserName(), EvictingQueue.create(100)); + Review review = new Review(); + + review.setText(reviewText); + review.setDateTime(DateTime.now().toString(fmt)); + review.setUser(webSession.getUserName()); + review.setStars(stars); + + reviews.add(review); + userReviews.put(webSession.getUserName(), reviews); + //short-circuit + if (validateReq == null || !validateReq.equals(weakAntiCSRF)) { + return failed().feedback("csrf-you-forgot-something").build(); + } + //we have the spoofed files + if (referer != "NULL" && refererArr[2].equals(host) ) { + return (failed().feedback("csrf-same-host").build()); + } else { + return (success().feedback("csrf-review.success").build()); //feedback("xss-stored-comment-failure") + } + } + + private Review parseJson(String comment) { + ObjectMapper mapper = new ObjectMapper(); + try { + return mapper.readValue(comment, Review.class); + } catch (IOException e) { + return new Review(); + } + } +} + + + + + diff --git a/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/Review.java b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/Review.java new file mode 100644 index 000000000..00f4f0fbc --- /dev/null +++ b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/Review.java @@ -0,0 +1,25 @@ +package org.owasp.webgoat.plugin; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * @author nbaars + * @since 4/8/17. + */ +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@XmlRootElement +public class Review { + private String user; + private String dateTime; + private String text; + private Integer stars; +} + diff --git a/webgoat-lessons/csrf/src/main/resources/.DS_Store b/webgoat-lessons/csrf/src/main/resources/.DS_Store new file mode 100644 index 000000000..4fb1e9b26 Binary files /dev/null and b/webgoat-lessons/csrf/src/main/resources/.DS_Store differ diff --git a/webgoat-lessons/csrf/src/main/resources/css/reviews.css b/webgoat-lessons/csrf/src/main/resources/css/reviews.css new file mode 100644 index 000000000..3bc2ca4eb --- /dev/null +++ b/webgoat-lessons/csrf/src/main/resources/css/reviews.css @@ -0,0 +1,75 @@ +/* Component: Posts */ +.post .post-heading { + height: 95px; + padding: 20px 15px; +} +.post .post-heading .avatar { + width: 60px; + height: 60px; + display: block; + margin-right: 15px; +} +.post .post-heading .meta .title { + margin-bottom: 0; +} +.post .post-heading .meta .title a { + color: black; +} +.post .post-heading .meta .title a:hover { + color: #aaaaaa; +} +.post .post-heading .meta .time { + margin-top: 8px; + color: #999; +} +.post .post-image .image { + width:20%; + height: 40%; +} +.post .post-description { + padding: 5px; +} +.post .post-footer { + border-top: 1px solid #ddd; + padding: 15px; +} +.post .post-footer .input-group-addon a { + color: #454545; +} +.post .post-footer .comments-list { + padding: 0; + margin-top: 20px; + list-style-type: none; +} +.post .post-footer .comments-list .comment { + display: block; + width: 100%; + margin: 20px 0; +} +.post .post-footer .comments-list .comment .avatar { + width: 35px; + height: 35px; +} +.post .post-footer .comments-list .comment .comment-heading { + display: block; + width: 100%; +} +.post .post-footer .comments-list .comment .comment-heading .user { + font-size: 14px; + font-weight: bold; + display: inline; + margin-top: 0; + margin-right: 10px; +} +.post .post-footer .comments-list .comment .comment-heading .time { + font-size: 12px; + color: #aaa; + margin-top: 0; + display: inline; +} +.post .post-footer .comments-list .comment .comment-body { + margin-left: 50px; +} +.post .post-footer .comments-list .comment > .comments-list { + margin-left: 50px; +} \ No newline at end of file diff --git a/webgoat-lessons/csrf/src/main/resources/html/CSRF.html b/webgoat-lessons/csrf/src/main/resources/html/CSRF.html new file mode 100644 index 000000000..64f8c03ab --- /dev/null +++ b/webgoat-lessons/csrf/src/main/resources/html/CSRF.html @@ -0,0 +1,121 @@ + + + + +
+
+
+ +
+
+
+ +
+
+ +
+ + + +
+ +
+ +
+
+ +
+
+ + Confirm Flag Value: + + + + +
+ +
+
+
+
+ +
+ +
+ + + + + +
+ +
+
+
+
+ user profile image +
+
+
+ John Doe + is selling this poster, read reviews below. +
+
24 days ago
+
+
+ +
+ image post +
+ +
+ +
+ +
+ +
+
+
+ + + +
+ +
+
+
+ + + \ No newline at end of file diff --git a/webgoat-lessons/csrf/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/csrf/src/main/resources/i18n/WebGoatLabels.properties new file mode 100644 index 000000000..84c269777 --- /dev/null +++ b/webgoat-lessons/csrf/src/main/resources/i18n/WebGoatLabels.properties @@ -0,0 +1,19 @@ +csrf.title=Cross-Site Request Forgeries +csrf-get-null-referer.success=Congratulations! Appears you made the request from your local machine. +csrf-get-other-referer.success=Congratulations! Appears you made the request from a separate host. + + +csrf-get.hint1=The form has hidden inputs. +csrf-get.hint2=You will need to use an external page and/or script to trigger it. +csrf-get.hint3=Try creating a local page or one that is uploaded and points to this form as its action. +csrf-get.hint4=The trigger can be manual or scripted to happen automatically + +csrf-same-host=It appears your request is coming from the same host you are submitting to. + +csrf-you-forgot-something=There's something missing from your request it appears, so I can't process it. + +csrf-review.success=It appears you have submitted correctly from another site. Go reload and see if your post is there. + +csrf-review-hint1=Again, you will need to submit from an external domain/host to trigger this action. While CSRF can often be triggered from the same host (e.g. via persisted payload), this doesn't work that way. +csrf-review-hint2=Remember, you need to mimic the existing workflow/form. +csrf-review-hint3=This one has a weak anti-CSRF protection, but you do need to overcome (mimic) it \ No newline at end of file diff --git a/webgoat-lessons/csrf/src/main/resources/js/csrf-review.js b/webgoat-lessons/csrf/src/main/resources/js/csrf-review.js new file mode 100644 index 000000000..ef2b39977 --- /dev/null +++ b/webgoat-lessons/csrf/src/main/resources/js/csrf-review.js @@ -0,0 +1,46 @@ +$(document).ready(function () { +// $("#postReview").on("click", function () { +// var commentInput = $("#reviewInput").val(); +// $.ajax({ +// type: 'POST', +// url: 'csrf/review', +// data: JSON.stringify({text: commentInput}), +// contentType: "application/json", +// dataType: 'json' +// }).then( +// function () { +// getChallenges(); +// $("#commentInput").val(''); +// } +// ) +// }); + + var html = '
  • ' + + '
    ' + + 'avatar' + + '
    ' + + '
    ' + + '
    ' + + '

    USER / STARS stars

    ' + + '
    DATETIME
    ' + + '
    ' + + '

    COMMENT

    ' + + '
    ' + + '
  • '; + + getChallenges(); + + function getChallenges() { + $("#list").empty(); + $.get('csrf/review', function (result, status) { + 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); + comment = comment.replace('STARS', result[i].stars) + $("#list").append(comment); + } + + }); + } +}) \ No newline at end of file diff --git a/webgoat-lessons/csrf/src/main/resources/lessonPlans/.DS_Store b/webgoat-lessons/csrf/src/main/resources/lessonPlans/.DS_Store new file mode 100644 index 000000000..1151fe231 Binary files /dev/null and b/webgoat-lessons/csrf/src/main/resources/lessonPlans/.DS_Store differ diff --git a/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Basic_Get-1.adoc b/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Basic_Get-1.adoc new file mode 100644 index 000000000..c81193a70 --- /dev/null +++ b/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Basic_Get-1.adoc @@ -0,0 +1,3 @@ +== Confirm Flag + +Confirm the flag you should have gotten on the previous page below. \ No newline at end of file diff --git a/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/lessonPlans/en/CSRF_GET.adoc b/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_GET.adoc similarity index 77% rename from webgoat-lessons/csrf/src/main/resources/plugin/CSRF/lessonPlans/en/CSRF_GET.adoc rename to webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_GET.adoc index b0271a5f7..12d69f08e 100644 --- a/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/lessonPlans/en/CSRF_GET.adoc +++ b/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_GET.adoc @@ -1,6 +1,6 @@ == CSRF with a GET request -This is the most easiest CSRF attack to perform. For example you receive an e-mail with the following content: +This is the most simple CSRF attack to perform. For example you receive an e-mail with the following content: `View my Pictures!` diff --git a/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Get_Flag.adoc b/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Get_Flag.adoc new file mode 100644 index 000000000..82c341785 --- /dev/null +++ b/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Get_Flag.adoc @@ -0,0 +1,4 @@ +== Basic Get CSRF Exercise + +Trigger the form below from an external source while logged in. The response will include a 'flag' (a numeric value). + diff --git a/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Impact_Defense.adoc b/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Impact_Defense.adoc new file mode 100644 index 000000000..f1faab81b --- /dev/null +++ b/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Impact_Defense.adoc @@ -0,0 +1,20 @@ +== CSRF Impact + +The impact is limited only by what the logged in user can do (if the site/function/action is not protected properly). +The areas that are really prone to CSRF attacks are IoT devices and 'smart' appliances. Sadly, many consumer-grade routers +have also proven vulnerable to CSRF. + +== CSRF Solution + +Fortunately, many (web) application frameworks now come with built in support to handle CSRF attacks. For example, Spring and +Tomcat have this on by default. As long as you don't turn it off (like it is in WebGoat), you should be safe from CSRF attacks. + +See the following for more information on CSRF protections: + +https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet (Prevention/Defense) + +https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) (Attack) + +https://tomcat.apache.org/tomcat-7.0-doc/config/filter.html#CSRF_Prevention_Filter / https://tomcat.apache.org/tomcat-8.0-doc/config/filter.html#CSRF_Prevention_Filter (Tomcat) + +https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html \ No newline at end of file diff --git a/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Reviews.adoc b/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Reviews.adoc new file mode 100644 index 000000000..6fb15da4e --- /dev/null +++ b/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Reviews.adoc @@ -0,0 +1,9 @@ +== Post a review on someone else's behalf + +The page below simulates a comment/review page. The difference here is that you have to inititate the submission elsewhere as you might +with a CSRF attack and like the previous exercise. It's easier than you think. In most cases, the trickier part is +finding somewhere that you want to execute the CSRF attack. The classic example is account/wire transfers in someone's bank account. + +But we're keepoing it simple here. In this case, you just need to trigger a review submission on behalf of the currently +logged in user. + diff --git a/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/lessonPlans/en/CSRF_intro.adoc b/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_intro.adoc similarity index 78% rename from webgoat-lessons/csrf/src/main/resources/plugin/CSRF/lessonPlans/en/CSRF_intro.adoc rename to webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_intro.adoc index 3cfda81aa..fb6a15641 100644 --- a/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/lessonPlans/en/CSRF_intro.adoc +++ b/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_intro.adoc @@ -1,11 +1,11 @@ -=== What is a Crosse-site request forgery? +=== What is a Cross-site request forgery? Cross-site request forgery, also known as one-click attack or session riding and abbreviated as CSRF (sometimes pronounced sea-surf) or XSRF, is a type of malicious exploit of a website where unauthorized commands are transmitted from a user that the website trusts. Unlike cross-site scripting (XSS), which exploits the trust a user has for a particular site, CSRF exploits the trust that a site has in a user's browser. -A cross-site request forgery is a confused deputy attack against a web browser. CSRF commonly has the following characteristics: +A cross-site request forgery is a 'confused deputy' attack against a web browser. CSRF commonly has the following characteristics: * It involves sites that rely on a user's identity. * It exploits the site's trust in that identity. @@ -16,7 +16,7 @@ At risk are web applications that perform actions based on input from trusted an the specific action. A user who is authenticated by a cookie saved in the user's web browser could unknowingly send an HTTP request to a site that trusts the user and thereby causes an unwanted action. -CSRF attacks target functionality that causes a state change on the server, such as changing the victim's email address or password, or purchasing +A CSRF attack targets/abuses basic web functionality. If the site allows that causes a state change on the server, such as changing the victim's email address or password, or purchasing something. Forcing the victim to retrieve data doesn't benefit an attacker because the attacker doesn't receive the response, the victim does. As such, CSRF attacks target state-changing requests. diff --git a/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/html/CSRF.html b/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/html/CSRF.html deleted file mode 100644 index c2bb6e238..000000000 --- a/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/html/CSRF.html +++ /dev/null @@ -1,181 +0,0 @@ - - -
    - - -
    -
    - -
    - - -
    -
    - -
    - - -
    - -
    -
    - - - -
    - -
    - Registration form - - - - - - - - - - - - - - - - - - -
    Username
    E-mail
    Password
    -
    -
    - -
    -
    -
    - -
    -
    - -
    -
    - -
    - -
    - - -
    -
    -
    - - - -
    - -
    - Registration form - - - - - - - - - - - - - - - - - - -
    Username
    E-mail
    Password
    -
    -
    - -
    -
    -
    - -
    -
    - - -
    - - -
    -
    - -
    - - -
    -
    - -
    - - -
    -
    -
    - - - -
    - -
    - Registration form - - - - - - - - - - - - - - - - - - -
    Username
    E-mail
    Password
    -
    -
    - -
    -
    -
    - -
    -
    - - -
    - - -
    -
    - - - \ No newline at end of file diff --git a/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/js/xxe.js b/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/js/xxe.js deleted file mode 100644 index b38c2d9c2..000000000 --- a/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/js/xxe.js +++ /dev/null @@ -1,15 +0,0 @@ -webgoat.customjs.register = function () { - var xml = '' + - '' + - ' ' + 'test' + '' + - ' ' + 'test' + '' + - ''; - return xml; -} -webgoat.customjs.registerJson = function () { - var json = '{' + - ' "user":' + '"test"' + - ' "password":' + '"test"' + - '}'; - return json; -} diff --git a/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/lessonPlans/en/CSRF_plan.adoc b/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/lessonPlans/en/CSRF_plan.adoc deleted file mode 100644 index 1cb953de9..000000000 --- a/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/lessonPlans/en/CSRF_plan.adoc +++ /dev/null @@ -1,10 +0,0 @@ -= Cross-site request forgery (CSRF) - -== Concept - -This lesson teaches how to what a CSRF attack is and how it can be abused and protected against. - -== Goals - -* The user should have basic knowledge of JavaScript -* The user will learn to perform a CSRF attack and how to protected against it. diff --git a/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/secret.txt b/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/secret.txt deleted file mode 100644 index e4ec56814..000000000 --- a/webgoat-lessons/csrf/src/main/resources/plugin/CSRF/secret.txt +++ /dev/null @@ -1 +0,0 @@ -WebGoat 8 rocks... \ No newline at end of file diff --git a/webgoat-lessons/csrf/webgoat-lesson-template/.DS_Store b/webgoat-lessons/csrf/webgoat-lesson-template/.DS_Store new file mode 100644 index 000000000..0d597e3db Binary files /dev/null and b/webgoat-lessons/csrf/webgoat-lesson-template/.DS_Store differ diff --git a/webgoat-lessons/csrf/webgoat-lesson-template/getting-started.txt b/webgoat-lessons/csrf/webgoat-lesson-template/getting-started.txt new file mode 100644 index 000000000..c0677c6b7 --- /dev/null +++ b/webgoat-lessons/csrf/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 ... + + + +
    + + +
    + + +
    + +
    + + +
    +
    + + + + + +