#304 incremental addition for IDOR, still experiencing 400 with PUT method
This commit is contained in:
parent
fe4f568fc0
commit
4e9b30d7f6
@ -12,8 +12,35 @@ import javax.ws.rs.Path;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by jason on 1/5/17.
|
||||
* ************************************************************************************************
|
||||
* 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/diff-attributes")
|
||||
public class IDORDiffAttributes extends AssignmentEndpoint {
|
||||
|
||||
@ -23,7 +50,7 @@ public class IDORDiffAttributes extends AssignmentEndpoint {
|
||||
attributes = attributes.trim();
|
||||
String[] diffAttribs = attributes.split(",");
|
||||
if (diffAttribs.length < 2) {
|
||||
return AttackResult.failed("You did not list two attributes string delimited");
|
||||
return AttackResult.failed("You did not list two attributes, comma delimited");
|
||||
}
|
||||
if (diffAttribs[0].toLowerCase().trim().equals("userid") && diffAttribs[1].toLowerCase().trim().equals("role") ||
|
||||
diffAttribs[1].toLowerCase().trim().equals("userid") && diffAttribs[0].toLowerCase().trim().equals("role")) {
|
||||
|
@ -43,26 +43,42 @@ import java.util.Map;
|
||||
*/
|
||||
|
||||
@Path("IDOR/profile/{userId}")
|
||||
public class IDOREditOwnProfiile extends AssignmentEndpoint {
|
||||
public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
||||
|
||||
@Autowired UserSessionData userSessionData;
|
||||
|
||||
@RequestMapping(method = RequestMethod.PUT, consumes = "application/json")
|
||||
public @ResponseBody
|
||||
AttackResult completed(@PathVariable("userId") String userId, @RequestParam UserProfile userSubmittedProfile, HttpServletRequest request) {
|
||||
AttackResult completed(@PathVariable("userId") String userId, @RequestParam UserProfile userSubmittedProfile) {
|
||||
|
||||
String authUserId = (String)userSessionData.getValue("idor-authenticated-user-id");
|
||||
UserProfile currentUserProfile = new UserProfile(authUserId);
|
||||
// this is where it starts ... accepting the user submitted ID and assuming it will be the same as the logged in userId and not checking for proper authorization
|
||||
// Certain roles can sometimes edit others' profiles, but we shouldn't just assume that and let everyone, right?
|
||||
// Except that this is a vulnerable app ... so we will
|
||||
UserProfile currentUserProfile = new UserProfile(userId);
|
||||
if (userSubmittedProfile.getUserId() != null && !userSubmittedProfile.getUserId().equals(authUserId)) {
|
||||
return AttackResult.failed("Don't worry, we'll get to modifying someone else's profile, just modify your own for now.");
|
||||
} else if (userSubmittedProfile.getUserId().equals(authUserId)) {
|
||||
// this is commonly how vulnerable code will act ... updating w/out an authorization check
|
||||
// let's get this started ...
|
||||
currentUserProfile.setColor(userSubmittedProfile.getColor());
|
||||
currentUserProfile.setRole(userSubmittedProfile.getRole());
|
||||
// we will persist in the session object for now
|
||||
userSessionData.setValue("idor-updated-own-profile",currentUserProfile);
|
||||
// we will persist in the session object for now in case we want to refer back or use it later
|
||||
userSessionData.setValue("idor-updated-other-profile",currentUserProfile);
|
||||
if (currentUserProfile.getRole() <= 1 && currentUserProfile.getColor().toLowerCase().equals("red")) {
|
||||
return trackProgress(AttackResult.success("Well done, you have modified someone else's profile (as displayed below)",currentUserProfile.profileToMap().toString()));
|
||||
}
|
||||
|
||||
if (currentUserProfile.getRole() > 1 && currentUserProfile.getColor().toLowerCase().equals("red")) {
|
||||
return trackProgress(AttackResult.success("Close ... you've got the technique. Now try for a lower role number)",currentUserProfile.profileToMap().toString()));
|
||||
}
|
||||
|
||||
if (currentUserProfile.getRole() <= 1 && !currentUserProfile.getColor().toLowerCase().equals("red")) {
|
||||
return trackProgress(AttackResult.success("Close ... you've got the technique. Now change the color in their profile to red.)",currentUserProfile.profileToMap().toString()));
|
||||
}
|
||||
|
||||
// else
|
||||
return trackProgress(AttackResult.success("Try again. Use the hints if you need to.",currentUserProfile.profileToMap().toString()));
|
||||
|
||||
} else if (userSubmittedProfile.getUserId().equals(authUserId)) {
|
||||
return AttackResult.failed("Modifying your own profile is good, but we want to do this to Buffalo Bill's profile.");
|
||||
}
|
||||
|
||||
if (currentUserProfile.getColor().equals("black") && currentUserProfile.getRole() <= 1 ) {
|
@ -0,0 +1,82 @@
|
||||
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.PathVariable;
|
||||
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 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/profile/{userId}")
|
||||
public class IDORViewOtherProfile extends AssignmentEndpoint{
|
||||
|
||||
@Autowired
|
||||
UserSessionData userSessionData;
|
||||
|
||||
@RequestMapping(produces = {"application/json"}, method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public AttackResult completed(@PathVariable("userId") String userId, HttpServletResponse resp) {
|
||||
Map<String,Object> details = new HashMap<>();
|
||||
|
||||
if (userSessionData.getValue("idor-authenticated-as").equals("tom")) {
|
||||
//going to use session auth to view this one
|
||||
String authUserId = (String)userSessionData.getValue("idor-authenticated-user-id");
|
||||
if(userId != null && !userId.equals(authUserId)) {
|
||||
//on the right track
|
||||
UserProfile requestedProfile = new UserProfile(userId);
|
||||
// secure code would ensure there was a horizontal access control check prior to dishing up the requested profile
|
||||
if (requestedProfile.getUserId().equals("2342388")){
|
||||
return trackProgress(AttackResult.success("Well done, you found someone else's profile",requestedProfile.profileToMap().toString()));
|
||||
} else {
|
||||
return trackProgress((AttackResult.failed("You're on the right path, try a different id")));
|
||||
}
|
||||
} else {
|
||||
return trackProgress((AttackResult.failed("Try again. You need to use the same method/URL you used to access your own profile via direct object reference.")));
|
||||
}
|
||||
}
|
||||
return trackProgress((AttackResult.failed("Try again. ")));
|
||||
}
|
||||
|
||||
}
|
@ -20,8 +20,35 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Created by jason on 1/5/17.
|
||||
* ************************************************************************************************
|
||||
* 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 IDORViewOwnProfile extends Endpoint{
|
||||
|
||||
@Autowired
|
||||
|
@ -17,8 +17,35 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by jason on 1/5/17.
|
||||
* ************************************************************************************************
|
||||
* 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/profile/alt-path")
|
||||
public class IDORViewOwnProfileAltUrl extends AssignmentEndpoint{
|
||||
|
||||
@ -37,12 +64,7 @@ public class IDORViewOwnProfileAltUrl extends AssignmentEndpoint{
|
||||
String[] urlParts = url.split("/");
|
||||
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("role", userProfile.getRole());
|
||||
return trackProgress(AttackResult.success("congratultions, you have used the alternate Url/route to view your own profile.",details.toString()));
|
||||
return trackProgress(AttackResult.success("congratultions, you have used the alternate Url/route to view your own profile.",userProfile.profileToMap().toString()));
|
||||
} else {
|
||||
return trackProgress(AttackResult.failed("please try again. The alternoute route is very similar to the previous way you viewed your profile. Only one difference really"));
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
package org.owasp.webgoat.plugin;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by jason on 1/5/17.
|
||||
*/
|
||||
@ -10,12 +13,10 @@ public class UserProfile {
|
||||
private String size;
|
||||
private boolean isAdmin;
|
||||
private int role;
|
||||
// anyting else?
|
||||
|
||||
public UserProfile() {}
|
||||
|
||||
public UserProfile(String id) {
|
||||
this.userId = id;
|
||||
setProfileFromId(id);
|
||||
}
|
||||
|
||||
@ -23,21 +24,35 @@ public class UserProfile {
|
||||
private void setProfileFromId(String id) {
|
||||
// emulate look up from database
|
||||
if (id.equals("2342384")) {
|
||||
this.userId = id;
|
||||
this.color = "yellow";
|
||||
this.name = "Tom Cat";
|
||||
this.size = "small";
|
||||
this.isAdmin = false;
|
||||
this.role = 3;
|
||||
} else if (id.equals("2342388")) {
|
||||
this.userId = id;
|
||||
this.color = "brown";
|
||||
this.name = "Buffalo Bill";
|
||||
this.size = "large";
|
||||
this.isAdmin = false;
|
||||
this.role = 3;
|
||||
} else {
|
||||
//not found
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Map <String,Object> profileToMap () {
|
||||
Map<String,Object> profileMap = new HashMap<>();
|
||||
profileMap.put("userId", this.userId);
|
||||
profileMap.put("name", this.name);
|
||||
profileMap.put("color", this.color);
|
||||
profileMap.put("size", this.size);
|
||||
profileMap.put("role", this.role);
|
||||
return profileMap;
|
||||
}
|
||||
|
||||
public String toHTMLString() {
|
||||
String htmlBreak = "<br/>";
|
||||
return "userId" + this.userId + htmlBreak +
|
||||
|
@ -2,7 +2,6 @@ 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;
|
||||
@ -24,7 +23,7 @@ import java.util.Map;
|
||||
*/
|
||||
|
||||
@Path("/IDOR/viewprofile/{id}")
|
||||
public class ViewOtherUserProfileEndpoint extends AssignmentEndpoint {
|
||||
public class ViewOtherUserProfile extends AssignmentEndpoint {
|
||||
|
||||
private String color;
|
||||
private String size;
|
||||
@ -49,7 +48,8 @@ public class ViewOtherUserProfileEndpoint extends AssignmentEndpoint {
|
||||
System.out.println("**** authenticated as " + userSessionData.getValue("idor-authenticated-as"));
|
||||
//logged in
|
||||
String authUserId = (String)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
|
||||
//secure code would check to make sure authUserId matches userId or some similar access control
|
||||
// ... and in this endpoint, we won't bother with that
|
||||
UserProfile userProfile = new UserProfile(userId);
|
||||
return trackProgress(AttackResult.failed("still working"));
|
||||
}
|
@ -131,7 +131,7 @@
|
||||
<!-- 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_eidtOwn.adoc"></div>
|
||||
<div class="adoc-content" th:replace="doc:IDOR_viewOtherProfile.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>
|
||||
@ -140,13 +140,13 @@
|
||||
<!-- 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"
|
||||
<form class="attack-form" accept-charset="UNKNOWN" id="view-other"
|
||||
method="GET" name="view-other-profile"
|
||||
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();" />
|
||||
<input name="View Profile" value="View Profile" type="submit" />
|
||||
|
||||
</form>
|
||||
</div>
|
||||
@ -155,6 +155,32 @@
|
||||
<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="adoc-content" th:replace="doc:IDOR_editOtherProfile.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" id="edit-other"
|
||||
method="GET" name="edit-other-profile"
|
||||
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="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">
|
||||
|
@ -0,0 +1,8 @@
|
||||
==== Edit Another Profile
|
||||
|
||||
Older apps may follow different patterns, but RESTful apps (which is what's going on here) often just change methods (and include a body or not)
|
||||
to perform different functions.
|
||||
|
||||
Use that knowledge to take the same base request, change its method, path and body (payload) to modify another user's (Buffalo Bill's) profile.
|
||||
Change the role to something lower (since higher privilege roles and users are ususally lower numbers). Also change modify the
|
||||
user's color to 'red'.
|
@ -19,7 +19,8 @@ POST, PUT, DELETE or other methods are also potentially succeptible and mainly o
|
||||
|
||||
== *Insecure* Direct Object References
|
||||
|
||||
These are considered insecure when the reference is not properly handled and allows for authorization bypasses.
|
||||
These are considered insecure when the reference is not properly handled and allows for authorization bypasses or disclose private data that could be used to
|
||||
perform opreations or access data that the user should not be able to perform or access.
|
||||
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`
|
||||
|
@ -0,0 +1,7 @@
|
||||
=== Playing with the Patterns
|
||||
|
||||
==== View Another Profile
|
||||
|
||||
View someone else's profile by using the alternate path you already used to view your own profile. Use the 'View Profile' button
|
||||
and intercept/modify the request to view another profile. Alternatively, you may also just be able to use a manual GET request with
|
||||
your browser.
|
Loading…
x
Reference in New Issue
Block a user