Initial/partial commit of IDOR lesson

This commit is contained in:
Jason White 2017-01-05 17:30:53 -05:00
parent 00eeae911d
commit 65eaa934ea
18 changed files with 763 additions and 0 deletions

View File

@ -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/
* <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author misfir3
* @version $Id: $Id
* @since January 3, 2017
*/
public class IDOR extends NewLesson {
@Override
public Category getDefaultCategory() {
return Category.ACCESS_CONTROL;
}
@Override
public List<String> 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";
}
}

View File

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

View File

@ -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/
* <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author misfir3
* @version $Id: $Id
* @since January 3, 2017
*/
@Path("/IDOR/{userId}/profile-edit")
public class IDOREditOwnProfiile extends AssignmentEndpoint {
private Map<String,Map<String,String>> 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?
}
}

View File

@ -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/
* <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author misfir3
* @version $Id: $Id
* @since January 3, 2017
*/
@Path("/IDOR/login")
public class IDORLogin extends AssignmentEndpoint {
private Map<String,Map<String,String>> idorUserInfo = new HashMap<>();
public void initIDORInfo() {
idorUserInfo.put("tom",new HashMap<String,String>());
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<String,String>());
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"));
}

View File

@ -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<String, Object> invoke(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Map<String,Object> 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";
}
}

View File

@ -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<String,Object> 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");
}
}

View File

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

View File

@ -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<String, Object> 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"));
}
}

View File

@ -0,0 +1,137 @@
<html xmlns:th="http://www.thymeleaf.org">
<div class="lesson-page-wrapper">
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
<div class="adoc-content" th:replace="doc:IDOR_intro.adoc"></div>
</div>
<div class="lesson-page-wrapper">
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
<div class="adoc-content" th:replace="doc:IDOR_login.adoc"></div>
<div class="attack-container">
<!-- using attack-form class on your form, will allow your request to be ajaxified and stay within the display framework for webgoat -->
<div class="lessonContent">
<!-- using attack-form class on your form will allow your request to be ajaxified and stay within the display framework for webgoat -->
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
<!-- modify the action to point to the intended endpoint -->
<form class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/IDOR/login"
enctype="application/json;charset=UTF-8">
<table>
<tr>
<td>user/pass</td>
<td>user:<input name="username" value="" type="TEXT" /></td>
<td>pass:<input name="password" value="" type="password" /></td>
<td>
<input
name="submit" value="Submit" type="SUBMIT"/>
</td>
</tr>
</table>
</form>
</div>
<!-- do not remove the two following div's, this is where your feedback/output will land -->
<div class="attack-feedback"></div>
<div class="attack-output"></div>
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
</div>
</div>
<div class="lesson-page-wrapper">
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
<div class="adoc-content" th:replace="doc:IDOR_viewDiffs.adoc"></div>
<div class="attack-container">
<!-- using attack-form class on your form, will allow your request to be ajaxified and stay within the display framework for webgoat -->
<div>
<!-- using attack-form class on your form will allow your request to be ajaxified and stay within the display framework for webgoat -->
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
<!-- modify the action to point to the intended endpoint -->
<form class="attack-form" accept-charset="UNKNOWN"
method="GET" name="form"
action="/WebGoat/IDOR/profile"
enctype="application/json;charset=UTF-8">
<script th:src="@{/plugin_lessons/plugin/IDOR/js/idor.js}" />
<input name="View Profile" value="View Profile" type="button" onclick="onViewProfile();" />
</form>
</div>
<div id="idor-profile"></div>
<!-- do not remove the two following div's, this is where your feedback/output will land -->
<div class="attack-feedback"></div>
<div class="attack-output"></div>
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
</div>
<div class="attack-container">
<!-- using attack-form class on your form, will allow your request to be ajaxified and stay within the display framework for webgoat -->
<div class="lessonContent">
<!-- using attack-form class on your form will allow your request to be ajaxified and stay within the display framework for webgoat -->
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
<div class="adoc-content" th:replace="doc:IDOR_whatDiffs.adoc"></div>
<!-- modify the action to point to the intended endpoint -->
<form class="attack-form"
method="POST" name="diff-form"
action="IDOR/diff-attributes"
enctype="application/json;charset=UTF-8">
<input name="attributes" type="text" />
<input name="Submit Diffs" value="Submit Diffs" type="submit" />
</form>
</div>
<!-- do not remove the two following div's, this is where your feedback/output will land -->
<div class="attack-feedback"></div>
<div class="attack-output"></div>
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
</div>
</div>
<div class="lesson-page-wrapper">
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
<div class="adoc-content" th:replace="doc:IDOR_viewOwnAltPath.adoc"></div>
<div class="attack-container">
<!-- using attack-form class on your form, will allow your request to be ajaxified and stay within the display framework for webgoat -->
<div class="lessonContent">
<!-- using attack-form class on your form will allow your request to be ajaxified and stay within the display framework for webgoat -->
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
<!-- modify the action to point to the intended endpoint -->
<form class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/IDOR/profile/alt-path"
enctype="application/json;charset=UTF-8">
<div class="adoc-content" th:replace="doc:IDOR_inputAltPath.adoc"></div>
<input name="url" value="WebGoat/" type="text"/>
<input name="submit" value="Submit" type="SUBMIT"/>
</form>
</div>
<!-- do not remove the two following div's, this is where your feedback/output will land -->
<div class="attack-feedback"></div>
<div class="attack-output"></div>
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
</div>
</div>
<div class="lesson-page-wrapper">
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
<div class="adoc-content" th:replace="doc:IDOR_mitigation.adoc"></div>
</div>
</html>

View File

@ -0,0 +1,18 @@
// need custom js for this?
webgoat.customjs.idorViewProfile = function(data) {
webgoat.customjs.jquery('#idor-profile').html(
'name:' + data.name + '<br/>'+
'color:' + data.color + '<br/>'+
'size:' + data.size + '<br/>'
);
}
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);
}

View File

@ -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/')

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,15 @@
- Describe how the attack works / should be some outpu
<p><b>Concept / Topic To Teach:</b> </p>
This lesson teaches how to perform XML External Entity Attacks.
<br>
<div align="Left">
<p>
<b>How the attacks works:</b>
</p>
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.

View File

@ -19,6 +19,7 @@
<module>http-basics</module> <module>http-basics</module>
<module>sql-injection</module> <module>sql-injection</module>
<module>xxe</module> <module>xxe</module>
<module>idor</module>
</modules> </modules>
<dependencies> <dependencies>