diff --git a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDOR.java b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDOR.java
new file mode 100644
index 000000000..339e4a083
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDOR.java
@@ -0,0 +1,67 @@
+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;
+
+/**
+ * ************************************************************************************************
+ * 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.
+ *
+ *
+ * @author misfir3
+ * @version $Id: $Id
+ * @since January 3, 2017
+ */
+public class IDOR extends NewLesson {
+
+ @Override
+ public Category getDefaultCategory() {
+ return Category.ACCESS_CONTROL;
+ }
+
+ @Override
+ public List getHints() {
+ return Lists.newArrayList("log in first");
+ }
+
+ @Override
+ public Integer getDefaultRanking() {
+ return 20;
+ }
+
+ @Override
+ public String getTitle() {
+ return "Insecure Direct Object References";
+ }
+
+ @Override
+ public String getId() {
+ return "IDOR";
+ }
+
+
+
+}
diff --git a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORDiffAttributes.java b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORDiffAttributes.java
new file mode 100644
index 000000000..39de62956
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORDiffAttributes.java
@@ -0,0 +1,35 @@
+package org.owasp.webgoat.plugin;
+
+import org.owasp.webgoat.endpoints.AssignmentEndpoint;
+import org.owasp.webgoat.lessons.AttackResult;
+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 javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Path;
+import java.io.IOException;
+
+/**
+ * Created by jason on 1/5/17.
+ */
+@Path("IDOR/diff-attributes")
+public class IDORDiffAttributes extends AssignmentEndpoint {
+
+ @RequestMapping(method = RequestMethod.POST)
+ public @ResponseBody
+ AttackResult completed(@RequestParam String attributes, HttpServletRequest request) throws IOException {
+ attributes = attributes.trim();
+ String[] diffAttribs = attributes.split(",");
+ if (diffAttribs.length < 2) {
+ return AttackResult.failed("You did not list two attributes string delimited");
+ }
+ if (diffAttribs[0].toLowerCase().equals("userid") && diffAttribs[1].toLowerCase().equals("admin") ||
+ diffAttribs[1].toLowerCase().equals("userid") && diffAttribs[0].toLowerCase().equals("admin")) {
+ return AttackResult.success("Correct, the two attributes not displayed are userId & admin. Keep those in mind");
+ } else {
+ return AttackResult.failed("Try again. Look in your browser dev tools or Proxy and compare to what's displayed on the screen.");
+ }
+ }
+}
diff --git a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDOREditOwnProfiile.java b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDOREditOwnProfiile.java
new file mode 100644
index 000000000..c2f1d76ea
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDOREditOwnProfiile.java
@@ -0,0 +1,59 @@
+package org.owasp.webgoat.plugin;
+
+import org.owasp.webgoat.endpoints.AssignmentEndpoint;
+import org.owasp.webgoat.lessons.AttackResult;
+import org.owasp.webgoat.session.UserSessionData;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Path;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * ************************************************************************************************
+ * 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.
+ *
+ *
+ * @author misfir3
+ * @version $Id: $Id
+ * @since January 3, 2017
+ */
+
+@Path("/IDOR/{userId}/profile-edit")
+public class IDOREditOwnProfiile extends AssignmentEndpoint {
+
+ private Map> idorUserInfo = new HashMap<>();
+
+ @RequestMapping(method = RequestMethod.POST)
+ public @ResponseBody
+ AttackResult completed(@PathVariable String userId, @RequestParam String password, HttpServletRequest request) throws IOException {
+
+ UserSessionData userSessionData = getUserSessionData();
+
+ return trackProgress(AttackResult.failed("still working on this")); //TODO: How do we localize messages like this?
+
+ }
+
+}
diff --git a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORLogin.java b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORLogin.java
new file mode 100644
index 000000000..df5fe9fe5
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORLogin.java
@@ -0,0 +1,98 @@
+package org.owasp.webgoat.plugin;
+
+import org.owasp.webgoat.endpoints.AssignmentEndpoint;
+import org.owasp.webgoat.lessons.AttackResult;
+
+import org.owasp.webgoat.session.UserSessionData;
+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 javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Path;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * ************************************************************************************************
+ * 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.
+ *
+ *
+ * @author misfir3
+ * @version $Id: $Id
+ * @since January 3, 2017
+ */
+
+@Path("/IDOR/login")
+public class IDORLogin extends AssignmentEndpoint {
+
+ private Map> idorUserInfo = new HashMap<>();
+
+ public void initIDORInfo() {
+
+ idorUserInfo.put("tom",new HashMap());
+ idorUserInfo.get("tom").put("password","cat");
+ idorUserInfo.get("tom").put("id","2342384");
+ idorUserInfo.get("tom").put("color","yellow");
+ idorUserInfo.get("tom").put("size","small");
+
+ idorUserInfo.put("bill",new HashMap());
+ idorUserInfo.get("bill").put("password","buffalo");
+ idorUserInfo.get("bill").put("id","2342388");
+ idorUserInfo.get("bill").put("color","brown");
+ idorUserInfo.get("bill").put("size","large");
+
+ }
+
+ @RequestMapping(method = RequestMethod.POST)
+ public @ResponseBody
+ AttackResult completed(@RequestParam String username, @RequestParam String password, HttpServletRequest request) throws IOException {
+
+ initIDORInfo();
+ UserSessionData userSessionData = getUserSessionData();
+
+ System.out.println("----:" + username + ":----");
+ if (idorUserInfo.containsKey(username)) {
+ System.out.println("****:" + username);
+ if ("tom".equals(username) && idorUserInfo.get("tom").get("password").equals(password)) {
+ userSessionData.setValue("idor-authenticated-as", username);
+ userSessionData.setValue("idor-authenticated-user-id", idorUserInfo.get(username).get("id"));
+ return trackProgress(AttackResult.success("You are now logged in as " + username + ". Please proceed."));
+ } else {
+ return trackProgress(AttackResult.failed("credentials provided are not correct"));
+ }
+ } else {
+ return trackProgress(AttackResult.failed("credentials provided are not correct"));
+ }
+ }
+
+// userSessionData.setValue("foo","bar");
+// System.out.println("*** value set");
+// System.out.println("*** fetching value");
+// System.out.println(userSessionData.getValue("foo"));
+// System.out.println("*** DONE fetching value");
+// return trackProgress(AttackResult.failed("You are close, try again"));
+
+}
diff --git a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORViewOwnProfile.java b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORViewOwnProfile.java
new file mode 100644
index 000000000..47ab16b3e
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORViewOwnProfile.java
@@ -0,0 +1,59 @@
+package org.owasp.webgoat.plugin;
+
+
+import org.owasp.webgoat.endpoints.Endpoint;
+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 com.google.common.collect.Lists;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Created by jason on 1/5/17.
+ */
+public class IDORViewOwnProfile extends Endpoint{
+
+ @Autowired
+ UserSessionData userSessionData;
+
+ @RequestMapping(produces = {"application/json"}, method = RequestMethod.GET)
+ @ResponseBody
+ public Map invoke(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ Map details = new HashMap<>();
+ try {
+ if (userSessionData.getValue("idor-authenticated-as").equals("tom")) {
+ //going to use session auth to view this one
+ String authUserId = userSessionData.getValue("idor-authenticated-user-id");
+ UserProfile userProfile = new UserProfile(authUserId);
+ details.put("userId",userProfile.getUserId());
+ details.put("name",userProfile.getName());
+ details.put("color",userProfile.getColor());
+ details.put("size",userProfile.getSize());
+ details.put("admin",userProfile.isAdmin());
+
+ } else {
+ details.put("error","You do not have privileges to view the profile.");
+ System.out.println("Not auth'd as tom");
+ }
+ }catch (Exception ex) {
+ System.out.println(ex.getMessage());
+ }
+ return details;
+ }
+
+ @Override
+ public String getPath() {
+ return "/IDOR/profile";
+ }
+}
diff --git a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORViewOwnProfileAltUrl.java b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORViewOwnProfileAltUrl.java
new file mode 100644
index 000000000..feb09dfd1
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORViewOwnProfileAltUrl.java
@@ -0,0 +1,63 @@
+package org.owasp.webgoat.plugin;
+
+
+import org.owasp.webgoat.endpoints.AssignmentEndpoint;
+import org.owasp.webgoat.endpoints.Endpoint;
+import org.owasp.webgoat.lessons.AttackResult;
+import org.owasp.webgoat.session.UserSessionData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.Path;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Created by jason on 1/5/17.
+ */
+@Path("IDOR/profile/alt-path")
+public class IDORViewOwnProfileAltUrl extends AssignmentEndpoint{
+
+ @Autowired
+ UserSessionData userSessionData;
+
+ @RequestMapping(method = RequestMethod.POST)
+ @ResponseBody
+ public AttackResult completed(@RequestParam String url, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ Map details = new HashMap<>();
+ try {
+ if (userSessionData.getValue("idor-authenticated-as").equals("tom")) {
+ //going to use session auth to view this one
+ String authUserId = userSessionData.getValue("idor-authenticated-user-id");
+ //don't care about http://localhost:8080 ... just want WebGoat/
+ String[] urlParts = url.split("/");
+ System.out.println("************");
+ System.out.println(urlParts[0]);
+ System.out.println(urlParts[1]);
+ System.out.println(urlParts[2]);
+ System.out.println(urlParts[3]);
+ System.out.println("************");
+ if (urlParts[0].equals("WebGoat") && urlParts[1].equals("IDOR") && urlParts[2].equals("profile") && urlParts[3].equals(authUserId)) {
+ UserProfile userProfile = new UserProfile(authUserId);
+ details.put("userId", userProfile.getUserId());
+ details.put("name", userProfile.getName());
+ details.put("color", userProfile.getColor());
+ details.put("size", userProfile.getSize());
+ details.put("admin", userProfile.isAdmin());
+ return AttackResult.success("congratultions, you have used the alternate Url/route to view your own profile.",details.toString());
+ }
+
+ } else {
+ return AttackResult.failed("please try again. The alternoute route is very similar to the previous way you viewed your profile. Only one difference really");
+ }
+ } catch (Exception ex) {
+ System.out.println(ex.getMessage());
+ }
+ return AttackResult.failed("fall back");
+ }
+
+}
diff --git a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/UserProfile.java b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/UserProfile.java
new file mode 100644
index 000000000..f5e2f076a
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/UserProfile.java
@@ -0,0 +1,86 @@
+package org.owasp.webgoat.plugin;
+
+/**
+ * Created by jason on 1/5/17.
+ */
+public class UserProfile {
+ private String userId;
+ private String name;
+ private String color;
+ private String size;
+ private boolean isAdmin;
+ // anyting else?
+
+ public UserProfile() {}
+
+ public UserProfile(String id) {
+ this.userId = id;
+ setProfileFromId(id);
+ }
+
+ //
+ private void setProfileFromId(String id) {
+ // emulate look up from database
+ if (id.equals("2342384")) {
+ this.color = "yellow";
+ this.name = "Tom Cat";
+ this.size = "small";
+ this.isAdmin = false;
+ } else if (id.equals("2342388")) {
+ this.color = "brown";
+ this.name = "Buffalo Bill";
+ this.size = "large";
+ this.isAdmin = false;
+ }
+
+ }
+
+ public String toHTMLString() {
+ String htmlBreak = "
";
+ return "userId" + this.userId + htmlBreak +
+ "name" + this.name + htmlBreak +
+ "size" + this.size + htmlBreak +
+ "isAdmin" + this.isAdmin;
+ }
+
+ //
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getColor() {
+ return color;
+ }
+
+ public void setColor(String color) {
+ this.color = color;
+ }
+
+ public String getSize() {
+ return size;
+ }
+
+ public void setSize(String size) {
+ this.size = size;
+ }
+
+ public boolean isAdmin() {
+ return isAdmin;
+ }
+
+ public void setAdmin(boolean admin) {
+ isAdmin = admin;
+ }
+}
diff --git a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/ViewOtherUserProfileEndpoint.java b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/ViewOtherUserProfileEndpoint.java
new file mode 100644
index 000000000..2a2b5c2cf
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/ViewOtherUserProfileEndpoint.java
@@ -0,0 +1,64 @@
+package org.owasp.webgoat.plugin;
+
+import com.google.common.collect.Lists;
+import org.owasp.webgoat.endpoints.AssignmentEndpoint;
+import org.owasp.webgoat.endpoints.Endpoint;
+import org.owasp.webgoat.lessons.AttackResult;
+import org.owasp.webgoat.session.UserSessionData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.Path;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by jason on 1/5/17.
+ */
+
+@Path("/IDOR/viewprofile/{id}")
+public class ViewOtherUserProfileEndpoint extends AssignmentEndpoint {
+
+ private String color;
+ private String size;
+ private boolean isAdmin;
+
+ @Autowired
+ UserSessionData userSessionData;
+
+ @RequestMapping(produces = {"application/json"})
+ public @ResponseBody
+ AttackResult completed(@PathVariable String userId, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ List json = Lists.newArrayList();
+ // can be re-used
+ Map errorMap = new HashMap();
+ errorMap.put("error","not logged in, go back and log in first");
+
+ if (userSessionData.getValue("idor-authenticated-as") == null) {
+ json.add(errorMap);
+ return trackProgress(AttackResult.failed("You must authenticate first"));
+ } else {
+ if (userSessionData.getValue("idor-authenticated-as").equals("bill") || userSessionData.getValue("idor-authenticated-as").equals("tom")) {
+ System.out.println("**** authenticated as " + userSessionData.getValue("idor-authenticated-as"));
+ //logged in
+ String authUserId = userSessionData.getValue("idor-authenticated-user-id");
+ //secure code would check to make sure authUserId matches userId ... and in this endpoint, we won't bother with that
+ UserProfile userProfile = new UserProfile(userId);
+ return trackProgress(AttackResult.failed("still working"));
+ }
+ }
+ // else
+ return trackProgress(AttackResult.failed("fall back"));
+ }
+
+
+
+
+}
diff --git a/webgoat-lessons/idor/src/main/resources/plugin/IDOR/html/IDOR.html b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/html/IDOR.html
new file mode 100644
index 000000000..c196f8954
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/html/IDOR.html
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/webgoat-lessons/idor/src/main/resources/plugin/IDOR/js/idor.js b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/js/idor.js
new file mode 100644
index 000000000..05ab1206f
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/js/idor.js
@@ -0,0 +1,18 @@
+// need custom js for this?
+
+webgoat.customjs.idorViewProfile = function(data) {
+ webgoat.customjs.jquery('#idor-profile').html(
+ 'name:' + data.name + '
'+
+ 'color:' + data.color + '
'+
+ 'size:' + data.size + '
'
+ );
+}
+
+var onViewProfile = function () {
+ console.warn("on view profile activated")
+ webgoat.customjs.jquery.ajax({
+ method: "GET",
+ url: "/WebGoat/IDOR/profile",
+ contentType: 'application/json; charset=UTF-8'
+ }).then(webgoat.customjs.idorViewProfile);
+}
diff --git a/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_inputAltPath.adoc b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_inputAltPath.adoc
new file mode 100644
index 000000000..1de5253e6
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_inputAltPath.adoc
@@ -0,0 +1 @@
+Please input the alternate path to the Url to view your own profile. Please start witih 'WebGoat' (i.e. disregard 'http://localhost:8080/')
\ No newline at end of file
diff --git a/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_intro.adoc b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_intro.adoc
new file mode 100644
index 000000000..7a5120bbf
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_intro.adoc
@@ -0,0 +1,37 @@
+
+== Direct Object References
+
+Direct Object References are when an application uses client-provided input to access data & objects.
+
+=== Examples
+
+Examples of Direct Object References using the GET method may look something like
+
+`https://some.company.tld/dor?id=12345`
+
+`https://some.company.tld/images?img=12345`
+
+`https://some.company.tld/dor/12345`
+
+=== Other Methods
+
+POST, PUT, DELETE or other methods are also potentially succeptible and mainly only differ in the method and the potential payload.
+
+== *Insecure* Direct Object References
+
+These are considered insecure when the reference is not properly handled and allows for authorization bypasses.
+Let's say that as a user, you go to view your profile and the URL looks something like:
+
+`https://some.company.tld/app/user/23398`
+
+\... and you can view your profile there. What happens if you navigate to:
+
+`https://some.company.tld/app/user/23399` ... or use another number at the end. If you can manipulate the number (user id) and view another's profile, then the object reference is insecure.
+This of course can be checked or expanded beyond GET methods to view data, but to also manipulate data.
+
+=== More good reading
+Before we go on to practice, here's some good reading on Insecure Direct Object References:
+
+* https://www.owasp.org/index.php/Testing_for_Insecure_Direct_Object_References_(OTG-AUTHZ-004)
+* https://www.owasp.org/index.php/Top_10_2013-A4-Insecure_Direct_Object_References
+* http://cwe.mitre.org/data/definitions/639.html
diff --git a/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_mitigation.adoc b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_mitigation.adoc
new file mode 100644
index 000000000..f92324e39
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_mitigation.adoc
@@ -0,0 +1,10 @@
+== Secure Object References
+
+=== Using Indrect References
+In some cases, using an indirect reference may help. This of course may make the application harder to trouble shoot and may also affect performance.
+
+=== Access Controls
+Since the root of 'Insecure' of IDOR's s really in controlling access to the objects referenced, the key to making them secure is implementing vertical and horizontal access control.
+
+==== Knowing How Things Should be Secured
+
diff --git a/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_viewDiffs.adoc b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_viewDiffs.adoc
new file mode 100644
index 000000000..8dfba20fa
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_viewDiffs.adoc
@@ -0,0 +1,6 @@
+
+=== Observing Differences & Behaviors
+
+A consistent principle from the offensive side of AppSec is to view differences from the raw response to what is visible.
+In other words (as you may have already noted in the client-side filtering lesson), there is often data in the raw response that doesn't show up on the screen/page.
+View the profile below and take note of the differences.
diff --git a/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_viewOwnAltPath.adoc b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_viewOwnAltPath.adoc
new file mode 100644
index 000000000..80f0a2c45
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_viewOwnAltPath.adoc
@@ -0,0 +1,6 @@
+
+=== Guessing & Predicting Patterns
+
+The application we are working with seems to follow a RESTful pattern so far as the profile goes. Many apps have roles in which an elevated user may access content of another.
+In that case, just /profile won't work since the own user's session/authentication data won't tell us whose profile they want view.
+So, what do you think is a likely pattern to view your own profile explicitly?
\ No newline at end of file
diff --git a/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_whatDiffs.adoc b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_whatDiffs.adoc
new file mode 100644
index 000000000..253db42c3
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/IDOR_whatDiffs.adoc
@@ -0,0 +1 @@
+In the text input below, list the two attributes that are in the server's response, but don't show above in the profile.
diff --git a/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/temp.txt b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/temp.txt
new file mode 100644
index 000000000..3b4a38c86
--- /dev/null
+++ b/webgoat-lessons/idor/src/main/resources/plugin/IDOR/lessonPlans/en/temp.txt
@@ -0,0 +1,15 @@
+
+
+- Describe how the attack works / should be some outpu
+
+Concept / Topic To Teach:
+ This lesson teaches how to perform XML External Entity Attacks.
+
+
+
+How the attacks works:
+
+An XML External Entity attack is a type of attack against an application that parses XML input.
+This attack occurs when XML input containing a reference to an external entity is processed by a weakly
+configured XML parser. This attack may lead to the disclosure of confidential data, denial of service,
+server side request forgery, port scanning from the perspective of the machine where the parser is located, and other system impacts.
diff --git a/webgoat-lessons/pom.xml b/webgoat-lessons/pom.xml
index 0bae95436..4a53dfd52 100644
--- a/webgoat-lessons/pom.xml
+++ b/webgoat-lessons/pom.xml
@@ -19,6 +19,7 @@
http-basics
sql-injection
xxe
+
idor