missing function level ac working again ... after VM implosion
This commit is contained in:
parent
8df1d53471
commit
b41751a55c
@ -1,43 +0,0 @@
|
||||
package org.owasp.webgoat.controller;
|
||||
|
||||
import com.sun.corba.se.spi.activation.EndPointInfo;
|
||||
import org.owasp.webgoat.assignments.*;
|
||||
import org.owasp.webgoat.session.UserSessionData;
|
||||
import org.owasp.webgoat.users.UserService;
|
||||
import org.owasp.webgoat.users.WebGoatUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by jason on 1/5/17.
|
||||
*/
|
||||
|
||||
@Controller
|
||||
public class ListUsers {
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@RequestMapping(path = {"list_users", "/"}, method = {RequestMethod.GET,RequestMethod.POST})
|
||||
public ModelAndView listUsers(HttpServletRequest request) {
|
||||
|
||||
ModelAndView model = new ModelAndView();
|
||||
model.setViewName("list_users");
|
||||
List<WebGoatUser> allUsers = userService.getAllUsers();
|
||||
model.addObject("numUsers",allUsers.size());
|
||||
model.addObject("allUsers",allUsers);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
}
|
@ -43,6 +43,7 @@ public class WebGoatUser implements UserDetails {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
|
||||
public void createUser() {
|
||||
this.user = new User(username, password, getAuthorities());
|
||||
}
|
||||
@ -51,6 +52,18 @@ public class WebGoatUser implements UserDetails {
|
||||
return Collections.singleton(new SimpleGrantedAuthority(getRole()));
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return this.role;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return this.user.isAccountNonExpired();
|
||||
@ -70,6 +83,8 @@ public class WebGoatUser implements UserDetails {
|
||||
public boolean isEnabled() {
|
||||
return this.user.isEnabled();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -123,8 +123,15 @@
|
||||
<section class="main-content-wrapper">
|
||||
<section id="main-content"> <!--ng-controller="goatLesson"-->
|
||||
<div id="lesson-page" class="pages">
|
||||
TEST ... <span th:text="${numUsers}"> Users in WebGoat</span>
|
||||
<div sec:authorize="hasAuthority('WEBGOAT_ADMIN')">Admin sees this ...
|
||||
<span th:text="${numUsers}"> Users in WebGoat</span>
|
||||
<!-- iterate over users below -->su
|
||||
<div sec:authorize="hasAuthority('WEBGOAT_ADMIN')">
|
||||
<h3>WebGoat Users</h3>
|
||||
<div th:each="user : ${allUsers}">
|
||||
<span th:text="${user.username}" />
|
||||
<ul>Hash: <span th:text="${user.userHash}" /></ul>
|
||||
<ul>Admin: <span th:text="${user.admin}" /></ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="lesson-helps-wrapper" class="panel">
|
||||
|
@ -0,0 +1,89 @@
|
||||
package org.owasp.webgoat.plugin;
|
||||
|
||||
|
||||
import lombok.Getter;
|
||||
import org.owasp.webgoat.users.WebGoatUser;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* ************************************************************************************************
|
||||
* 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>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
public class DisplayUser {
|
||||
//intended to provide a display version of WebGoatUser for admins to view user attributes
|
||||
|
||||
|
||||
private String username;
|
||||
private boolean admin;
|
||||
private String userHash;
|
||||
|
||||
public DisplayUser(WebGoatUser user) {
|
||||
this.username = user.getUsername();
|
||||
this.admin = false;
|
||||
|
||||
for (GrantedAuthority authority : user.getAuthorities()) {
|
||||
this.admin = (authority.getAuthority().contains("WEBGOAT_ADMIN")) ? true : false;
|
||||
}
|
||||
|
||||
// create userHash on the fly
|
||||
//TODO: persist userHash
|
||||
try {
|
||||
this.userHash = genUserHash(user.getUsername(), user.getPassword());
|
||||
} catch (Exception ex) {
|
||||
//TODO: implement better fallback operation
|
||||
this.userHash = "Error generating user hash";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected String genUserHash (String username, String password) throws Exception {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
// salting is good, but static & too predictable ... short too for a salt
|
||||
String salted = password + "DeliberatelyInsecure1234" + username;
|
||||
//md.update(salted.getBytes("UTF-8")); // Change this to "UTF-16" if needed
|
||||
byte[] hash = md.digest(salted.getBytes("UTF-8"));
|
||||
String encoded = Base64.getEncoder().encodeToString(hash);
|
||||
return encoded;
|
||||
}
|
||||
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public boolean isAdmin() {
|
||||
return admin;
|
||||
}
|
||||
|
||||
public String getUserHash() {
|
||||
return userHash;
|
||||
}
|
||||
|
||||
}
|
@ -38,14 +38,14 @@ public class HiddenMenuItems extends AssignmentEndpoint {
|
||||
AttackResult completed(String hiddenMenu1, String hiddenMenu2, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
|
||||
//overly simple example for success. See other existing lesssons for ways to detect 'success' or 'failure'
|
||||
if (hiddenMenu1.equals("List Users") && hiddenMenu2.equals("Add User")) {
|
||||
if (hiddenMenu1.equals("Users") && hiddenMenu2.equals("Config")) {
|
||||
return trackProgress(success()
|
||||
.output("")
|
||||
.feedback("access-control.hidden-menus.success")
|
||||
.build());
|
||||
}
|
||||
|
||||
if (hiddenMenu1.equals("Add User") && hiddenMenu2.equals("List Users")) {
|
||||
if (hiddenMenu1.equals("Config") && hiddenMenu2.equals("Users")) {
|
||||
return trackProgress(success()
|
||||
.output("")
|
||||
.feedback("access-control.hidden-menus.close")
|
||||
|
@ -0,0 +1,78 @@
|
||||
package org.owasp.webgoat.plugin;
|
||||
|
||||
import com.sun.corba.se.spi.activation.EndPointInfo;
|
||||
import org.owasp.webgoat.assignments.*;
|
||||
import org.owasp.webgoat.session.UserSessionData;
|
||||
import org.owasp.webgoat.users.UserService;
|
||||
import org.owasp.webgoat.users.WebGoatUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by jason on 1/5/17.
|
||||
*/
|
||||
|
||||
@Controller
|
||||
public class MissingFunctionACUsers {
|
||||
|
||||
|
||||
// this will actually put controllers on the /WebGoat/* path ... the jsp for list_users restricts what can be seen, but the add_user is not controlled carefully
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@RequestMapping(path = {"users", "/"}, method = RequestMethod.GET)
|
||||
public ModelAndView listUsers(HttpServletRequest request) {
|
||||
|
||||
ModelAndView model = new ModelAndView();
|
||||
model.setViewName("list_users");
|
||||
List<WebGoatUser> allUsers = userService.getAllUsers();
|
||||
model.addObject("numUsers",allUsers.size());
|
||||
//add display user objects in place of direct users
|
||||
List<DisplayUser> displayUsers = new ArrayList<>();
|
||||
for (WebGoatUser user : allUsers) {
|
||||
displayUsers.add(new DisplayUser(user));
|
||||
}
|
||||
model.addObject("allUsers",displayUsers);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
@RequestMapping(path = {"users", "/"}, method = RequestMethod.GET,consumes = "application/json")
|
||||
@ResponseBody
|
||||
public List<DisplayUser> usersService(HttpServletRequest request) {
|
||||
|
||||
List<WebGoatUser> allUsers = userService.getAllUsers();
|
||||
List<DisplayUser> displayUsers = new ArrayList<>();
|
||||
for (WebGoatUser user : allUsers) {
|
||||
displayUsers.add(new DisplayUser(user));
|
||||
}
|
||||
return displayUsers;
|
||||
}
|
||||
|
||||
@RequestMapping(path = {"users","/"}, method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
|
||||
@ResponseBody
|
||||
//@PreAuthorize()
|
||||
public WebGoatUser addUser(@RequestBody WebGoatUser newUser) {
|
||||
try {
|
||||
userService.addUser(newUser.getUsername(),newUser.getPassword(),newUser.getRole());
|
||||
return userService.loadUserByUsername(newUser.getUsername());
|
||||
} catch (Exception ex) {
|
||||
System.out.println("Error creating new User" + ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
//TODO: implement error handling ...
|
||||
} finally {
|
||||
// no streams or other resources opened ... nothing to do, right?
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//@RequestMapping(path = {"user/{username}","/"}, method = RequestMethod.DELETE, consumes = "application/json", produces = "application/json")
|
||||
//TODO implement delete method with id param and authorization
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package org.owasp.webgoat.plugin;
|
||||
|
||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
||||
import org.owasp.webgoat.assignments.AttackResult;
|
||||
import org.owasp.webgoat.users.UserService;
|
||||
import org.owasp.webgoat.users.WebGoatUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
@AssignmentPath("/access-control/user-hash")
|
||||
@AssignmentHints({"access-control.hash.hint1","access-control.hash.hint2","access-control.hash.hint3",
|
||||
"access-control.hash.hint4","access-control.hash.hint5","access-control.hash.hint6","access-control.hash.hint7",
|
||||
"access-control.hash.hint8","access-control.hash.hint9"})
|
||||
public class MissingFunctionACYourHash extends AssignmentEndpoint {
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@PostMapping(produces = {"application/json"})
|
||||
public @ResponseBody
|
||||
AttackResult completed(String userHash) {
|
||||
String currentUser = getWebSession().getUserName();
|
||||
WebGoatUser user = userService.loadUserByUsername(currentUser);
|
||||
DisplayUser displayUser = new DisplayUser(user);
|
||||
if (userHash.equals(displayUser.getUserHash())) {
|
||||
return trackProgress(success().feedback("access-control.hash.success").build());
|
||||
} else {
|
||||
return trackProgress(success().feedback("access-control.hash.close").build());
|
||||
}
|
||||
}
|
||||
}
|
@ -30,8 +30,8 @@
|
||||
<h3 class="hidden-menu-item menu-header">Admin</h3>
|
||||
<div class="menu-section hidden-menu-item">
|
||||
<ul>
|
||||
<li>List Users</li>
|
||||
<li>Add User</li>
|
||||
<li><a href="/users">Users</a></li>
|
||||
<li><a href="/config">Config</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@ -57,25 +57,26 @@
|
||||
|
||||
</div>
|
||||
|
||||
<!--<div class="lesson-page-wrapper">-->
|
||||
<!--<div class="adoc-content" th:replace="doc:missing-function-ac-03-list-users.adoc"></div>-->
|
||||
<div class="lesson-page-wrapper">
|
||||
|
||||
<!--<div class="attack-container">-->
|
||||
<!--<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>-->
|
||||
<!--<form class="attack-form" accept-charset="UNKNOWN"-->
|
||||
<!--method="POST" name="form"-->
|
||||
<!--action="/WebGoat/access-control/user-info">-->
|
||||
<div class="adoc-content" th:replace="doc:missing-function-ac-03-users.adoc"></div>
|
||||
|
||||
<!--<p>CC Number: <input name="ccNum" value="" type="TEXT" /></p>-->
|
||||
<!--<br/>-->
|
||||
<!--<input name="submit" value="Submit" type="SUBMIT"/>-->
|
||||
<div class="attack-container">
|
||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||
<form class="attack-form" accept-charset="UNKNOWN"
|
||||
method="POST" name="form"
|
||||
action="/WebGoat/access-control/user-hash">
|
||||
|
||||
<!--</form>-->
|
||||
<p>Your Hash: <input name="userHash" value="" type="TEXT" /></p>
|
||||
<br/>
|
||||
<input name="submit" value="Submit" type="SUBMIT"/>
|
||||
|
||||
<!--<div class="attack-feedback"></div>-->
|
||||
<!--<div class="attack-output"></div>-->
|
||||
<!--</div>-->
|
||||
</form>
|
||||
|
||||
<!--</div>-->
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</html>
|
||||
|
@ -7,3 +7,16 @@ access-control.hidden-menus.failure=Please try again.
|
||||
access-control.hidden-menus.hint1=You can inspect the DOM or review the source in the proxy request/response cycle.
|
||||
access-control.hidden-menus.hint2=Look for indications of something that would not be available to a typical user
|
||||
access-control.hidden-menus.hint3=Look for something a super-user or administator might have available to them
|
||||
|
||||
access-control.hash.success=Congrats! You really succeeded when you added the user.
|
||||
access-control.hash.close=Keep trying, this one may take several attempts & steps to achieve. See the hints for help.
|
||||
|
||||
access-control.hash.hint1=If you haven't found the hidden menus from the earlier exercise, go do that now.
|
||||
access-control.hash.hint2=When you look at the users page, there is a hint that more info is viewable by a given role of user.
|
||||
access-control.hash.hint3=Have you tried tampering the GET request? Can you find supported or unsupported methods? Can you trigger 500 errors?
|
||||
access-control.hash.hint4=There are actually two ways to solve this one. The first involves just changing a request header.
|
||||
access-control.hash.hint5=If the request to view users, were a 'service' or 'RESTful' endpoint, what would be different about it?
|
||||
access-control.hash.hint6=If you're still looking for hints ... try changing the Content-type header in the GET request.
|
||||
access-control.hash.hint7=The harder way involves changing the Content-type AND the method ... As well as a proper payload for the request. Look at how registration works first and extrapolate out from there.
|
||||
access-control.hash.hint8=See if you can add a user with a webgoat admin role, and if more is visible once you log in as that user.
|
||||
access-control.hash.hint9=If you create a new user with the admin role ... The role should include 'WEBGOAT' and 'ADMIN' in the role name. You'll have to do some guessing beyond that.
|
@ -1,10 +0,0 @@
|
||||
== Just Try It
|
||||
|
||||
As the previous page noted, sometimes apps rely on client controls. to control access (obscurity). If you can find items that don't have visible links, just try them, see what happens. Yes, it
|
||||
can be that simple!
|
||||
|
||||
=== Gathering User Info
|
||||
|
||||
Often times, data dumps from vulnerabilities such as sql injection, but they can also come from poor or lacking access control. Use the info. you already gathered to pull the list of users and
|
||||
then provide the CC# for Chaos Monkey.
|
||||
|
@ -0,0 +1,10 @@
|
||||
== Just Try It
|
||||
|
||||
As the previous page noted, sometimes apps rely on client controls. to control access (obscurity). If you can find items that don't have visible links, just try them, see what happens. Yes, it
|
||||
can be that simple!
|
||||
|
||||
=== Gathering User Info
|
||||
|
||||
Often times, data dumps from vulnerabilities such as sql injection, but they can also come from poor or lacking access control.
|
||||
|
||||
It will likely take multiple steps and multiple attempts to get this one. Pay attention to the comments, leaked info. and you'll need to guess some. You may need to use another browser/account along the way. Start with the info. you already gathered (hidden menu items) to see if you can pull the list of users and then provide the 'Hash' for your own user account.
|
Loading…
x
Reference in New Issue
Block a user