missing function level ac working again ... after VM implosion

This commit is contained in:
Jason White
2017-08-08 17:15:20 -06:00
parent 8df1d53471
commit b41751a55c
11 changed files with 269 additions and 75 deletions

View File

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

View File

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

View File

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

View File

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