Initial/partial commit of IDOR lesson
This commit is contained in:
parent
00eeae911d
commit
65eaa934ea
@ -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";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
@ -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?
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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"));
|
||||
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -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>
|
@ -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);
|
||||
}
|
@ -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/')
|
@ -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
|
@ -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
|
||||
|
@ -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.
|
@ -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?
|
@ -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.
|
@ -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.
|
@ -19,6 +19,7 @@
|
||||
<module>http-basics</module>
|
||||
<module>sql-injection</module>
|
||||
<module>xxe</module>
|
||||
<module>idor</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
|
Loading…
x
Reference in New Issue
Block a user