Refactoring (#1201)

* Some initial refactoring

* Make it one application

* Got it working

* Fix problem on Windows

* Move WebWolf

* Move first lesson

* Moved all lessons

* Fix pom.xml

* Fix tests

* Add option to initialize a lesson

This way we can create content for each user inside a lesson. The initialize method will be called when a new user is created or when a lesson reset happens

* Clean up pom.xml files

* Remove fetching labels based on language.

We only support English at the moment, all the lesson explanations are written in English which makes it very difficult to translate. If we only had labels it would make sense to support multiple languages

* Fix SonarLint issues

* And move it all to the main project

* Fix for documentation paths

* Fix pom warnings

* Remove PMD as it does not work

* Update release notes about refactoring

Update release notes about refactoring

Update release notes about refactoring

* Fix lesson template

* Update release notes

* Keep it in the same repo in Dockerhub

* Update documentation to show how the connection is obtained.

Resolves: #1180

* Rename all integration tests

* Remove command from Dockerfile

* Simplify GitHub actions

Currently, we use a separate actions for pull-requests and branch build.
This is now consolidated in one action.
The PR action triggers always, it now only trigger when the PR is
opened and not in draft.
Running all platforms on a branch build is a bit too much, it is better
 to only run all platforms when someone opens a PR.

* Remove duplicate entry from release notes

* Add explicit registry for base image

* Lesson scanner not working when fat jar

When running the fat jar we have to take into account we
are reading from the jar file and not the filesystem. In
this case you cannot use `getFile` for example.

* added info in README and fixed release docker

* changed base image and added ignore file

Co-authored-by: Zubcevic.com <rene@zubcevic.com>
This commit is contained in:
Nanne Baars
2022-04-09 14:56:12 +02:00
committed by GitHub
parent f3d8206a07
commit 711649924b
1130 changed files with 3540 additions and 7643 deletions

View File

@@ -0,0 +1,87 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.auth_bypass;
import java.util.HashMap;
import java.util.Map;
/**
* Created by appsec on 7/18/17.
*/
public class AccountVerificationHelper {
//simulating database storage of verification credentials
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");
}
private static final Map<Integer, Map> secQuestionStore = new HashMap<>();
static {
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) {
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")))) {
likely = true;
} else {
likely = false;
}
return likely;
}
//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) {
//short circuit if no questions are submitted
if (submittedQuestions.entrySet().size() != secQuestionStore.get(verifyUserId).size()) {
return false;
}
if (submittedQuestions.containsKey("secQuestion0") && !submittedQuestions.get("secQuestion0").equals(secQuestionStore.get(verifyUserId).get("secQuestion0"))) {
return false;
}
if (submittedQuestions.containsKey("secQuestion1") && !submittedQuestions.get("secQuestion1").equals(secQuestionStore.get(verifyUserId).get("secQuestion1"))) {
return false;
}
// else
return true;
}
}

View File

@@ -0,0 +1,41 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.auth_bypass;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
@Component
public class AuthBypass extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.AUTHENTICATION;
}
@Override
public String getTitle() {
return "auth-bypass.title";
}
}

View File

@@ -0,0 +1,95 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.auth_bypass;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.session.UserSessionData;
import org.owasp.webgoat.container.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
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;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by jason on 1/5/17.
*/
@RestController
@AssignmentHints({"auth-bypass.hints.verify.1", "auth-bypass.hints.verify.2", "auth-bypass.hints.verify.3", "auth-bypass.hints.verify.4"})
public class VerifyAccount extends AssignmentEndpoint {
@Autowired
private WebSession webSession;
@Autowired
UserSessionData userSessionData;
@PostMapping(path = "/auth-bypass/verify-account", produces = {"application/json"})
@ResponseBody
public AttackResult completed(@RequestParam String userId, @RequestParam String verifyMethod, HttpServletRequest req) throws ServletException, IOException {
AccountVerificationHelper verificationHelper = new AccountVerificationHelper();
Map<String, String> submittedAnswers = parseSecQuestions(req);
if (verificationHelper.didUserLikelylCheat((HashMap) submittedAnswers)) {
return failed(this)
.feedback("verify-account.cheated")
.output("Yes, you guessed correctly, but see the feedback message")
.build();
}
// else
if (verificationHelper.verifyAccount(Integer.valueOf(userId), (HashMap) submittedAnswers)) {
userSessionData.setValue("account-verified-id", userId);
return success(this)
.feedback("verify-account.success")
.build();
} else {
return failed(this)
.feedback("verify-account.failed")
.build();
}
}
private HashMap<String, String> parseSecQuestions(HttpServletRequest req) {
Map<String, String> userAnswers = new HashMap<>();
List<String> paramNames = Collections.list(req.getParameterNames());
for (String paramName : paramNames) {
//String paramName = req.getParameterNames().nextElement();
if (paramName.contains("secQuestion")) {
userAnswers.put(paramName, req.getParameter(paramName));
}
}
return (HashMap) userAnswers;
}
}

View File

@@ -0,0 +1,40 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.bypass_restrictions;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
@Component
public class BypassRestrictions extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.CLIENT_SIDE;
}
@Override
public String getTitle() {
return "bypass-restrictions.title";
}
}

View File

@@ -0,0 +1,55 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.bypass_restrictions;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
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;
@RestController
public class BypassRestrictionsFieldRestrictions extends AssignmentEndpoint {
@PostMapping("/BypassRestrictions/FieldRestrictions")
@ResponseBody
public AttackResult completed(@RequestParam String select, @RequestParam String radio, @RequestParam String checkbox, @RequestParam String shortInput, @RequestParam String readOnlyInput) {
if (select.equals("option1") || select.equals("option2")) {
return failed(this).build();
}
if (radio.equals("option1") || radio.equals("option2")) {
return failed(this).build();
}
if (checkbox.equals("on") || checkbox.equals("off")) {
return failed(this).build();
}
if (shortInput.length() <= 5) {
return failed(this).build();
}
if ("change".equals(readOnlyInput)) {
return failed(this).build();
}
return success(this).build();
}
}

View File

@@ -0,0 +1,71 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.bypass_restrictions;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
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;
@RestController
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) {
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 failed(this).build();
}
if (field1.matches(regex1)) {
return failed(this).build();
}
if (field2.matches(regex2)) {
return failed(this).build();
}
if (field3.matches(regex3)) {
return failed(this).build();
}
if (field4.matches(regex4)) {
return failed(this).build();
}
if (field5.matches(regex5)) {
return failed(this).build();
}
if (field6.matches(regex6)) {
return failed(this).build();
}
if (field7.matches(regex7)) {
return failed(this).build();
}
return success(this).build();
}
}

View File

@@ -0,0 +1,21 @@
package org.owasp.webgoat.lessons.challenges;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
/**
* @author nbaars
* @since 3/21/17.
*/
public class ChallengeIntro extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.CHALLENGE;
}
@Override
public String getTitle() {
return "challenge0.title";
}
}

View File

@@ -0,0 +1,44 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.challenges;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author nbaars
* @since 8/20/17.
*/
@Builder
@Data
public class Email implements Serializable {
private LocalDateTime time;
private String contents;
private String sender;
private String title;
private String recipient;
}

View File

@@ -0,0 +1,88 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.challenges;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.UserTracker;
import org.owasp.webgoat.container.users.UserTrackerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import 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;
/**
* @author nbaars
* @since 3/23/17.
*/
@RestController
public class Flag extends AssignmentEndpoint {
public static final Map<Integer, String> FLAGS = new HashMap<>();
@Autowired
private UserTrackerRepository userTrackerRepository;
@Autowired
private WebSession webSession;
@AllArgsConstructor
private class FlagPosted {
@Getter
private boolean lessonCompleted;
}
@PostConstruct
public void initFlags() {
IntStream.range(1, 10).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString()));
}
@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());
String currentChallenge = webSession.getCurrentLesson().getName();
int challengeNumber = Integer.valueOf(currentChallenge.substring(currentChallenge.length() - 1, currentChallenge.length()));
String expectedFlag = FLAGS.get(challengeNumber);
final AttackResult attackResult;
if (expectedFlag.equals(flag)) {
userTracker.assignmentSolved(webSession.getCurrentLesson(), "Assignment" + challengeNumber);
attackResult = success(this).feedback("challenge.flag.correct").build();
} else {
userTracker.assignmentFailed(webSession.getCurrentLesson());
attackResult = failed(this).feedback("challenge.flag.incorrect").build();
}
userTrackerRepository.save(userTracker);
return attackResult;
}
}

View File

@@ -0,0 +1,37 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.challenges;
/**
* Interface with constants so we can easily change the flags
*
* @author nbaars
* @since 3/23/17.
*/
public interface SolutionConstants {
//TODO should be random generated when starting the server
String PASSWORD = "!!webgoat_admin_1234!!";
String PASSWORD_TOM = "thisisasecretfortomonly";
String ADMIN_PASSWORD_LINK = "375afe1104f4a487a73823c50a9292a2";
}

View File

@@ -0,0 +1,64 @@
package org.owasp.webgoat.lessons.challenges.challenge1;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.lessons.challenges.Flag;
import org.springframework.util.StringUtils;
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;
import javax.servlet.http.HttpServletRequest;
import static org.owasp.webgoat.lessons.challenges.SolutionConstants.PASSWORD;
/**
* ************************************************************************************************
* 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 - 2014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author WebGoat
* @version $Id: $Id
* @since August 11, 2016
*/
@RestController
public class Assignment1 extends AssignmentEndpoint {
@PostMapping("/challenge/1")
@ResponseBody
public AttackResult completed(@RequestParam String username, @RequestParam String password, HttpServletRequest request) {
boolean ipAddressKnown = true;
boolean passwordCorrect = "admin".equals(username) && PASSWORD.replace("1234", String.format("%04d",ImageServlet.PINCODE)).equals(password);
if (passwordCorrect && ipAddressKnown) {
return success(this).feedback("challenge.solved").feedbackArgs(Flag.FLAGS.get(1)).build();
} else if (passwordCorrect) {
return failed(this).feedback("ip.address.unknown").build();
}
return failed(this).build();
}
public static boolean containsHeader(HttpServletRequest request) {
return StringUtils.hasText(request.getHeader("X-Forwarded-For"));
}
}

View File

@@ -0,0 +1,23 @@
package org.owasp.webgoat.lessons.challenges.challenge1;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* @author nbaars
* @since 3/21/17.
*/
@Component
public class Challenge1 extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.CHALLENGE;
}
@Override
public String getTitle() {
return "challenge1.title";
}
}

View File

@@ -0,0 +1,36 @@
package org.owasp.webgoat.lessons.challenges.challenge1;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServlet;
import java.io.IOException;
import java.security.SecureRandom;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
@RestController
public class ImageServlet extends HttpServlet {
private static final long serialVersionUID = 9132775506936676850L;
static final public int PINCODE = new SecureRandom().nextInt(10000);
@RequestMapping(method = {GET, POST}, value = "/challenge/logo", produces = MediaType.IMAGE_PNG_VALUE)
@ResponseBody
public byte[] logo() throws IOException {
byte[] in = new ClassPathResource("lessons/challenges/images/webgoat2.png").getInputStream().readAllBytes();
String pincode = String.format("%04d", PINCODE);
in[81216]=(byte) pincode.charAt(0);
in[81217]=(byte) pincode.charAt(1);
in[81218]=(byte) pincode.charAt(2);
in[81219]=(byte) pincode.charAt(3);
return in;
}
}

View File

@@ -0,0 +1,70 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.challenges.challenge5;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.LessonDataSource;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.lessons.challenges.Flag;
import org.springframework.util.StringUtils;
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;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@RestController
@Slf4j
public class Assignment5 extends AssignmentEndpoint {
private final LessonDataSource dataSource;
public Assignment5(LessonDataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/challenge/5")
@ResponseBody
public AttackResult login(@RequestParam String username_login, @RequestParam String password_login) throws Exception {
if (!StringUtils.hasText(username_login) || !StringUtils.hasText(password_login)) {
return failed(this).feedback("required4").build();
}
if (!"Larry".equals(username_login)) {
return failed(this).feedback("user.not.larry").feedbackArgs(username_login).build();
}
try (var connection = dataSource.getConnection()) {
PreparedStatement statement = connection.prepareStatement("select password from challenge_users where userid = '" + username_login + "' and password = '" + password_login + "'");
ResultSet resultSet = statement.executeQuery();
if (resultSet.next()) {
return success(this).feedback("challenge.solved").feedbackArgs(Flag.FLAGS.get(5)).build();
} else {
return failed(this).feedback("challenge.close").build();
}
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.challenges.challenge5;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* @author nbaars
* @since 3/21/17.
*/
@Component
public class Challenge5 extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.CHALLENGE;
}
@Override
public String getTitle() {
return "challenge5.title";
}
}

View File

@@ -0,0 +1,86 @@
package org.owasp.webgoat.lessons.challenges.challenge7;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.lessons.challenges.Email;
import org.owasp.webgoat.lessons.challenges.SolutionConstants;
import org.owasp.webgoat.lessons.challenges.Flag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import java.net.URI;
import java.net.URISyntaxException;
import java.time.LocalDateTime;
/**
* @author nbaars
* @since 4/8/17.
*/
@RestController
@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";
@Autowired
private RestTemplate restTemplate;
@Value("${webwolf.mail.url}")
private String webWolfMailURL;
@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>" + Flag.FLAGS.get(7) + "</b>");
}
return ResponseEntity.status(HttpStatus.I_AM_A_TEAPOT).body("That is not the reset link for admin");
}
@PostMapping("/challenge/7")
@ResponseBody
public AttackResult sendPasswordResetLink(@RequestParam String email, HttpServletRequest request) throws URISyntaxException {
if (StringUtils.hasText(email)) {
String username = email.substring(0, email.indexOf("@"));
if (StringUtils.hasText(username)) {
URI uri = new URI(request.getRequestURL().toString());
Email mail = Email.builder()
.title("Your password reset link for challenge 7")
.contents(String.format(TEMPLATE, uri.getScheme() + "://" + uri.getHost(), new PasswordResetLink().createPasswordReset(username, "webgoat")))
.sender("password-reset@webgoat-cloud.net")
.recipient(username)
.time(LocalDateTime.now()).build();
restTemplate.postForEntity(webWolfMailURL, mail, Object.class);
}
}
return success(this).feedback("email.send").feedbackArgs(email).build();
}
@GetMapping(value = "/challenge/7/.git", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
public ClassPathResource git() {
return new ClassPathResource("challenge7/git.zip");
}
}

View File

@@ -0,0 +1,23 @@
package org.owasp.webgoat.lessons.challenges.challenge7;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* @author nbaars
* @since 3/21/17.
*/
@Component
public class Challenge7 extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.CHALLENGE;
}
@Override
public String getTitle() {
return "challenge7.title";
}
}

View File

@@ -0,0 +1,688 @@
package org.owasp.webgoat.lessons.challenges.challenge7;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
/**
* MD5 hash generator.
* More information about this class is available from <a target="_top" href=
* "http://ostermiller.org/utils/MD5.html">ostermiller.org</a>.
* <p>
* This class takes as input a message of arbitrary length and produces
* as output a 128-bit "fingerprint" or "message digest" of the input.
* It is conjectured that it is computationally infeasible to produce
* two messages having the same message digest, or to produce any
* message having a given pre-specified target message digest. The MD5
* algorithm is intended for digital signature applications, where a
* large file must be "compressed" in a secure manner before being
* encrypted with a private (secret) key under a public-key cryptosystem
* such as RSA.
* <p>
* For more information see RFC1321.
*
* @author Santeri Paavolainen http://santtu.iki.fi/md5/
* @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
* @since ostermillerutils 1.00.00
*/
public class MD5 {
/**
* Class constructor
*
* @since ostermillerutils 1.00.00
*/
public MD5() {
reset();
}
/**
* Command line program that will take files as arguments
* and output the MD5 sum for each file.
*
* @param args command line arguments
* @since ostermillerutils 1.00.00
*/
public static void main(String[] args) {
if (args.length == 0) {
System.err.println("Please specify a file.");
} else {
for (String element : args) {
try {
System.out.println(MD5.getHashString(new File(element)) + " " + element);
} catch (IOException x) {
System.err.println(x.getMessage());
}
}
}
}
/**
* Gets this hash sum as an array of 16 bytes.
*
* @return Array of 16 bytes, the hash of all updated bytes.
* @since ostermillerutils 1.00.00
*/
public byte[] getHash() {
if (!finalState.valid) {
finalState.copy(workingState);
long bitCount = finalState.bitCount;
// Compute the number of left over bits
int leftOver = (int) (((bitCount >>> 3)) & 0x3f);
// Compute the amount of padding to add based on number of left over bits.
int padlen = (leftOver < 56) ? (56 - leftOver) : (120 - leftOver);
// add the padding
update(finalState, padding, 0, padlen);
// add the length (computed before padding was added)
update(finalState, encode(bitCount), 0, 8);
finalState.valid = true;
}
// make a copy of the hash before returning it.
return encode(finalState.state, 16);
}
/**
* Returns 32-character hex representation of this hash.
*
* @return String representation of this object's hash.
* @since ostermillerutils 1.00.00
*/
public String getHashString() {
return toHex(this.getHash());
}
/**
* Gets the MD5 hash of the given byte array.
*
* @param b byte array for which an MD5 hash is desired.
* @return Array of 16 bytes, the hash of all updated bytes.
* @since ostermillerutils 1.00.00
*/
public static byte[] getHash(byte[] b) {
MD5 md5 = new MD5();
md5.update(b);
return md5.getHash();
}
/**
* Gets the MD5 hash of the given byte array.
*
* @param b byte array for which an MD5 hash is desired.
* @return 32-character hex representation the data's MD5 hash.
* @since ostermillerutils 1.00.00
*/
public static String getHashString(byte[] b) {
MD5 md5 = new MD5();
md5.update(b);
return md5.getHashString();
}
/**
* Gets the MD5 hash the data on the given InputStream.
*
* @param in byte array for which an MD5 hash is desired.
* @return Array of 16 bytes, the hash of all updated bytes.
* @throws IOException if an I/O error occurs.
* @since ostermillerutils 1.00.00
*/
public static byte[] getHash(InputStream in) throws IOException {
MD5 md5 = new MD5();
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
md5.update(buffer, read);
}
return md5.getHash();
}
/**
* Gets the MD5 hash the data on the given InputStream.
*
* @param in byte array for which an MD5 hash is desired.
* @return 32-character hex representation the data's MD5 hash.
* @throws IOException if an I/O error occurs.
* @since ostermillerutils 1.00.00
*/
public static String getHashString(InputStream in) throws IOException {
MD5 md5 = new MD5();
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
md5.update(buffer, read);
}
return md5.getHashString();
}
/**
* Gets the MD5 hash of the given file.
*
* @param f file for which an MD5 hash is desired.
* @return Array of 16 bytes, the hash of all updated bytes.
* @throws IOException if an I/O error occurs.
* @since ostermillerutils 1.00.00
*/
public static byte[] getHash(File f) throws IOException {
InputStream is = new FileInputStream(f);
byte[] hash = getHash(is);
is.close();
return hash;
}
/**
* Gets the MD5 hash of the given file.
*
* @param f file array for which an MD5 hash is desired.
* @return 32-character hex representation the data's MD5 hash.
* @throws IOException if an I/O error occurs.
* @since ostermillerutils 1.00.00
*/
public static String getHashString(File f) throws IOException {
InputStream is = new FileInputStream(f);
String hash = getHashString(is);
is.close();
return hash;
}
/**
* Gets the MD5 hash of the given String.
* The string is converted to bytes using the current
* platform's default character encoding.
*
* @param s String for which an MD5 hash is desired.
* @return Array of 16 bytes, the hash of all updated bytes.
* @since ostermillerutils 1.00.00
*/
public static byte[] getHash(String s) {
MD5 md5 = new MD5();
md5.update(s);
return md5.getHash();
}
/**
* Gets the MD5 hash of the given String.
* The string is converted to bytes using the current
* platform's default character encoding.
*
* @param s String for which an MD5 hash is desired.
* @return 32-character hex representation the data's MD5 hash.
* @since ostermillerutils 1.00.00
*/
public static String getHashString(String s) {
MD5 md5 = new MD5();
md5.update(s);
return md5.getHashString();
}
/**
* Gets the MD5 hash of the given String.
*
* @param s String for which an MD5 hash is desired.
* @param enc The name of a supported character encoding.
* @return Array of 16 bytes, the hash of all updated bytes.
* @throws UnsupportedEncodingException If the named encoding is not supported.
* @since ostermillerutils 1.00.00
*/
public static byte[] getHash(String s, String enc) throws UnsupportedEncodingException {
MD5 md5 = new MD5();
md5.update(s, enc);
return md5.getHash();
}
/**
* Gets the MD5 hash of the given String.
*
* @param s String for which an MD5 hash is desired.
* @param enc The name of a supported character encoding.
* @return 32-character hex representation the data's MD5 hash.
* @throws UnsupportedEncodingException If the named encoding is not supported.
* @since ostermillerutils 1.00.00
*/
public static String getHashString(String s, String enc) throws UnsupportedEncodingException {
MD5 md5 = new MD5();
md5.update(s, enc);
return md5.getHashString();
}
/**
* Reset the MD5 sum to its initial state.
*
* @since ostermillerutils 1.00.00
*/
public void reset() {
workingState.reset();
finalState.valid = false;
}
/**
* Returns 32-character hex representation of this hash.
*
* @return String representation of this object's hash.
* @since ostermillerutils 1.00.00
*/
@Override
public String toString() {
return getHashString();
}
/**
* Update this hash with the given data.
* <p>
* A state may be passed into this method so that we can add padding
* and finalize a md5 hash without limiting our ability to update
* more data later.
* <p>
* If length bytes are not available to be hashed, as many bytes as
* possible will be hashed.
*
* @param state Which state is updated.
* @param buffer Array of bytes to be hashed.
* @param offset Offset to buffer array.
* @param length number of bytes to hash.
* @since ostermillerutils 1.00.00
*/
private void update(MD5State state, byte buffer[], int offset, int length) {
finalState.valid = false;
// if length goes beyond the end of the buffer, cut it short.
if ((length + offset) > buffer.length) {
length = buffer.length - offset;
}
// compute number of bytes mod 64
// this is what we have sitting in a buffer
// that have not been hashed yet
int index = (int) (state.bitCount >>> 3) & 0x3f;
// add the length to the count (translate bytes to bits)
state.bitCount += length << 3;
int partlen = 64 - index;
int i = 0;
if (length >= partlen) {
System.arraycopy(buffer, offset, state.buffer, index, partlen);
transform(state, decode(state.buffer, 64, 0));
for (i = partlen; (i + 63) < length; i += 64) {
transform(state, decode(buffer, 64, i));
}
index = 0;
}
// buffer remaining input
if (i < length) {
for (int start = i; i < length; i++) {
state.buffer[index + i - start] = buffer[i + offset];
}
}
}
/**
* Update this hash with the given data.
* <p>
* If length bytes are not available to be hashed, as many bytes as
* possible will be hashed.
*
* @param buffer Array of bytes to be hashed.
* @param offset Offset to buffer array.
* @param length number of bytes to hash.
* @since ostermillerutils 1.00.00
*/
public void update(byte buffer[], int offset, int length) {
update(workingState, buffer, offset, length);
}
/**
* Update this hash with the given data.
* <p>
* If length bytes are not available to be hashed, as many bytes as
* possible will be hashed.
*
* @param buffer Array of bytes to be hashed.
* @param length number of bytes to hash.
* @since ostermillerutils 1.00.00
*/
public void update(byte buffer[], int length) {
update(buffer, 0, length);
}
/**
* Update this hash with the given data.
*
* @param buffer Array of bytes to be hashed.
* @since ostermillerutils 1.00.00
*/
public void update(byte buffer[]) {
update(buffer, 0, buffer.length);
}
/**
* Updates this hash with a single byte.
*
* @param b byte to be hashed.
* @since ostermillerutils 1.00.00
*/
public void update(byte b) {
byte buffer[] = new byte[1];
buffer[0] = b;
update(buffer, 1);
}
/**
* Update this hash with a String.
* The string is converted to bytes using the current
* platform's default character encoding.
*
* @param s String to be hashed.
* @since ostermillerutils 1.00.00
*/
public void update(String s) {
update(s.getBytes());
}
/**
* Update this hash with a String.
*
* @param s String to be hashed.
* @param enc The name of a supported character encoding.
* @throws UnsupportedEncodingException If the named encoding is not supported.
* @since ostermillerutils 1.00.00
*/
public void update(String s, String enc) throws UnsupportedEncodingException {
update(s.getBytes(enc));
}
/**
* The current state from which the hash sum
* can be computed or updated.
*
* @since ostermillerutils 1.00.00
*/
private MD5State workingState = new MD5State();
/**
* Cached copy of the final MD5 hash sum. This is created when
* the hash is requested and it is invalidated when the hash
* is updated.
*
* @since ostermillerutils 1.00.00
*/
private MD5State finalState = new MD5State();
/**
* Temporary buffer cached here for performance reasons.
*
* @since ostermillerutils 1.00.00
*/
private int[] decodeBuffer = new int[16];
/**
* 64 bytes of padding that can be added if the length
* is not divisible by 64.
*
* @since ostermillerutils 1.00.00
*/
private static final byte padding[] = {
(byte) 0x80, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
/**
* Contains internal state of the MD5 class.
* Passes MD5 test suite as defined in RFC1321.
*
* @since ostermillerutils 1.00.00
*/
private class MD5State {
/**
* True if this state is valid.
*
* @since ostermillerutils 1.00.00
*/
private boolean valid = true;
/**
* Reset to initial state.
*
* @since ostermillerutils 1.00.00
*/
private void reset() {
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
state[3] = 0x10325476;
bitCount = 0;
}
/**
* 128-byte state
*
* @since ostermillerutils 1.00.00
*/
private int state[] = new int[4];
/**
* 64-bit count of the number of bits that have been hashed.
*
* @since ostermillerutils 1.00.00
*/
private long bitCount;
/**
* 64-byte buffer (512 bits) for storing to-be-hashed characters
*
* @since ostermillerutils 1.00.00
*/
private byte buffer[] = new byte[64];
private MD5State() {
reset();
}
/**
* Set this state to be exactly the same as some other.
*
* @param from state to copy from.
* @since ostermillerutils 1.00.00
*/
private void copy(MD5State from) {
System.arraycopy(from.buffer, 0, this.buffer, 0, this.buffer.length);
System.arraycopy(from.state, 0, this.state, 0, this.state.length);
this.valid = from.valid;
this.bitCount = from.bitCount;
}
}
/**
* Turns array of bytes into string representing each byte as
* a two digit unsigned hex number.
*
* @param hash Array of bytes to convert to hex-string
* @return Generated hex string
* @since ostermillerutils 1.00.00
*/
private static String toHex(byte hash[]) {
StringBuffer buf = new StringBuffer(hash.length * 2);
for (byte element : hash) {
int intVal = element & 0xff;
if (intVal < 0x10) {
// append a zero before a one digit hex
// number to make it two digits.
buf.append("0");
}
buf.append(Integer.toHexString(intVal));
}
return buf.toString();
}
private static int FF(int a, int b, int c, int d, int x, int s, int ac) {
a += ((b & c) | (~b & d));
a += x;
a += ac;
//return rotateLeft(a, s) + b;
a = (a << s) | (a >>> (32 - s));
return a + b;
}
private static int GG(int a, int b, int c, int d, int x, int s, int ac) {
a += ((b & d) | (c & ~d));
a += x;
a += ac;
//return rotateLeft(a, s) + b;
a = (a << s) | (a >>> (32 - s));
return a + b;
}
private static int HH(int a, int b, int c, int d, int x, int s, int ac) {
a += (b ^ c ^ d);
a += x;
a += ac;
//return rotateLeft(a, s) + b;
a = (a << s) | (a >>> (32 - s));
return a + b;
}
private static int II(int a, int b, int c, int d, int x, int s, int ac) {
a += (c ^ (b | ~d));
a += x;
a += ac;
//return rotateLeft(a, s) + b;
a = (a << s) | (a >>> (32 - s));
return a + b;
}
private static byte[] encode(long l) {
byte[] out = new byte[8];
out[0] = (byte) (l & 0xff);
out[1] = (byte) ((l >>> 8) & 0xff);
out[2] = (byte) ((l >>> 16) & 0xff);
out[3] = (byte) ((l >>> 24) & 0xff);
out[4] = (byte) ((l >>> 32) & 0xff);
out[5] = (byte) ((l >>> 40) & 0xff);
out[6] = (byte) ((l >>> 48) & 0xff);
out[7] = (byte) ((l >>> 56) & 0xff);
return out;
}
private static byte[] encode(int input[], int len) {
byte[] out = new byte[len];
int i, j;
for (i = j = 0; j < len; i++, j += 4) {
out[j] = (byte) (input[i] & 0xff);
out[j + 1] = (byte) ((input[i] >>> 8) & 0xff);
out[j + 2] = (byte) ((input[i] >>> 16) & 0xff);
out[j + 3] = (byte) ((input[i] >>> 24) & 0xff);
}
return out;
}
private int[] decode(byte buffer[], int len, int offset) {
int i, j;
for (i = j = 0; j < len; i++, j += 4) {
decodeBuffer[i] = (
(buffer[j + offset] & 0xff)) |
(((buffer[j + 1 + offset] & 0xff)) << 8) |
(((buffer[j + 2 + offset] & 0xff)) << 16) |
(((buffer[j + 3 + offset] & 0xff)) << 24
);
}
return decodeBuffer;
}
private static void transform(MD5State state, int[] x) {
int a = state.state[0];
int b = state.state[1];
int c = state.state[2];
int d = state.state[3];
/* Round 1 */
a = FF(a, b, c, d, x[0], 7, 0xd76aa478); /* 1 */
d = FF(d, a, b, c, x[1], 12, 0xe8c7b756); /* 2 */
c = FF(c, d, a, b, x[2], 17, 0x242070db); /* 3 */
b = FF(b, c, d, a, x[3], 22, 0xc1bdceee); /* 4 */
a = FF(a, b, c, d, x[4], 7, 0xf57c0faf); /* 5 */
d = FF(d, a, b, c, x[5], 12, 0x4787c62a); /* 6 */
c = FF(c, d, a, b, x[6], 17, 0xa8304613); /* 7 */
b = FF(b, c, d, a, x[7], 22, 0xfd469501); /* 8 */
a = FF(a, b, c, d, x[8], 7, 0x698098d8); /* 9 */
d = FF(d, a, b, c, x[9], 12, 0x8b44f7af); /* 10 */
c = FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */
b = FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */
a = FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */
d = FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */
c = FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */
b = FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */
/* Round 2 */
a = GG(a, b, c, d, x[1], 5, 0xf61e2562); /* 17 */
d = GG(d, a, b, c, x[6], 9, 0xc040b340); /* 18 */
c = GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */
b = GG(b, c, d, a, x[0], 20, 0xe9b6c7aa); /* 20 */
a = GG(a, b, c, d, x[5], 5, 0xd62f105d); /* 21 */
d = GG(d, a, b, c, x[10], 9, 0x02441453); /* 22 */
c = GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */
b = GG(b, c, d, a, x[4], 20, 0xe7d3fbc8); /* 24 */
a = GG(a, b, c, d, x[9], 5, 0x21e1cde6); /* 25 */
d = GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */
c = GG(c, d, a, b, x[3], 14, 0xf4d50d87); /* 27 */
b = GG(b, c, d, a, x[8], 20, 0x455a14ed); /* 28 */
a = GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */
d = GG(d, a, b, c, x[2], 9, 0xfcefa3f8); /* 30 */
c = GG(c, d, a, b, x[7], 14, 0x676f02d9); /* 31 */
b = GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */
/* Round 3 */
a = HH(a, b, c, d, x[5], 4, 0xfffa3942); /* 33 */
d = HH(d, a, b, c, x[8], 11, 0x8771f681); /* 34 */
c = HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */
b = HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */
a = HH(a, b, c, d, x[1], 4, 0xa4beea44); /* 37 */
d = HH(d, a, b, c, x[4], 11, 0x4bdecfa9); /* 38 */
c = HH(c, d, a, b, x[7], 16, 0xf6bb4b60); /* 39 */
b = HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */
a = HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */
d = HH(d, a, b, c, x[0], 11, 0xeaa127fa); /* 42 */
c = HH(c, d, a, b, x[3], 16, 0xd4ef3085); /* 43 */
b = HH(b, c, d, a, x[6], 23, 0x04881d05); /* 44 */
a = HH(a, b, c, d, x[9], 4, 0xd9d4d039); /* 45 */
d = HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */
c = HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */
b = HH(b, c, d, a, x[2], 23, 0xc4ac5665); /* 48 */
/* Round 4 */
a = II(a, b, c, d, x[0], 6, 0xf4292244); /* 49 */
d = II(d, a, b, c, x[7], 10, 0x432aff97); /* 50 */
c = II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */
b = II(b, c, d, a, x[5], 21, 0xfc93a039); /* 52 */
a = II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */
d = II(d, a, b, c, x[3], 10, 0x8f0ccc92); /* 54 */
c = II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */
b = II(b, c, d, a, x[1], 21, 0x85845dd1); /* 56 */
a = II(a, b, c, d, x[8], 6, 0x6fa87e4f); /* 57 */
d = II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */
c = II(c, d, a, b, x[6], 15, 0xa3014314); /* 59 */
b = II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */
a = II(a, b, c, d, x[4], 6, 0xf7537e82); /* 61 */
d = II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */
c = II(c, d, a, b, x[2], 15, 0x2ad7d2bb); /* 63 */
b = II(b, c, d, a, x[9], 21, 0xeb86d391); /* 64 */
state.state[0] += a;
state.state[1] += b;
state.state[2] += c;
state.state[3] += d;
}
}

View File

@@ -0,0 +1,43 @@
package org.owasp.webgoat.lessons.challenges.challenge7;
import java.util.Random;
/**
* WARNING: DO NOT CHANGE FILE WITHOUT CHANGING .git contents
*
* @author nbaars
* @since 8/17/17.
*/
public class PasswordResetLink {
public String createPasswordReset(String username, String key) {
Random random = new Random();
if (username.equalsIgnoreCase("admin")) {
//Admin has a fix reset link
random.setSeed(key.length());
}
return scramble(random, scramble(random, scramble(random, MD5.getHashString(username))));
}
public static String scramble(Random random, String inputString) {
char[] a = inputString.toCharArray();
for (int i = 0; i < a.length; i++) {
int j = random.nextInt(a.length);
char temp = a[i];
a[i] = a[j];
a[j] = temp;
}
return new String(a);
}
public static void main(String[] args) {
if (args == null || args.length != 2) {
System.out.println("Need a username and key");
System.exit(1);
}
String username = args[0];
String key = args[1];
System.out.println("Generation password reset link for " + username);
System.out.println("Created password reset link: " + new PasswordResetLink().createPasswordReset(username, key));
}
}

View File

@@ -0,0 +1,69 @@
package org.owasp.webgoat.lessons.challenges.challenge8;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.lessons.challenges.Flag;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
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.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author nbaars
* @since 4/8/17.
*/
@RestController
@Slf4j
public class Assignment8 extends AssignmentEndpoint {
private static final Map<Integer, Integer> votes = new HashMap<>();
static {
votes.put(1, 400);
votes.put(2, 120);
votes.put(3, 140);
votes.put(4, 150);
votes.put(5, 300);
}
@GetMapping(value = "/challenge/8/vote/{stars}", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<?> vote(@PathVariable(value = "stars") int nrOfStars, HttpServletRequest request) {
//Simple implementation of VERB Based Authentication
String msg = "";
if (request.getMethod().equals("GET")) {
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);
votes.put(nrOfStars, allVotesForStar + 1);
return ResponseEntity.ok().header("X-Flag", "Thanks for voting, your flag is: " + Flag.FLAGS.get(8)).build();
}
@GetMapping("/challenge/8/votes/")
public ResponseEntity<?> getVotes() {
return ResponseEntity.ok(votes.entrySet().stream().collect(Collectors.toMap(e -> "" + e.getKey(), e -> e.getValue())));
}
@GetMapping("/challenge/8/votes/average")
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);
var json = Map.of("average", (int) Math.ceil((double) categories / totalNumberOfVotes));
return ResponseEntity.ok(json);
}
@GetMapping("/challenge/8/notUsed")
public AttackResult notUsed() {
throw new IllegalStateException("Should never be called, challenge specific method");
}
}

View File

@@ -0,0 +1,23 @@
package org.owasp.webgoat.lessons.challenges.challenge8;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* @author nbaars
* @since 3/21/17.
*/
@Component
public class Challenge8 extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.CHALLENGE;
}
@Override
public String getTitle() {
return "challenge8.title";
}
}

View File

@@ -0,0 +1,45 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.chrome_dev_tools;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* @author TMelzer
* @since 30.11.18
*/
@Component
public class ChromeDevTools extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.GENERAL;
}
@Override
public String getTitle() {
return "3.chrome-dev-tools.title";//3rd lesson in General
}
}

View File

@@ -0,0 +1,54 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.chrome_dev_tools;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.session.UserSessionData;
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;
/**
* This is just a class used to make the the HTTP request.
*
* @author TMelzer
* @since 30.11.18
*/
@RestController
public class NetworkDummy extends AssignmentEndpoint {
@PostMapping("/ChromeDevTools/dummy")
@ResponseBody
public AttackResult completed(@RequestParam String successMessage) {
UserSessionData userSessionData = getUserSessionData();
String answer = (String) userSessionData.getValue("randValue");
if (successMessage != null && successMessage.equals(answer)) {
return success(this).feedback("xss-dom-message-success").build();
} else {
return failed(this).feedback("xss-dom-message-failure").build();
}
}
}

View File

@@ -0,0 +1,60 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.chrome_dev_tools;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.http.ResponseEntity;
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;
/**
* Assignment where the user has to look through an HTTP Request
* using the Developer Tools and find a specific number.
*
* @author TMelzer
* @since 30.11.18
*/
@RestController
@AssignmentHints({"networkHint1", "networkHint2"})
public class NetworkLesson extends AssignmentEndpoint {
@PostMapping(value = "/ChromeDevTools/network", params = {"network_num", "number"})
@ResponseBody
public AttackResult completed(@RequestParam String network_num, @RequestParam String number) {
if (network_num.equals(number)) {
return success(this).feedback("network.success").output("").build();
} else {
return failed(this).feedback("network.failed").build();
}
}
@PostMapping(path = "/ChromeDevTools/network", params = "networkNum")
@ResponseBody
public ResponseEntity<?> ok(@RequestParam String networkNum) {
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,23 @@
package org.owasp.webgoat.lessons.cia;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* @author BenediktStuhrmann
* @since 11/2/18.
*/
@Component
public class CIA extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.GENERAL;
}
@Override
public String getTitle() {
return "4.cia.title";//4th lesson in general
}
}

View File

@@ -0,0 +1,48 @@
package org.owasp.webgoat.lessons.cia;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.web.bind.annotation.GetMapping;
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;
@RestController
public class CIAQuiz extends AssignmentEndpoint {
String[] solutions = {"Solution 3", "Solution 1", "Solution 4", "Solution 2"};
boolean[] guesses = new boolean[solutions.length];
@PostMapping("/cia/quiz")
@ResponseBody
public AttackResult completed(@RequestParam String[] question_0_solution, @RequestParam String[] question_1_solution, @RequestParam String[] question_2_solution, @RequestParam String[] question_3_solution) {
int correctAnswers = 0;
String[] givenAnswers = {question_0_solution[0], question_1_solution[0], question_2_solution[0], question_3_solution[0]};
for (int i = 0; i < solutions.length; i++) {
if (givenAnswers[i].contains(solutions[i])) {
// answer correct
correctAnswers++;
guesses[i] = true;
} else {
// answer incorrect
guesses[i] = false;
}
}
if (correctAnswers == solutions.length) {
return success(this).build();
} else {
return failed(this).build();
}
}
@GetMapping("/cia/quiz")
@ResponseBody
public boolean[] getResults() {
return this.guesses;
}
}

View File

@@ -0,0 +1,48 @@
package org.owasp.webgoat.lessons.client_side_filtering;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* ************************************************************************************************
* 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 - 2014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author WebGoat
* @version $Id: $Id
* @since October 12, 2016
*/
@Component
public class ClientSideFiltering extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.CLIENT_SIDE;
}
@Override
public String getTitle() {
return "client.side.filtering.title";
}
}

View File

@@ -0,0 +1,44 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.client_side_filtering;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
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;
@RestController
@AssignmentHints({"ClientSideFilteringHint1", "ClientSideFilteringHint2", "ClientSideFilteringHint3", "ClientSideFilteringHint4"})
public class ClientSideFilteringAssignment extends AssignmentEndpoint {
@PostMapping("/clientSideFiltering/attack1")
@ResponseBody
public AttackResult completed(@RequestParam String answer) {
return "450000".equals(answer)
? success(this).feedback("assignment.solved").build() :
failed(this).feedback("ClientSideFiltering.incorrect").build();
}
}

View File

@@ -0,0 +1,51 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.client_side_filtering;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
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;
/**
* @author nbaars
* @since 4/6/17.
*/
@RestController
@AssignmentHints({"client.side.filtering.free.hint1", "client.side.filtering.free.hint2", "client.side.filtering.free.hint3"})
public class ClientSideFilteringFreeAssignment extends AssignmentEndpoint {
public static final String SUPER_COUPON_CODE = "get_it_for_free";
@PostMapping("/clientSideFiltering/getItForFree")
@ResponseBody
public AttackResult completed(@RequestParam String checkoutCode) {
if (SUPER_COUPON_CODE.equals(checkoutCode)) {
return success(this).build();
}
return failed(this).build();
}
}

View File

@@ -0,0 +1,110 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.client_side_filtering;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import javax.annotation.PostConstruct;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@Slf4j
public class Salaries {
@Value("${webgoat.user.directory}")
private String webGoatHomeDirectory;
@PostConstruct
public void copyFiles() {
ClassPathResource classPathResource = new ClassPathResource("lessons/employees.xml");
File targetDirectory = new File(webGoatHomeDirectory, "/ClientSideFiltering");
if (!targetDirectory.exists()) {
targetDirectory.mkdir();
}
try {
FileCopyUtils.copy(classPathResource.getInputStream(), new FileOutputStream(new File(targetDirectory, "employees.xml")));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@GetMapping("clientSideFiltering/salaries")
@ResponseBody
public List<Map<String, Object>> invoke() {
NodeList nodes = null;
File d = new File(webGoatHomeDirectory, "ClientSideFiltering/employees.xml");
XPathFactory factory = XPathFactory.newInstance();
XPath path = factory.newXPath();
try (InputStream is = new FileInputStream(d)) {
InputSource inputSource = new InputSource(is);
StringBuffer sb = new StringBuffer();
sb.append("/Employees/Employee/UserID | ");
sb.append("/Employees/Employee/FirstName | ");
sb.append("/Employees/Employee/LastName | ");
sb.append("/Employees/Employee/SSN | ");
sb.append("/Employees/Employee/Salary ");
String expression = sb.toString();
nodes = (NodeList) path.evaluate(expression, inputSource, XPathConstants.NODESET);
} catch (XPathExpressionException e) {
log.error("Unable to parse xml", e);
} catch (IOException e) {
log.error("Unable to read employees.xml at location: '{}'", d);
}
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 = new HashMap<>();
json.add(employeeJson);
}
Node node = nodes.item(i);
employeeJson.put(node.getNodeName(), node.getTextContent());
}
return json;
}
}

View File

@@ -0,0 +1,89 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.client_side_filtering;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Optional;
/**
* @author nbaars
* @since 4/6/17.
*/
@RestController
@RequestMapping("/clientSideFiltering/challenge-store")
public class ShopEndpoint {
@AllArgsConstructor
private class CheckoutCodes {
@Getter
private List<CheckoutCode> codes;
public Optional<CheckoutCode> get(String code) {
return codes.stream().filter(c -> c.getCode().equals(code)).findFirst();
}
}
@AllArgsConstructor
@Getter
private class CheckoutCode {
private String code;
private int discount;
}
private CheckoutCodes checkoutCodes;
public ShopEndpoint() {
List<CheckoutCode> codes = Lists.newArrayList();
codes.add(new CheckoutCode("webgoat", 25));
codes.add(new CheckoutCode("owasp", 25));
codes.add(new CheckoutCode("owasp-webgoat", 50));
this.checkoutCodes = new CheckoutCodes(codes);
}
@GetMapping(value = "/coupons/{code}", produces = MediaType.APPLICATION_JSON_VALUE)
public CheckoutCode getDiscountCode(@PathVariable String code) {
if (ClientSideFilteringFreeAssignment.SUPER_COUPON_CODE.equals(code)) {
return new CheckoutCode(ClientSideFilteringFreeAssignment.SUPER_COUPON_CODE, 100);
}
return checkoutCodes.get(code).orElse(new CheckoutCode("no", 0));
}
@GetMapping(value = "/coupons", produces = MediaType.APPLICATION_JSON_VALUE)
public CheckoutCodes all() {
List<CheckoutCode> all = Lists.newArrayList();
all.addAll(this.checkoutCodes.getCodes());
all.add(new CheckoutCode(ClientSideFilteringFreeAssignment.SUPER_COUPON_CODE, 100));
return new CheckoutCodes(all);
}
}

View File

@@ -0,0 +1,135 @@
package org.owasp.webgoat.lessons.cryptography;
import lombok.extern.slf4j.Slf4j;
import javax.xml.bind.DatatypeConverter;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAKeyGenParameterSpec;
import java.util.Base64;
@Slf4j
public class CryptoUtil {
private static final BigInteger[] FERMAT_PRIMES =
{ BigInteger.valueOf(3),
BigInteger.valueOf(5),
BigInteger.valueOf(17),
BigInteger.valueOf(257),
BigInteger.valueOf(65537) };
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
RSAKeyGenParameterSpec kpgSpec = new RSAKeyGenParameterSpec(2048, FERMAT_PRIMES[new SecureRandom().nextInt(FERMAT_PRIMES.length)]);
keyPairGenerator.initialize(kpgSpec);
//keyPairGenerator.initialize(2048);
return keyPairGenerator.generateKeyPair();
}
public static String getPrivateKeyInPEM(KeyPair keyPair) {
String encodedString = "-----BEGIN PRIVATE KEY-----\n";
encodedString = encodedString+new String(Base64.getEncoder().encode(keyPair.getPrivate().getEncoded()),Charset.forName("UTF-8"))+"\n";
encodedString = encodedString+"-----END PRIVATE KEY-----\n";
return encodedString;
}
public static String signMessage(String message, PrivateKey privateKey) {
log.debug("start signMessage");
String signature = null;
try {
//Initiate signature verification
Signature instance = Signature.getInstance("SHA256withRSA");
instance.initSign(privateKey);
instance.update(message.getBytes("UTF-8"));
//actual verification against signature
signature = new String(Base64.getEncoder().encode(instance.sign()), Charset.forName("UTF-8"));
log.info("signe the signature with result: {}", signature);
} catch (Exception e) {
log.error("Signature signing failed", e);
}
log.debug("end signMessage");
return signature;
}
public static boolean verifyMessage(String message, String base64EncSignature,
PublicKey publicKey) {
log.debug("start verifyMessage");
boolean result = false;
try {
base64EncSignature = base64EncSignature.replace("\r", "").replace("\n", "")
.replace(" ", "");
//get raw signature from base64 encrypted string in header
byte[] decodedSignature = Base64.getDecoder().decode(base64EncSignature);
//Initiate signature verification
Signature instance = Signature.getInstance("SHA256withRSA");
instance.initVerify(publicKey);
instance.update(message.getBytes("UTF-8"));
//actual verification against signature
result = instance.verify(decodedSignature);
log.info("Verified the signature with result: {}", result);
} catch (Exception e) {
log.error("Signature verification failed", e);
}
log.debug("end verifyMessage");
return result;
}
public static boolean verifyAssignment(String modulus, String signature, PublicKey publicKey) {
/* first check if the signature is correct, i.e. right private key and right hash */
boolean result = false;
if (modulus != null && signature != null) {
result = verifyMessage(modulus, signature, publicKey);
/*
* next check if the submitted modulus is the correct modulus of the public key
*/
RSAPublicKey rsaPubKey = (RSAPublicKey) publicKey;
if (modulus.length()==512) {
modulus = "00".concat(modulus);
}
result = result && (DatatypeConverter.printHexBinary(rsaPubKey.getModulus().toByteArray()).equals(modulus.toUpperCase()));
}
return result;
}
public static PrivateKey getPrivateKeyFromPEM(String privateKeyPem) throws NoSuchAlgorithmException, InvalidKeySpecException {
privateKeyPem = privateKeyPem.replace("-----BEGIN PRIVATE KEY-----", "");
privateKeyPem = privateKeyPem.replace("-----END PRIVATE KEY-----", "");
privateKeyPem = privateKeyPem.replace("\n", "").replace("\r", "");
byte [] decoded = Base64.getDecoder().decode(privateKeyPem);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
}

View File

@@ -0,0 +1,41 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.cryptography;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
@Component
public class Cryptography extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.GENERAL;
}
@Override
public String getTitle() {
return "6.crypto.title";//first lesson in general
}
}

View File

@@ -0,0 +1,73 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.cryptography;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
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;
import javax.servlet.http.HttpServletRequest;
import java.util.Base64;
import java.util.Random;
@RestController
public class EncodingAssignment extends AssignmentEndpoint {
public static String getBasicAuth(String username, String password) {
return Base64.getEncoder().encodeToString(username.concat(":").concat(password).getBytes());
}
@GetMapping(path="/crypto/encoding/basic",produces=MediaType.TEXT_HTML_VALUE)
@ResponseBody
public String getBasicAuth(HttpServletRequest request) {
String basicAuth = (String) request.getSession().getAttribute("basicAuth");
String username = request.getUserPrincipal().getName();
if (basicAuth == null) {
String password = HashingAssignment.SECRETS[new Random().nextInt(HashingAssignment.SECRETS.length)];
basicAuth = getBasicAuth(username, password);
request.getSession().setAttribute("basicAuth", basicAuth);
}
return "Authorization: Basic ".concat(basicAuth);
}
@PostMapping("/crypto/encoding/basic-auth")
@ResponseBody
public AttackResult completed(HttpServletRequest request, @RequestParam String answer_user, @RequestParam String answer_pwd) {
String basicAuth = (String) request.getSession().getAttribute("basicAuth");
if (basicAuth !=null && answer_user!=null && answer_pwd !=null
&& basicAuth.equals(getBasicAuth(answer_user,answer_pwd)))
{
return success(this)
.feedback("crypto-encoding.success")
.build();
} else {
return failed(this).feedback("crypto-encoding.empty").build();
}
}
}

View File

@@ -0,0 +1,110 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.cryptography;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.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 org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
@RestController
@AssignmentHints({"crypto-hashing.hints.1","crypto-hashing.hints.2"})
public class HashingAssignment extends AssignmentEndpoint {
public static final String[] SECRETS = {"secret","admin","password", "123456", "passw0rd"};
@RequestMapping(path="/crypto/hashing/md5",produces=MediaType.TEXT_HTML_VALUE)
@ResponseBody
public String getMd5(HttpServletRequest request) throws NoSuchAlgorithmException {
String md5Hash = (String) request.getSession().getAttribute("md5Hash");
if (md5Hash == null) {
String secret = SECRETS[new Random().nextInt(SECRETS.length)];
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(secret.getBytes());
byte[] digest = md.digest();
md5Hash = DatatypeConverter
.printHexBinary(digest).toUpperCase();
request.getSession().setAttribute("md5Hash", md5Hash);
request.getSession().setAttribute("md5Secret", secret);
}
return md5Hash;
}
@RequestMapping(path="/crypto/hashing/sha256",produces=MediaType.TEXT_HTML_VALUE)
@ResponseBody
public String getSha256(HttpServletRequest request) throws NoSuchAlgorithmException {
String sha256 = (String) request.getSession().getAttribute("sha256");
if (sha256 == null) {
String secret = SECRETS[new Random().nextInt(SECRETS.length)];
sha256 = getHash(secret, "SHA-256");
request.getSession().setAttribute("sha256Hash", sha256);
request.getSession().setAttribute("sha256Secret", secret);
}
return sha256;
}
@PostMapping("/crypto/hashing")
@ResponseBody
public AttackResult completed(HttpServletRequest request, @RequestParam String answer_pwd1, @RequestParam String answer_pwd2) {
String md5Secret = (String) request.getSession().getAttribute("md5Secret");
String sha256Secret = (String) request.getSession().getAttribute("sha256Secret");
if (answer_pwd1!=null && answer_pwd2 !=null) {
if (answer_pwd1.equals(md5Secret)
&& answer_pwd2.equals(sha256Secret)) {
return success(this)
.feedback("crypto-hashing.success")
.build();
} else if (answer_pwd1.equals(md5Secret)
|| answer_pwd2.equals(sha256Secret)) {
return failed(this).feedback("crypto-hashing.oneok").build();
}
}
return failed(this).feedback("crypto-hashing.empty").build();
}
public static String getHash(String secret, String algorithm) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance(algorithm);
md.update(secret.getBytes());
byte[] digest = md.digest();
return DatatypeConverter
.printHexBinary(digest).toUpperCase();
}
}

View File

@@ -0,0 +1,53 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.cryptography;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
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;
import java.security.NoSuchAlgorithmException;
@RestController
@AssignmentHints({"crypto-secure-defaults.hints.1", "crypto-secure-defaults.hints.2", "crypto-secure-defaults.hints.3"})
public class SecureDefaultsAssignment extends AssignmentEndpoint {
@PostMapping("/crypto/secure/defaults")
@ResponseBody
public AttackResult completed(@RequestParam String secretFileName, @RequestParam String secretText) throws NoSuchAlgorithmException {
if (secretFileName!=null && secretFileName.equals("default_secret")) {
if (secretText!=null && HashingAssignment.getHash(secretText, "SHA-256").equalsIgnoreCase("34de66e5caf2cb69ff2bebdc1f3091ecf6296852446c718e38ebfa60e4aa75d2")) {
return success(this)
.feedback("crypto-secure-defaults.success")
.build();
} else {
return failed(this).feedback("crypto-secure-defaults.messagenotok").build();
}
}
return failed(this).feedback("crypto-secure-defaults.notok").build();
}
}

View File

@@ -0,0 +1,86 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.cryptography;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.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 org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPublicKey;
@RestController
@AssignmentHints({"crypto-signing.hints.1","crypto-signing.hints.2", "crypto-signing.hints.3", "crypto-signing.hints.4"})
@Slf4j
public class SigningAssignment extends AssignmentEndpoint {
@RequestMapping(path="/crypto/signing/getprivate",produces=MediaType.TEXT_HTML_VALUE)
@ResponseBody
public String getPrivateKey(HttpServletRequest request) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
String privateKey = (String) request.getSession().getAttribute("privateKeyString");
if (privateKey == null) {
KeyPair keyPair = CryptoUtil.generateKeyPair();
privateKey = CryptoUtil.getPrivateKeyInPEM(keyPair);
request.getSession().setAttribute("privateKeyString", privateKey);
request.getSession().setAttribute("keyPair", keyPair);
}
return privateKey;
}
@PostMapping("/crypto/signing/verify")
@ResponseBody
public AttackResult completed(HttpServletRequest request, @RequestParam String modulus, @RequestParam String signature) {
String tempModulus = modulus;/* used to validate the modulus of the public key but might need to be corrected */
KeyPair keyPair = (KeyPair) request.getSession().getAttribute("keyPair");
RSAPublicKey rsaPubKey = (RSAPublicKey) keyPair.getPublic();
if (tempModulus.length() == 512) {
tempModulus = "00".concat(tempModulus);
}
if (!DatatypeConverter.printHexBinary(rsaPubKey.getModulus().toByteArray()).equals(tempModulus.toUpperCase())) {
log.warn("modulus {} incorrect", modulus);
return failed(this).feedback("crypto-signing.modulusnotok").build();
}
/* orginal modulus must be used otherwise the signature would be invalid */
if (CryptoUtil.verifyMessage(modulus, signature, keyPair.getPublic())) {
return success(this).feedback("crypto-signing.success").build();
} else {
log.warn("signature incorrect");
return failed(this).feedback("crypto-signing.notok").build();
}
}
}

View File

@@ -0,0 +1,47 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.cryptography;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
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;
@RestController
@AssignmentHints({"crypto-encoding-xor.hints.1"})
public class XOREncodingAssignment extends AssignmentEndpoint {
@PostMapping("/crypto/encoding/xor")
@ResponseBody
public AttackResult completed(@RequestParam String answer_pwd1) {
if (answer_pwd1!=null && answer_pwd1.equals("databasepassword")) {
return success(this)
.feedback("crypto-encoding-xor.success")
.build();
}
return failed(this).feedback("crypto-encoding-xor.empty").build();
}
}

View File

@@ -0,0 +1,41 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.csrf;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* Created by jason on 9/29/17.
*/
@Component
public class CSRF extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.REQUEST_FORGERIES;
}
@Override
public String getTitle() { return "csrf.title"; }
}

View File

@@ -0,0 +1,58 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.csrf;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.session.UserSessionData;
import org.springframework.beans.factory.annotation.Autowired;
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 9/29/17.
*/
@RestController
@AssignmentHints({"csrf-get.hint1", "csrf-get.hint2", "csrf-get.hint3", "csrf-get.hint4"})
public class CSRFConfirmFlag1 extends AssignmentEndpoint {
@Autowired
UserSessionData userSessionData;
@PostMapping(path = "/csrf/confirm-flag-1", produces = {"application/json"})
@ResponseBody
public AttackResult completed(String confirmFlagVal) {
Object userSessionDataStr = userSessionData.getValue("csrf-get-success");
if (userSessionDataStr != null && confirmFlagVal.equals(userSessionDataStr.toString())) {
return success(this)
.feedback("csrf-get-null-referer.success")
.output("Correct, the flag was " + userSessionData.getValue("csrf-get-success"))
.build();
}
return failed(this).build();
}
}

View File

@@ -0,0 +1,120 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.csrf;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.session.UserSessionData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;
/**
* @author nbaars
* @since 11/17/17.
*/
@RestController
@AssignmentHints({"csrf-feedback-hint1", "csrf-feedback-hint2", "csrf-feedback-hint3"})
public class CSRFFeedback extends AssignmentEndpoint {
@Autowired
private UserSessionData userSessionData;
@Autowired
private ObjectMapper objectMapper;
@PostMapping(value = "/csrf/feedback/message", produces = {"application/json"})
@ResponseBody
public AttackResult completed(HttpServletRequest request, @RequestBody String feedback) {
try {
objectMapper.enable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES);
objectMapper.enable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
objectMapper.enable(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS);
objectMapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
objectMapper.enable(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES);
objectMapper.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
objectMapper.readValue(feedback.getBytes(), Map.class);
} catch (IOException e) {
return failed(this).feedback(ExceptionUtils.getStackTrace(e)).build();
}
boolean correctCSRF = requestContainsWebGoatCookie(request.getCookies()) && request.getContentType().contains(MediaType.TEXT_PLAIN_VALUE);
correctCSRF &= hostOrRefererDifferentHost(request);
if (correctCSRF) {
String flag = UUID.randomUUID().toString();
userSessionData.setValue("csrf-feedback", flag);
return success(this).feedback("csrf-feedback-success").feedbackArgs(flag).build();
}
return failed(this).build();
}
@PostMapping(path = "/csrf/feedback", produces = "application/json")
@ResponseBody
public AttackResult flag(@RequestParam("confirmFlagVal") String flag) {
if (flag.equals(userSessionData.getValue("csrf-feedback"))) {
return success(this).build();
} else {
return failed(this).build();
}
}
private boolean hostOrRefererDifferentHost(HttpServletRequest request) {
String referer = request.getHeader("Referer");
String host = request.getHeader("Host");
if (referer != null) {
return !referer.contains(host);
} else {
return true;
}
}
private boolean requestContainsWebGoatCookie(Cookie[] cookies) {
if (cookies != null) {
for (Cookie c : cookies) {
if (c.getName().equals("JSESSIONID")) {
return true;
}
}
}
return false;
}
/** Solution
<form name="attack" enctype="text/plain" action="http://localhost:8080/WebGoat/csrf/feedback/message" METHOD="POST">
<input type="hidden" name='{"name": "Test", "email": "test1233@dfssdf.de", "subject": "service", "message":"dsaffd"}'>
</form>
<script>document.attack.submit();</script>
*/
}

View File

@@ -0,0 +1,89 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.csrf;
import org.owasp.webgoat.container.i18n.PluginMessages;
import org.owasp.webgoat.container.session.UserSessionData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
/**
* Created by jason on 9/30/17.
*/
@RestController
public class CSRFGetFlag {
@Autowired
UserSessionData userSessionData;
@Autowired
private PluginMessages pluginMessages;
@RequestMapping(path = "/csrf/basic-get-flag", produces = {"application/json"}, method = RequestMethod.POST)
@ResponseBody
public Map<String, Object> invoke(HttpServletRequest req) {
Map<String, Object> response = new HashMap<>();
String host = (req.getHeader("host") == null) ? "NULL" : req.getHeader("host");
String referer = (req.getHeader("referer") == null) ? "NULL" : req.getHeader("referer");
String[] refererArr = referer.split("/");
if (referer.equals("NULL")) {
if ("true".equals(req.getParameter("csrf"))) {
Random random = new Random();
userSessionData.setValue("csrf-get-success", random.nextInt(65536));
response.put("success", true);
response.put("message", pluginMessages.getMessage("csrf-get-null-referer.success"));
response.put("flag", userSessionData.getValue("csrf-get-success"));
} else {
Random random = new Random();
userSessionData.setValue("csrf-get-success", random.nextInt(65536));
response.put("success", true);
response.put("message", pluginMessages.getMessage("csrf-get-other-referer.success"));
response.put("flag", userSessionData.getValue("csrf-get-success"));
}
} else if (refererArr[2].equals(host)) {
response.put("success", false);
response.put("message", "Appears the request came from the original host");
response.put("flag", null);
} else {
Random random = new Random();
userSessionData.setValue("csrf-get-success", random.nextInt(65536));
response.put("success", true);
response.put("message", pluginMessages.getMessage("csrf-get-other-referer.success"));
response.put("flag", userSessionData.getValue("csrf-get-success"));
}
return response;
}
}

View File

@@ -0,0 +1,66 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.csrf;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.users.UserTracker;
import org.owasp.webgoat.container.users.UserTrackerRepository;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* @author nbaars
* @since 11/17/17.
*/
@RestController
@AssignmentHints({"csrf-login-hint1", "csrf-login-hint2", "csrf-login-hint3"})
public class CSRFLogin extends AssignmentEndpoint {
private final UserTrackerRepository userTrackerRepository;
public CSRFLogin(UserTrackerRepository userTrackerRepository) {
this.userTrackerRepository = userTrackerRepository;
}
@PostMapping(path = "/csrf/login", produces = {"application/json"})
@ResponseBody
public AttackResult completed(HttpServletRequest request) {
String userName = request.getUserPrincipal().getName();
if (userName.startsWith("csrf")) {
markAssignmentSolvedWithRealUser(userName.substring("csrf-".length()));
return success(this).feedback("csrf-login-success").build();
}
return failed(this).feedback("csrf-login-failed").feedbackArgs(userName).build();
}
private void markAssignmentSolvedWithRealUser(String username) {
UserTracker userTracker = userTrackerRepository.findByUser(username);
userTracker.assignmentSolved(getWebSession().getCurrentLesson(), this.getClass().getSimpleName());
userTrackerRepository.save(userTracker);
}
}

View File

@@ -0,0 +1,114 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.csrf;
import com.google.common.collect.Lists;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.springframework.http.MediaType.ALL_VALUE;
@RestController
@AssignmentHints({"csrf-review-hint1", "csrf-review-hint2", "csrf-review-hint3"})
public class ForgedReviews extends AssignmentEndpoint {
@Autowired
private WebSession webSession;
private static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd, HH:mm:ss");
private static final Map<String, List<Review>> userReviews = new HashMap<>();
private static final List<Review> REVIEWS = new ArrayList<>();
private static final String weakAntiCSRF = "2aa14227b9a13d0bede0388a7fba9aa9";
static {
REVIEWS.add(new Review("secUriTy", DateTime.now().toString(fmt), "This is like swiss cheese", 0));
REVIEWS.add(new Review("webgoat", DateTime.now().toString(fmt), "It works, sorta", 2));
REVIEWS.add(new Review("guest", DateTime.now().toString(fmt), "Best, App, Ever", 5));
REVIEWS.add(new Review("guest", DateTime.now().toString(fmt), "This app is so insecure, I didn't even post this review, can you pull that off too?", 1));
}
@GetMapping(path = "/csrf/review", produces = MediaType.APPLICATION_JSON_VALUE, consumes = ALL_VALUE)
@ResponseBody
public Collection<Review> retrieveReviews() {
Collection<Review> allReviews = Lists.newArrayList();
Collection<Review> newReviews = userReviews.get(webSession.getUserName());
if (newReviews != null) {
allReviews.addAll(newReviews);
}
allReviews.addAll(REVIEWS);
return allReviews;
}
@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("/");
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
if (validateReq == null || !validateReq.equals(weakAntiCSRF)) {
return failed(this).feedback("csrf-you-forgot-something").build();
}
//we have the spoofed files
if (referer != "NULL" && refererArr[2].equals(host)) {
return failed(this).feedback("csrf-same-host").build();
} else {
return success(this).feedback("csrf-review.success").build(); //feedback("xss-stored-comment-failure")
}
}
}

View File

@@ -0,0 +1,47 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.csrf;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author nbaars
* @since 4/8/17.
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@XmlRootElement
public class Review {
private String user;
private String dateTime;
private String text;
private Integer stars;
}

View File

@@ -0,0 +1,47 @@
package org.owasp.webgoat.lessons.deserialization;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* ************************************************************************************************
* 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 - 2014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author WebGoat
* @version $Id: $Id
* @since October 12, 2016
*/
@Component
public class InsecureDeserialization extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.INSECURE_DESERIALIZATION;
}
@Override
public String getTitle() {
return "insecure-deserialization.title";
}
}

View File

@@ -0,0 +1,81 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.deserialization;
import org.dummy.insecure.framework.VulnerableTaskHolder;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
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;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.util.Base64;
@RestController
@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;
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 failed(this).feedback("insecure-deserialization.stringobject").build();
}
return failed(this).feedback("insecure-deserialization.wrongobject").build();
}
after = System.currentTimeMillis();
} catch (InvalidClassException e) {
return failed(this).feedback("insecure-deserialization.invalidversion").build();
} catch (IllegalArgumentException e) {
return failed(this).feedback("insecure-deserialization.expired").build();
} catch (Exception e) {
return failed(this).feedback("insecure-deserialization.invalidversion").build();
}
delay = (int) (after - before);
if (delay > 7000) {
return failed(this).build();
}
if (delay < 3000) {
return failed(this).build();
}
return success(this).build();
}
}

View File

@@ -0,0 +1,54 @@
package org.owasp.webgoat.lessons.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

@@ -0,0 +1,48 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2021 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.hijacksession;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/***
*
* @author Angel Olle Blazquez
*
*/
@Component
public class HijackSession extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.SESSION_MANAGEMENT;
}
@Override
public String getTitle() {
return "hijacksession.title";
}
}

View File

@@ -0,0 +1,92 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2021 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.hijacksession;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.lessons.hijacksession.cas.Authentication;
import org.owasp.webgoat.lessons.hijacksession.cas.HijackSessionAuthenticationProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CookieValue;
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;
/***
*
* @author Angel Olle Blazquez
*
*/
@RestController
@AssignmentHints({
"hijacksession.hints.1",
"hijacksession.hints.2",
"hijacksession.hints.3",
"hijacksession.hints.4",
"hijacksession.hints.5"
})
public class HijackSessionAssignment extends AssignmentEndpoint {
private static final String COOKIE_NAME = "hijack_cookie";
@Autowired
HijackSessionAuthenticationProvider provider;
@PostMapping(path = "/HijackSession/login")
@ResponseBody
public AttackResult login(
@RequestParam String username,
@RequestParam String password,
@CookieValue(value = COOKIE_NAME, required = false) String cookieValue,
HttpServletResponse response) {
Authentication authentication;
if (StringUtils.isEmpty(cookieValue)) {
authentication = provider.authenticate(Authentication.builder().name(username).credentials(password).build());
setCookie(response, authentication.getId());
} else {
authentication = provider.authenticate(Authentication.builder().id(cookieValue).build());
}
if (authentication.isAuthenticated()) {
return success(this).build();
}
return failed(this).build();
}
private void setCookie(HttpServletResponse response, String cookieValue) {
Cookie cookie = new Cookie(COOKIE_NAME, cookieValue);
cookie.setPath("/WebGoat");
cookie.setSecure(true);
response.addCookie(cookie);
}
}

View File

@@ -0,0 +1,67 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2021 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.hijacksession.cas;
import java.security.Principal;
import lombok.Builder;
import lombok.Getter;
import lombok.ToString;
/**
*
* @author Angel Olle Blazquez
*
*/
@Getter
@ToString
public class Authentication implements Principal {
private boolean authenticated = false;
private String name;
private Object credentials;
private String id;
@Builder
public Authentication(String name, Object credentials, String id) {
this.name = name;
this.credentials = credentials;
this.id = id;
}
@Override
public String getName() {
return name;
}
protected void setAuthenticated(boolean authenticated) {
this.authenticated = authenticated;
}
protected void setId(String id) {
this.id = id;
}
}

View File

@@ -0,0 +1,39 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2021 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.hijacksession.cas;
import java.security.Principal;
/**
*
* @author Angel Olle Blazquez
*
*/
@FunctionalInterface
public interface AuthenticationProvider<T extends Principal> {
T authenticate(T t);
}

View File

@@ -0,0 +1,100 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2021 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.hijacksession.cas;
import java.time.Instant;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.DoublePredicate;
import java.util.function.Supplier;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.ApplicationScope;
/**
*
* @author Angel Olle Blazquez
*
*/
// weak id value and mechanism
@ApplicationScope
@Component
public class HijackSessionAuthenticationProvider implements AuthenticationProvider<Authentication> {
private Queue<String> sessions = new LinkedList<>();
private static long id = new Random().nextLong() & Long.MAX_VALUE;
protected static final int MAX_SESSIONS = 50;
private static final DoublePredicate PROBABILITY_DOUBLE_PREDICATE = pr -> pr < 0.75;
private static final Supplier<String> GENERATE_SESSION_ID = () -> ++id + "-" + Instant.now().toEpochMilli();
public static final Supplier<Authentication> AUTHENTICATION_SUPPLIER = () -> Authentication
.builder()
.id(GENERATE_SESSION_ID.get())
.build();
@Override
public Authentication authenticate(Authentication authentication) {
if (authentication == null) {
return AUTHENTICATION_SUPPLIER.get();
}
if (StringUtils.isNotEmpty(authentication.getId()) && sessions.contains(authentication.getId())) {
authentication.setAuthenticated(true);
return authentication;
}
if (StringUtils.isEmpty(authentication.getId())) {
authentication.setId(GENERATE_SESSION_ID.get());
}
authorizedUserAutoLogin();
return authentication;
}
protected void authorizedUserAutoLogin() {
if (!PROBABILITY_DOUBLE_PREDICATE.test(ThreadLocalRandom.current().nextDouble())) {
Authentication authentication = AUTHENTICATION_SUPPLIER.get();
authentication.setAuthenticated(true);
addSession(authentication.getId());
}
}
protected boolean addSession(String sessionId) {
if (sessions.size() >= MAX_SESSIONS) {
sessions.remove();
}
return sessions.add(sessionId);
}
protected int getSessionsSize() {
return sessions.size();
}
}

View File

@@ -0,0 +1,47 @@
package org.owasp.webgoat.lessons.html_tampering;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* ************************************************************************************************
* 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 - 2014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author WebGoat
* @version $Id: $Id
* @since October 12, 2016
*/
@Component
public class HtmlTampering extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.CLIENT_SIDE;
}
@Override
public String getTitle() {
return "html-tampering.title";
}
}

View File

@@ -0,0 +1,45 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.html_tampering;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
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;
@RestController
@AssignmentHints({"hint1", "hint2", "hint3"})
public class HtmlTamperingTask extends AssignmentEndpoint {
@PostMapping("/HtmlTampering/task")
@ResponseBody
public AttackResult completed(@RequestParam String QTY, @RequestParam String Total) {
if (Float.parseFloat(QTY) * 2999.99 > Float.parseFloat(Total) + 1) {
return success(this).feedback("html-tampering.tamper.success").build();
}
return failed(this).feedback("html-tampering.tamper.failure").build();
}
}

View File

@@ -0,0 +1,40 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.http_basics;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
@Component
public class HttpBasics extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.GENERAL;
}
@Override
public String getTitle() {
return "1.http-basics.title";//first lesson in general
}
}

View File

@@ -0,0 +1,49 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.http_basics;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
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;
@RestController
@AssignmentHints({"http-basics.hints.http_basics_lesson.1"})
public class HttpBasicsLesson extends AssignmentEndpoint {
@PostMapping("/HttpBasics/attack1")
@ResponseBody
public AttackResult completed(@RequestParam String person) {
if (!person.isBlank()) {
return success(this)
.feedback("http-basics.reversed")
.feedbackArgs(new StringBuilder(person).reverse().toString())
.build();
} else {
return failed(this).feedback("http-basics.empty").build();
}
}
}

View File

@@ -0,0 +1,54 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.http_basics;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AssignmentPath;
import org.owasp.webgoat.container.assignments.AttackResult;
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;
@RestController
@AssignmentHints({"http-basics.hints.http_basic_quiz.1", "http-basics.hints.http_basic_quiz.2"})
@AssignmentPath("HttpBasics/attack2")
public class HttpBasicsQuiz extends AssignmentEndpoint {
@PostMapping("/HttpBasics/attack2")
@ResponseBody
public AttackResult completed(@RequestParam String answer, @RequestParam String magic_answer, @RequestParam String magic_num) {
if ("POST".equalsIgnoreCase(answer) && magic_answer.equals(magic_num)) {
return success(this).build();
} else {
if (!"POST".equalsIgnoreCase(answer)) {
return failed(this).feedback("http-basics.incorrect").build();
}
if (!magic_answer.equals(magic_num)) {
return failed(this).feedback("http-basics.magic").build();
}
}
return failed(this).build();
}
}

View File

@@ -0,0 +1,53 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.http_proxies;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController
public class HttpBasicsInterceptRequest extends AssignmentEndpoint {
@RequestMapping(path = "/HttpProxies/intercept-request", method = {RequestMethod.POST, RequestMethod.GET})
@ResponseBody
public AttackResult completed(@RequestHeader(value = "x-request-intercepted", required = false) Boolean headerValue,
@RequestParam(value = "changeMe", required = false) String paramValue, HttpServletRequest request) {
if (HttpMethod.POST.matches(request.getMethod())) {
return failed(this).feedback("http-proxies.intercept.failure").build();
}
if (headerValue != null && paramValue != null && headerValue && "Requests are tampered easily".equalsIgnoreCase(paramValue)) {
return success(this).feedback("http-proxies.intercept.success").build();
} else {
return failed(this).feedback("http-proxies.intercept.failure").build();
}
}
}

View File

@@ -0,0 +1,47 @@
package org.owasp.webgoat.lessons.http_proxies;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* ************************************************************************************************
* 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 - 2014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author WebGoat
* @version $Id: $Id
* @since October 12, 2016
*/
@Component
public class HttpProxies extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.GENERAL;
}
@Override
public String getTitle() {
return "2.http-proxies.title";//second lesson in GENERAL
}
}

View File

@@ -0,0 +1,48 @@
package org.owasp.webgoat.lessons.idor;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* ************************************************************************************************
* 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 - 2014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author misfir3
* @version $Id: $Id
* @since January 3, 2017
*/
@Component
public class IDOR extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.ACCESS_CONTROL;
}
@Override
public String getTitle() {
return "idor.title";
}
}

View File

@@ -0,0 +1,52 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.idor;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
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;
@RestController
@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) {
attributes = attributes.trim();
String[] diffAttribs = attributes.split(",");
if (diffAttribs.length < 2) {
return failed(this).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")) {
return success(this).feedback("idor.diff.success").build();
} else {
return failed(this).feedback("idor.diff.failure").build();
}
}
}

View File

@@ -0,0 +1,99 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.idor;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.session.UserSessionData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@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 IDOREditOtherProfiile extends AssignmentEndpoint {
@Autowired
private UserSessionData userSessionData;
@PutMapping(path = "/IDOR/profile/{userId}", consumes = "application/json")
@ResponseBody
public AttackResult completed(@PathVariable("userId") String userId, @RequestBody UserProfile userSubmittedProfile) {
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
UserProfile currentUserProfile = new UserProfile(userId);
if (userSubmittedProfile.getUserId() != null && !userSubmittedProfile.getUserId().equals(authUserId)) {
// let's get this started ...
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);
if (currentUserProfile.getRole() <= 1 && currentUserProfile.getColor().toLowerCase().equals("red")) {
return success(this)
.feedback("idor.edit.profile.success1")
.output(currentUserProfile.profileToMap().toString())
.build();
}
if (currentUserProfile.getRole() > 1 && currentUserProfile.getColor().toLowerCase().equals("red")) {
return success(this)
.feedback("idor.edit.profile.failure1")
.output(currentUserProfile.profileToMap().toString())
.build();
}
if (currentUserProfile.getRole() <= 1 && !currentUserProfile.getColor().toLowerCase().equals("red")) {
return success(this)
.feedback("idor.edit.profile.failure2")
.output(currentUserProfile.profileToMap().toString())
.build();
}
// else
return failed(this)
.feedback("idor.edit.profile.failure3")
.output(currentUserProfile.profileToMap().toString())
.build();
} else if (userSubmittedProfile.getUserId().equals(authUserId)) {
return failed(this).feedback("idor.edit.profile.failure4").build();
}
if (currentUserProfile.getColor().equals("black") && currentUserProfile.getRole() <= 1) {
return success(this)
.feedback("idor.edit.profile.success2")
.output(userSessionData.getValue("idor-updated-own-profile").toString())
.build();
} else {
return failed(this).feedback("idor.edit.profile.failure3").build();
}
}
}

View File

@@ -0,0 +1,77 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.idor;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.session.UserSessionData;
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;
import java.util.HashMap;
import java.util.Map;
@RestController
@AssignmentHints({"idor.hints.idor_login"})
public class IDORLogin extends AssignmentEndpoint {
private Map<String, Map<String, String>> idorUserInfo = new HashMap<>();
public void initIDORInfo() {
idorUserInfo.put("tom", new HashMap<String, String>());
idorUserInfo.get("tom").put("password", "cat");
idorUserInfo.get("tom").put("id", "2342384");
idorUserInfo.get("tom").put("color", "yellow");
idorUserInfo.get("tom").put("size", "small");
idorUserInfo.put("bill", new HashMap<String, String>());
idorUserInfo.get("bill").put("password", "buffalo");
idorUserInfo.get("bill").put("id", "2342388");
idorUserInfo.get("bill").put("color", "brown");
idorUserInfo.get("bill").put("size", "large");
}
@PostMapping("/IDOR/login")
@ResponseBody
public AttackResult completed(@RequestParam String username, @RequestParam String password) {
initIDORInfo();
UserSessionData userSessionData = getUserSessionData();
if (idorUserInfo.containsKey(username)) {
if ("tom".equals(username) && idorUserInfo.get("tom").get("password").equals(password)) {
userSessionData.setValue("idor-authenticated-as", username);
userSessionData.setValue("idor-authenticated-user-id", idorUserInfo.get(username).get("id"));
return success(this).feedback("idor.login.success").feedbackArgs(username).build();
} else {
return failed(this).feedback("idor.login.failure").build();
}
} else {
return failed(this).feedback("idor.login.failure").build();
}
}
}

View File

@@ -0,0 +1,69 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.idor;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.session.UserSessionData;
import org.springframework.beans.factory.annotation.Autowired;
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 {
@Autowired
UserSessionData userSessionData;
@GetMapping(path = "/IDOR/profile/{userId}", produces = {"application/json"})
@ResponseBody
public AttackResult completed(@PathVariable("userId") String userId, HttpServletResponse resp) {
Map<String, Object> details = new HashMap<>();
if (userSessionData.getValue("idor-authenticated-as").equals("tom")) {
//going to use session auth to view this one
String authUserId = (String) userSessionData.getValue("idor-authenticated-user-id");
if (userId != null && !userId.equals(authUserId)) {
//on the right track
UserProfile requestedProfile = new UserProfile(userId);
// secure code would ensure there was a horizontal access control check prior to dishing up the requested profile
if (requestedProfile.getUserId().equals("2342388")) {
return success(this).feedback("idor.view.profile.success").output(requestedProfile.profileToMap().toString()).build();
} else {
return failed(this).feedback("idor.view.profile.close1").build();
}
} else {
return failed(this).feedback("idor.view.profile.close2").build();
}
}
return failed(this).build();
}
}

View File

@@ -0,0 +1,65 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.idor;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.session.UserSessionData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@Slf4j
public class IDORViewOwnProfile {
@Autowired
UserSessionData userSessionData;
@GetMapping(path = {"/IDOR/own", "/IDOR/profile"}, produces = {"application/json"})
@ResponseBody
public Map<String, Object> invoke() {
Map<String,Object> details = new HashMap<>();
try {
if (userSessionData.getValue("idor-authenticated-as").equals("tom")) {
//going to use session auth to view this one
String authUserId = (String)userSessionData.getValue("idor-authenticated-user-id");
UserProfile userProfile = new UserProfile(authUserId);
details.put("userId",userProfile.getUserId());
details.put("name",userProfile.getName());
details.put("color",userProfile.getColor());
details.put("size",userProfile.getSize());
details.put("role",userProfile.getRole());
} else {
details.put("error","You do not have privileges to view the profile. Authenticate as tom first please.");
}
}catch (Exception ex) {
log.error("something went wrong", ex.getMessage());
}
return details;
}
}

View File

@@ -0,0 +1,66 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.idor;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.session.UserSessionData;
import org.springframework.beans.factory.annotation.Autowired;
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;
@RestController
@AssignmentHints({"idor.hints.ownProfileAltUrl1", "idor.hints.ownProfileAltUrl2", "idor.hints.ownProfileAltUrl3"})
public class IDORViewOwnProfileAltUrl extends AssignmentEndpoint {
@Autowired
UserSessionData userSessionData;
@PostMapping("/IDOR/profile/alt-path")
@ResponseBody
public AttackResult completed(@RequestParam String url) {
try {
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");
//don't care about http://localhost:8080 ... just want WebGoat/
String[] urlParts = url.split("/");
if (urlParts[0].equals("WebGoat") && urlParts[1].equals("IDOR") && urlParts[2].equals("profile") && urlParts[3].equals(authUserId)) {
UserProfile userProfile = new UserProfile(authUserId);
return success(this).feedback("idor.view.own.profile.success").output(userProfile.profileToMap().toString()).build();
} else {
return failed(this).feedback("idor.view.own.profile.failure1").build();
}
} else {
return failed(this).feedback("idor.view.own.profile.failure2").build();
}
} catch (Exception ex) {
return failed(this).feedback("an error occurred with your request").build();
}
}
}

View File

@@ -0,0 +1,136 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.idor;
import java.util.HashMap;
import java.util.Map;
/**
* Created by jason on 1/5/17.
*/
public class UserProfile {
private String userId;
private String name;
private String color;
private String size;
private boolean isAdmin;
private int role;
public UserProfile() {}
public UserProfile(String id) {
setProfileFromId(id);
}
//
private void setProfileFromId(String id) {
// emulate look up from database
if (id.equals("2342384")) {
this.userId = id;
this.color = "yellow";
this.name = "Tom Cat";
this.size = "small";
this.isAdmin = false;
this.role = 3;
} else if (id.equals("2342388")) {
this.userId = id;
this.color = "brown";
this.name = "Buffalo Bill";
this.size = "large";
this.isAdmin = false;
this.role = 3;
} else {
//not found
}
}
public Map <String,Object> profileToMap () {
Map<String,Object> profileMap = new HashMap<>();
profileMap.put("userId", this.userId);
profileMap.put("name", this.name);
profileMap.put("color", this.color);
profileMap.put("size", this.size);
profileMap.put("role", this.role);
return profileMap;
}
public String toHTMLString() {
String htmlBreak = "<br/>";
return "userId" + this.userId + htmlBreak +
"name" + this.name + htmlBreak +
"size" + this.size + htmlBreak +
"role" + this.role + htmlBreak +
"isAdmin" + this.isAdmin;
}
//
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
public boolean isAdmin() {
return isAdmin;
}
public void setAdmin(boolean admin) {
isAdmin = admin;
}
public int getRole() {
return role;
}
public void setRole(int role) {
this.role = role;
}
}

View File

@@ -0,0 +1,47 @@
package org.owasp.webgoat.lessons.insecure_login;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* ************************************************************************************************
* 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 - 2014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author WebGoat
* @version $Id: $Id
* @since October 12, 2016
*/
@Component
public class InsecureLogin extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.INSECURE_COMMUNICATION;
}
@Override
public String getTitle() {
return "insecure-login.title";
}
}

View File

@@ -0,0 +1,47 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.insecure_login;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@RestController
public class InsecureLoginTask extends AssignmentEndpoint {
@PostMapping("/InsecureLogin/task")
@ResponseBody
public AttackResult completed(@RequestParam String username, @RequestParam String password) {
if ("CaptainJack".equals(username) && "BlackPearl".equals(password)) {
return success(this).build();
}
return failed(this).build();
}
@PostMapping("/InsecureLogin/login")
@ResponseStatus(HttpStatus.ACCEPTED)
public void login() {
//only need to exists as the JS needs to call an existing endpoint
}
}

View File

@@ -0,0 +1,45 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.jwt;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* @author nbaars
* @since 3/22/17.
*/
@Component
public class JWT extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.AUTHENTICATION;
}
@Override
public String getTitle() {
return "jwt.title";
}
}

View File

@@ -0,0 +1,22 @@
package org.owasp.webgoat.lessons.jwt;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
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;
@RestController
public class JWTDecodeEndpoint extends AssignmentEndpoint {
@PostMapping("/JWT/decode")
@ResponseBody
public AttackResult decode(@RequestParam("jwt-encode-user") String user) {
if ("user".equals(user)) {
return success(this).build();
} else {
return failed(this).build();
}
}
}

View File

@@ -0,0 +1,122 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.jwt;
import io.jsonwebtoken.*;
import io.jsonwebtoken.impl.TextCodec;
import org.apache.commons.lang3.StringUtils;
import org.owasp.webgoat.container.LessonDataSource;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.web.bind.annotation.*;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* <pre>
* {
* "typ": "JWT",
* "kid": "webgoat_key",
* "alg": "HS256"
* }
* {
* "iss": "WebGoat Token Builder",
* "iat": 1524210904,
* "exp": 1618905304,
* "aud": "webgoat.org",
* "sub": "jerry@webgoat.com",
* "username": "Jerry",
* "Email": "jerry@webgoat.com",
* "Role": [
* "Cat"
* ]
* }
* </pre>
*
* @author nbaars
* @since 4/23/17.
*/
@RestController
@AssignmentHints({"jwt-final-hint1", "jwt-final-hint2", "jwt-final-hint3", "jwt-final-hint4", "jwt-final-hint5", "jwt-final-hint6"})
public class JWTFinalEndpoint extends AssignmentEndpoint {
private final LessonDataSource dataSource;
private JWTFinalEndpoint(LessonDataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/JWT/final/follow/{user}")
public @ResponseBody
String follow(@PathVariable("user") String user) {
if ("Jerry".equals(user)) {
return "Following yourself seems redundant";
} else {
return "You are now following Tom";
}
}
@PostMapping("/JWT/final/delete")
public @ResponseBody
AttackResult resetVotes(@RequestParam("token") String token) {
if (StringUtils.isEmpty(token)) {
return failed(this).feedback("jwt-invalid-token").build();
} else {
try {
final String[] errorMessage = {null};
Jwt jwt = Jwts.parser().setSigningKeyResolver(new SigningKeyResolverAdapter() {
@Override
public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) {
final String kid = (String) header.get("kid");
try (var connection = dataSource.getConnection()) {
ResultSet rs = connection.createStatement().executeQuery("SELECT key FROM jwt_keys WHERE id = '" + kid + "'");
while (rs.next()) {
return TextCodec.BASE64.decode(rs.getString(1));
}
} catch (SQLException e) {
errorMessage[0] = e.getMessage();
}
return null;
}
}).parseClaimsJws(token);
if (errorMessage[0] != null) {
return failed(this).output(errorMessage[0]).build();
}
Claims claims = (Claims) jwt.getBody();
String username = (String) claims.get("username");
if ("Jerry".equals(username)) {
return failed(this).feedback("jwt-final-jerry-account").build();
}
if ("Tom".equals(username)) {
return success(this).build();
} else {
return failed(this).feedback("jwt-final-not-tom").build();
}
} catch (JwtException e) {
return failed(this).feedback("jwt-invalid-token").output(e.toString()).build();
}
}
}
}

View File

@@ -0,0 +1,49 @@
package org.owasp.webgoat.lessons.jwt;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.web.bind.annotation.GetMapping;
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;
@RestController
public class JWTQuiz extends AssignmentEndpoint {
private final String[] solutions = {"Solution 1", "Solution 2"};
private final boolean[] guesses = new boolean[solutions.length];
@PostMapping("/JWT/quiz")
@ResponseBody
public AttackResult completed(@RequestParam String[] question_0_solution, @RequestParam String[] question_1_solution) {
int correctAnswers = 0;
String[] givenAnswers = {question_0_solution[0], question_1_solution[0]};
for (int i = 0; i < solutions.length; i++) {
if (givenAnswers[i].contains(solutions[i])) {
// answer correct
correctAnswers++;
guesses[i] = true;
} else {
// answer incorrect
guesses[i] = false;
}
}
if (correctAnswers == solutions.length) {
return success(this).build();
} else {
return failed(this).build();
}
}
@GetMapping("/JWT/quiz")
@ResponseBody
public boolean[] getResults() {
return this.guesses;
}
}

View File

@@ -0,0 +1,146 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.jwt;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Header;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import org.apache.commons.lang3.RandomStringUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static org.springframework.http.ResponseEntity.ok;
/**
* @author nbaars
* @since 4/23/17.
*/
@RestController
@AssignmentHints({"jwt-refresh-hint1", "jwt-refresh-hint2", "jwt-refresh-hint3", "jwt-refresh-hint4"})
public class JWTRefreshEndpoint extends AssignmentEndpoint {
public static final String PASSWORD = "bm5nhSkxCXZkKRy4";
private static final String JWT_PASSWORD = "bm5n3SkxCX4kKRy4";
private static final List<String> validRefreshTokens = new ArrayList<>();
@PostMapping(value = "/JWT/refresh/login", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity follow(@RequestBody(required = false) Map<String, Object> json) {
if (json == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
String user = (String) json.get("user");
String password = (String) json.get("password");
if ("Jerry".equalsIgnoreCase(user) && PASSWORD.equals(password)) {
return ok(createNewTokens(user));
}
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
private Map<String, Object> createNewTokens(String user) {
Map<String, Object> claims = new HashMap<>();
claims.put("admin", "false");
claims.put("user", user);
String token = Jwts.builder()
.setIssuedAt(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toDays(10)))
.setClaims(claims)
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, JWT_PASSWORD)
.compact();
Map<String, Object> tokenJson = new HashMap<>();
String refreshToken = RandomStringUtils.randomAlphabetic(20);
validRefreshTokens.add(refreshToken);
tokenJson.put("access_token", token);
tokenJson.put("refresh_token", refreshToken);
return tokenJson;
}
@PostMapping("/JWT/refresh/checkout")
@ResponseBody
public ResponseEntity<AttackResult> checkout(@RequestHeader(value = "Authorization", required = false) String token) {
if (token == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
try {
Jwt jwt = Jwts.parser().setSigningKey(JWT_PASSWORD).parse(token.replace("Bearer ", ""));
Claims claims = (Claims) jwt.getBody();
String user = (String) claims.get("user");
if ("Tom".equals(user)) {
return ok(success(this).build());
}
return ok(failed(this).feedback("jwt-refresh-not-tom").feedbackArgs(user).build());
} catch (ExpiredJwtException e) {
return ok(failed(this).output(e.getMessage()).build());
} catch (JwtException e) {
return ok(failed(this).feedback("jwt-invalid-token").build());
}
}
@PostMapping("/JWT/refresh/newToken")
@ResponseBody
public ResponseEntity newToken(@RequestHeader(value = "Authorization", required = false) String token,
@RequestBody(required = false) Map<String, Object> json) {
if (token == null || json == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
String user;
String refreshToken;
try {
Jwt<Header, Claims> jwt = Jwts.parser().setSigningKey(JWT_PASSWORD).parse(token.replace("Bearer ", ""));
user = (String) jwt.getBody().get("user");
refreshToken = (String) json.get("refresh_token");
} catch (ExpiredJwtException e) {
user = (String) e.getClaims().get("user");
refreshToken = (String) json.get("refresh_token");
}
if (user == null || refreshToken == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
} else if (validRefreshTokens.contains(refreshToken)) {
validRefreshTokens.remove(refreshToken);
return ok(createNewTokens(user));
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}
}

View File

@@ -0,0 +1,95 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.jwt;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.TextCodec;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.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 org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.time.Instant;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Random;
/**
* @author nbaars
* @since 4/23/17.
*/
@RestController
@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 JWT_SECRET = TextCodec.BASE64.encode(SECRETS[new Random().nextInt(SECRETS.length)]);
private static final String WEBGOAT_USER = "WebGoat";
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)
@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();
}
@PostMapping("/JWT/secret")
@ResponseBody
public AttackResult login(@RequestParam String token) {
try {
Jwt jwt = Jwts.parser().setSigningKey(JWT_SECRET).parseClaimsJws(token);
Claims claims = (Claims) jwt.getBody();
if (!claims.keySet().containsAll(expectedClaims)) {
return failed(this).feedback("jwt-secret-claims-missing").build();
} else {
String user = (String) claims.get("username");
if (WEBGOAT_USER.equalsIgnoreCase(user)) {
return success(this).build();
} else {
return failed(this).feedback("jwt-secret-incorrect-user").feedbackArgs(user).build();
}
}
} catch (Exception e) {
return failed(this).feedback("jwt-invalid-token").output(e.getMessage()).build();
}
}
}

View File

@@ -0,0 +1,184 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.jwt;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.impl.TextCodec;
import org.apache.commons.lang3.StringUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.lessons.jwt.votes.Views;
import org.owasp.webgoat.lessons.jwt.votes.Vote;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.MappingJacksonValue;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import javax.servlet.http.Cookie;
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;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toList;
/**
* @author nbaars
* @since 4/23/17.
*/
@RestController
@AssignmentHints({"jwt-change-token-hint1", "jwt-change-token-hint2", "jwt-change-token-hint3", "jwt-change-token-hint4", "jwt-change-token-hint5"})
public class JWTVotesEndpoint extends AssignmentEndpoint {
public static final String JWT_PASSWORD = TextCodec.BASE64.encode("victory");
private static String validUsers = "TomJerrySylvester";
private static int totalVotes = 38929;
private Map<String, Vote> votes = new HashMap<>();
@PostConstruct
public void initVotes() {
votes.put("Admin lost password", new Vote("Admin lost password",
"In this challenge you will need to help the admin and find the password in order to login",
"challenge1-small.png", "challenge1.png", 36000, totalVotes));
votes.put("Vote for your favourite",
new Vote("Vote for your favourite",
"In this challenge ...",
"challenge5-small.png", "challenge5.png", 30000, totalVotes));
votes.put("Get it for free",
new Vote("Get it for free",
"The objective for this challenge is to buy a Samsung phone for free.",
"challenge2-small.png", "challenge2.png", 20000, totalVotes));
votes.put("Photo comments",
new Vote("Photo comments",
"n this challenge you can comment on the photo you will need to find the flag somewhere.",
"challenge3-small.png", "challenge3.png", 10000, totalVotes));
}
@GetMapping("/JWT/votings/login")
public void login(@RequestParam("user") String user, HttpServletResponse response) {
if (validUsers.contains(user)) {
Claims claims = Jwts.claims().setIssuedAt(Date.from(Instant.now().plus(Duration.ofDays(10))));
claims.put("admin", "false");
claims.put("user", user);
String token = Jwts.builder()
.setClaims(claims)
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, JWT_PASSWORD)
.compact();
Cookie cookie = new Cookie("access_token", token);
response.addCookie(cookie);
response.setStatus(HttpStatus.OK.value());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
} else {
Cookie cookie = new Cookie("access_token", "");
response.addCookie(cookie);
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
}
}
@GetMapping("/JWT/votings")
@ResponseBody
public MappingJacksonValue getVotes(@CookieValue(value = "access_token", required = false) String accessToken) {
MappingJacksonValue value = new MappingJacksonValue(votes.values().stream().sorted(comparingLong(Vote::getAverage).reversed()).collect(toList()));
if (StringUtils.isEmpty(accessToken)) {
value.setSerializationView(Views.GuestView.class);
} else {
try {
Jwt jwt = Jwts.parser().setSigningKey(JWT_PASSWORD).parse(accessToken);
Claims claims = (Claims) jwt.getBody();
String user = (String) claims.get("user");
if ("Guest".equals(user) || !validUsers.contains(user)) {
value.setSerializationView(Views.GuestView.class);
} else {
value.setSerializationView(Views.UserView.class);
}
} catch (JwtException e) {
value.setSerializationView(Views.GuestView.class);
}
}
return value;
}
@PostMapping(value = "/JWT/votings/{title}")
@ResponseBody
@ResponseStatus(HttpStatus.ACCEPTED)
public ResponseEntity<?> vote(@PathVariable String title, @CookieValue(value = "access_token", required = false) String accessToken) {
if (StringUtils.isEmpty(accessToken)) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
} else {
try {
Jwt jwt = Jwts.parser().setSigningKey(JWT_PASSWORD).parse(accessToken);
Claims claims = (Claims) jwt.getBody();
String user = (String) claims.get("user");
if (!validUsers.contains(user)) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
} else {
ofNullable(votes.get(title)).ifPresent(v -> v.incrementNumberOfVotes(totalVotes));
return ResponseEntity.accepted().build();
}
} catch (JwtException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}
}
@PostMapping("/JWT/votings")
@ResponseBody
public AttackResult resetVotes(@CookieValue(value = "access_token", required = false) String accessToken) {
if (StringUtils.isEmpty(accessToken)) {
return failed(this).feedback("jwt-invalid-token").build();
} else {
try {
Jwt jwt = Jwts.parser().setSigningKey(JWT_PASSWORD).parse(accessToken);
Claims claims = (Claims) jwt.getBody();
boolean isAdmin = Boolean.valueOf((String) claims.get("admin"));
if (!isAdmin) {
return failed(this).feedback("jwt-only-admin").build();
} else {
votes.values().forEach(vote -> vote.reset());
return success(this).build();
}
} catch (JwtException e) {
return failed(this).feedback("jwt-invalid-token").output(e.toString()).build();
}
}
}
}

View File

@@ -0,0 +1,13 @@
package org.owasp.webgoat.lessons.jwt.votes;
/**
* @author nbaars
* @since 4/30/17.
*/
public class Views {
public interface GuestView {
}
public interface UserView extends GuestView {
}
}

View File

@@ -0,0 +1,72 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.jwt.votes;
import com.fasterxml.jackson.annotation.JsonView;
import lombok.Getter;
/**
* @author nbaars
* @since 5/2/17.
*/
@Getter
public class Vote {
@JsonView(Views.GuestView.class)
private final String title;
@JsonView(Views.GuestView.class)
private final String information;
@JsonView(Views.GuestView.class)
private final String imageSmall;
@JsonView(Views.GuestView.class)
private final String imageBig;
@JsonView(Views.UserView.class)
private int numberOfVotes;
@JsonView(Views.UserView.class)
private boolean votingAllowed = true;
@JsonView(Views.UserView.class)
private long average = 0;
public Vote(String title, String information, String imageSmall, String imageBig, int numberOfVotes, int totalVotes) {
this.title = title;
this.information = information;
this.imageSmall = imageSmall;
this.imageBig = imageBig;
this.numberOfVotes = numberOfVotes;
this.average = calculateStars(totalVotes);
}
public void incrementNumberOfVotes(int totalVotes) {
this.numberOfVotes = this.numberOfVotes + 1;
this.average = calculateStars(totalVotes);
}
public void reset() {
this.numberOfVotes = 1;
this.average = 1;
}
private long calculateStars(int totalVotes) {
return Math.round(((double) numberOfVotes / (double) totalVotes) * 4);
}
}

View File

@@ -0,0 +1,41 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.lesson_template;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
@Component
public class LessonTemplate extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.GENERAL;
}
@Override
public String getTitle() {
return "lesson-template.title";
}
}

View File

@@ -0,0 +1,90 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.lesson_template;
import lombok.AllArgsConstructor;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.session.UserSessionData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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;
import java.util.List;
/**
* Created by jason on 1/5/17.
*/
@RestController
@AssignmentHints({"lesson-template.hints.1", "lesson-template.hints.2", "lesson-template.hints.3"})
public class SampleAttack extends AssignmentEndpoint {
String secretValue = "secr37Value";
//UserSessionData is bound to session and can be used to persist data across multiple assignments
@Autowired
UserSessionData userSessionData;
@PostMapping("/lesson-template/sample-attack")
@ResponseBody
public AttackResult completed(@RequestParam("param1") String param1, @RequestParam("param2") String param2) {
if (userSessionData.getValue("some-value") != null) {
// do any session updating you want here ... or not, just comment/example here
//return failed().feedback("lesson-template.sample-attack.failure-2").build());
}
//overly simple example for success. See other existing lesssons for ways to detect 'success' or 'failure'
if (secretValue.equals(param1)) {
return success(this)
.output("Custom Output ...if you want, for success")
.feedback("lesson-template.sample-attack.success")
.build();
//lesson-template.sample-attack.success is defined in src/main/resources/i18n/WebGoatLabels.properties
}
// else
return failed(this)
.feedback("lesson-template.sample-attack.failure-2")
.output("Custom output for this failure scenario, usually html that will get rendered directly ... yes, you can self-xss if you want")
.build();
}
@GetMapping("lesson-template/shop/{user}")
@ResponseBody
public List<Item> getItemsInBasket(@PathVariable("user") String user) {
return List.of(new Item("WG-1", "WebGoat promo", 12.0), new Item("WG-2", "WebGoat sticker", 0.00));
}
@AllArgsConstructor
private class Item {
private String number;
private String description;
private double price;
}
}

View File

@@ -0,0 +1,66 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.logging;
import org.apache.logging.log4j.util.Strings;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
import javax.annotation.PostConstruct;
import java.util.Base64;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
@RestController
public class LogBleedingTask extends AssignmentEndpoint {
Logger log = LoggerFactory.getLogger(this.getClass().getName());
private String password;
@PostConstruct
public void generatePassword(){
password = UUID.randomUUID().toString();
log.info("Password for admin: {}", Base64.getEncoder().encodeToString(password.getBytes(StandardCharsets.UTF_8)));
}
@PostMapping("/LogSpoofing/log-bleeding")
@ResponseBody
public AttackResult completed(@RequestParam String username, @RequestParam String password) {
if (Strings.isEmpty(username) || Strings.isEmpty(password)) {
return failed(this).output("Please provide username (Admin) and password").build();
}
if (username.equals("Admin") && password.equals(this.password)) {
return success(this).build();
}
return failed(this).build();
}
}

View File

@@ -0,0 +1,47 @@
package org.owasp.webgoat.lessons.logging;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* ************************************************************************************************
* 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 - 2014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author WebGoat
* @version $Id: $Id
* @since October 12, 2016
*/
@Component
public class LogSpoofing extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.INSECURE_CONFIGURATION;
}
@Override
public String getTitle() {
return "logging.title";
}
}

View File

@@ -0,0 +1,51 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.logging;
import org.apache.logging.log4j.util.Strings;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
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;
@RestController
public class LogSpoofingTask extends AssignmentEndpoint {
@PostMapping("/LogSpoofing/log-spoofing")
@ResponseBody
public AttackResult completed(@RequestParam String username, @RequestParam String password) {
if (Strings.isEmpty(username)) {
return failed(this).output(username).build();
}
username = username.replace("\n", "<br/>");
if (username.contains("<p>") || username.contains("<div>")) {
return failed(this).output("Try to think of something simple ").build();
}
if (username.indexOf("<br/>") < username.indexOf("admin")) {
return success(this).output(username).build();
}
return failed(this).output(username).build();
}
}

View File

@@ -0,0 +1,62 @@
package org.owasp.webgoat.lessons.missing_ac;
import lombok.Getter;
import java.nio.charset.StandardCharsets;
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 - 2014 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>
*/
@Getter
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(User user, String passwordSalt) {
this.username = user.getUsername();
this.admin = user.isAdmin();
try {
this.userHash = genUserHash(user.getUsername(), user.getPassword(), passwordSalt);
} catch (Exception ex) {
this.userHash = "Error generating user hash";
}
}
protected String genUserHash(String username, String password, String passwordSalt) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-256");
// salting is good, but static & too predictable ... short too for a salt
String salted = password + passwordSalt + username;
//md.update(salted.getBytes("UTF-8")); // Change this to "UTF-16" if needed
byte[] hash = md.digest(salted.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(hash);
}
}

View File

@@ -0,0 +1,45 @@
package org.owasp.webgoat.lessons.missing_ac;
import org.owasp.webgoat.container.LessonDataSource;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
@Component
public class MissingAccessControlUserRepository {
private final NamedParameterJdbcTemplate jdbcTemplate;
private final RowMapper<User> mapper = (rs, rowNum) -> new User(rs.getString("username"), rs.getString("password"), rs.getBoolean("admin"));
public MissingAccessControlUserRepository(LessonDataSource lessonDataSource) {
this.jdbcTemplate = new NamedParameterJdbcTemplate(lessonDataSource);
}
public List<User> findAllUsers() {
return jdbcTemplate.query("select username, password, admin from access_control_users", mapper);
}
public User findByUsername(String username) {
var users = jdbcTemplate.query("select username, password, admin from access_control_users where username=:username",
new MapSqlParameterSource().addValue("username", username),
mapper);
if (CollectionUtils.isEmpty(users)) {
return null;
}
return users.get(0);
}
public User save(User user) {
jdbcTemplate.update("INSERT INTO access_control_users(username, password, admin) VALUES(:username,:password,:admin)",
new MapSqlParameterSource()
.addValue("username", user.getUsername())
.addValue("password", user.getPassword())
.addValue("admin", user.isAdmin()));
return user;
}
}

View File

@@ -0,0 +1,44 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.missing_ac;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
@Component
public class MissingFunctionAC extends Lesson {
public static final String PASSWORD_SALT_SIMPLE = "DeliberatelyInsecure1234";
public static final String PASSWORD_SALT_ADMIN = "DeliberatelyInsecure1235";
@Override
public Category getDefaultCategory() {
return Category.ACCESS_CONTROL;
}
@Override
public String getTitle() {
return "missing-function-access-control.title";
}
}

View File

@@ -0,0 +1,61 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.missing_ac;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
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.
*/
@RestController
@AssignmentHints({"access-control.hidden-menus.hint1","access-control.hidden-menus.hint2","access-control.hidden-menus.hint3"})
public class MissingFunctionACHiddenMenus extends AssignmentEndpoint {
@PostMapping(path = "/access-control/hidden-menu", produces = {"application/json"})
@ResponseBody
public AttackResult completed(String hiddenMenu1, String hiddenMenu2) {
if (hiddenMenu1.equals("Users") && hiddenMenu2.equals("Config")) {
return success(this)
.output("")
.feedback("access-control.hidden-menus.success")
.build();
}
if (hiddenMenu1.equals("Config") && hiddenMenu2.equals("Users")) {
return failed(this)
.output("")
.feedback("access-control.hidden-menus.close")
.build();
}
return failed(this)
.feedback("access-control.hidden-menus.failure")
.output("")
.build();
}
}

View File

@@ -0,0 +1,103 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.missing_ac;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.session.WebSession;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
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.servlet.ModelAndView;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static org.owasp.webgoat.lessons.missing_ac.MissingFunctionAC.PASSWORD_SALT_ADMIN;
import static org.owasp.webgoat.lessons.missing_ac.MissingFunctionAC.PASSWORD_SALT_SIMPLE;
/**
* Created by jason on 1/5/17.
*/
@Controller
@AllArgsConstructor
@Slf4j
public class MissingFunctionACUsers {
private final MissingAccessControlUserRepository userRepository;
private final WebSession webSession;
@GetMapping(path = {"access-control/users"})
public ModelAndView listUsers() {
ModelAndView model = new ModelAndView();
model.setViewName("list_users");
List<User> allUsers = userRepository.findAllUsers();
model.addObject("numUsers", allUsers.size());
//add display user objects in place of direct users
List<DisplayUser> displayUsers = new ArrayList<>();
for (User user : allUsers) {
displayUsers.add(new DisplayUser(user, PASSWORD_SALT_SIMPLE));
}
model.addObject("allUsers", displayUsers);
return model;
}
@GetMapping(path = {"access-control/users"}, consumes = "application/json")
@ResponseBody
public ResponseEntity<List<DisplayUser>> usersService() {
return ResponseEntity.ok(userRepository.findAllUsers().stream().map(user -> new DisplayUser(user, PASSWORD_SALT_SIMPLE)).collect(Collectors.toList()));
}
@GetMapping(path = {"access-control/users-admin-fix"}, consumes = "application/json")
@ResponseBody
public ResponseEntity<List<DisplayUser>> usersFixed() {
var currentUser = userRepository.findByUsername(webSession.getUserName());
if (currentUser != null && currentUser.isAdmin()) {
return ResponseEntity.ok(userRepository.findAllUsers().stream().map(user -> new DisplayUser(user, PASSWORD_SALT_ADMIN)).collect(Collectors.toList()));
}
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
@PostMapping(path = {"access-control/users", "access-control/users-admin-fix"}, consumes = "application/json", produces = "application/json")
@ResponseBody
public User addUser(@RequestBody User newUser) {
try {
userRepository.save(newUser);
return newUser;
} catch (Exception ex) {
log.error("Error creating new User", ex);
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,54 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.missing_ac;
import lombok.RequiredArgsConstructor;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import static org.owasp.webgoat.lessons.missing_ac.MissingFunctionAC.PASSWORD_SALT_SIMPLE;
@RestController
@AssignmentHints({"access-control.hash.hint1", "access-control.hash.hint2", "access-control.hash.hint3", "access-control.hash.hint4", "access-control.hash.hint5"})
@RequiredArgsConstructor
public class MissingFunctionACYourHash extends AssignmentEndpoint {
private final MissingAccessControlUserRepository userRepository;
@PostMapping(path = "/access-control/user-hash", produces = {"application/json"})
@ResponseBody
public AttackResult simple(String userHash) {
User user = userRepository.findByUsername("Jerry");
DisplayUser displayUser = new DisplayUser(user, PASSWORD_SALT_SIMPLE);
if (userHash.equals(displayUser.getUserHash())) {
return success(this).feedback("access-control.hash.success").build();
} else {
return failed(this).build();
}
}
}

View File

@@ -0,0 +1,60 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.missing_ac;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import static org.owasp.webgoat.lessons.missing_ac.MissingFunctionAC.PASSWORD_SALT_ADMIN;
@RestController
@AssignmentHints({"access-control.hash.hint6", "access-control.hash.hint7",
"access-control.hash.hint8", "access-control.hash.hint9", "access-control.hash.hint10", "access-control.hash.hint11", "access-control.hash.hint12"})
public class MissingFunctionACYourHashAdmin extends AssignmentEndpoint {
private final MissingAccessControlUserRepository userRepository;
public MissingFunctionACYourHashAdmin(MissingAccessControlUserRepository userRepository) {
this.userRepository = userRepository;
}
@PostMapping(path = "/access-control/user-hash-fix", produces = {"application/json"})
@ResponseBody
public AttackResult admin(String userHash) {
//current user should be in the DB
//if not admin then return 403
var user = userRepository.findByUsername("Jerry");
var displayUser = new DisplayUser(user, PASSWORD_SALT_ADMIN);
if (userHash.equals(displayUser.getUserHash())) {
return success(this).feedback("access-control.hash.success").build();
} else {
return failed(this).feedback("access-control.hash.close").build();
}
}
}

View File

@@ -0,0 +1,15 @@
package org.owasp.webgoat.lessons.missing_ac;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String username;
private String password;
private boolean admin;
}

View File

@@ -0,0 +1,40 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.password_reset;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
@Component
public class PasswordReset extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.AUTHENTICATION;
}
@Override
public String getTitle() {
return "password-reset.title";
}
}

View File

@@ -0,0 +1,40 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.password_reset;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Builder
@Data
public class PasswordResetEmail implements Serializable {
private LocalDateTime time;
private String contents;
private String sender;
private String title;
private String recipient;
}

View File

@@ -0,0 +1,71 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.password_reset;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.http.MediaType;
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;
import java.util.HashMap;
import java.util.Map;
/**
* @author nbaars
* @since 8/20/17.
*/
@RestController
public class QuestionsAssignment extends AssignmentEndpoint {
private static final Map<String, String> COLORS = new HashMap<>();
static {
COLORS.put("admin", "green");
COLORS.put("jerry", "orange");
COLORS.put("tom", "purple");
COLORS.put("larry", "yellow");
COLORS.put("webgoat", "red");
}
@PostMapping(path = "/PasswordReset/questions", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@ResponseBody
public AttackResult passwordReset(@RequestParam Map<String, Object> json) {
String securityQuestion = (String) json.getOrDefault("securityQuestion", "");
String username = (String) json.getOrDefault("username", "");
if ("webgoat".equalsIgnoreCase(username.toLowerCase())) {
return failed(this).feedback("password-questions-wrong-user").build();
}
String validAnswer = COLORS.get(username.toLowerCase());
if (validAnswer == null) {
return failed(this).feedback("password-questions-unknown-user").feedbackArgs(username).build();
} else if (validAnswer.equals(securityQuestion)) {
return success(this).build();
}
return failed(this).build();
}
}

View File

@@ -0,0 +1,131 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.password_reset;
import com.google.common.collect.Maps;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.lessons.password_reset.resetlink.PasswordChangeForm;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
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;
import org.springframework.web.servlet.ModelAndView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author nbaars
* @since 8/20/17.
*/
@RestController
@AssignmentHints({"password-reset-hint1", "password-reset-hint2", "password-reset-hint3", "password-reset-hint4", "password-reset-hint5", "password-reset-hint6"})
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 = new HashMap<>();
static Map<String, String> usersToTomPassword = Maps.newHashMap();
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";
@PostMapping("/PasswordReset/reset/login")
@ResponseBody
public AttackResult login(@RequestParam String password, @RequestParam String email) {
if (TOM_EMAIL.equals(email)) {
String passwordTom = usersToTomPassword.getOrDefault(getWebSession().getUserName(), PASSWORD_TOM_9);
if (passwordTom.equals(PASSWORD_TOM_9)) {
return failed(this).feedback("login_failed").build();
} else if (passwordTom.equals(password)) {
return success(this).build();
}
}
return failed(this).feedback("login_failed.tom").build();
}
@GetMapping("/PasswordReset/reset/reset-password/{link}")
public ModelAndView resetPassword(@PathVariable(value = "link") String link, Model model) {
ModelAndView modelAndView = new ModelAndView();
if (ResetLinkAssignment.resetLinks.contains(link)) {
PasswordChangeForm form = new PasswordChangeForm();
form.setResetLink(link);
model.addAttribute("form", form);
modelAndView.addObject("form", form);
modelAndView.setViewName("password_reset"); //Display html page for changing password
} else {
modelAndView.setViewName("password_link_not_found");
}
return modelAndView;
}
@GetMapping("/PasswordReset/reset/change-password")
public ModelAndView illegalCall() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("password_link_not_found");
return modelAndView;
}
@PostMapping("/PasswordReset/reset/change-password")
public ModelAndView changePassword(@ModelAttribute("form") PasswordChangeForm form, BindingResult bindingResult) {
ModelAndView modelAndView = new ModelAndView();
if (!org.springframework.util.StringUtils.hasText(form.getPassword())) {
bindingResult.rejectValue("password", "not.empty");
}
if (bindingResult.hasErrors()) {
modelAndView.setViewName("password_reset");
return modelAndView;
}
if (!resetLinks.contains(form.getResetLink())) {
modelAndView.setViewName("password_link_not_found");
return modelAndView;
}
if (checkIfLinkIsFromTom(form.getResetLink())) {
usersToTomPassword.put(getWebSession().getUserName(), form.getPassword());
}
modelAndView.setViewName("lessons/password_reset/templates/success.html");
return modelAndView;
}
private boolean checkIfLinkIsFromTom(String resetLinkFromForm) {
String resetLink = userToTomResetLink.getOrDefault(getWebSession().getUserName(), "unknown");
return resetLink.equals(resetLinkFromForm);
}
}

View File

@@ -0,0 +1,104 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.password_reset;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
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;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import java.util.UUID;
/**
* Part of the password reset assignment. Used to send the e-mail.
*
* @author nbaars
* @since 8/20/17.
*/
@RestController
public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
private final RestTemplate restTemplate;
private String webWolfHost;
private String webWolfPort;
private final String webWolfMailURL;
public ResetLinkAssignmentForgotPassword(RestTemplate restTemplate,
@Value("${webwolf.host}") String webWolfHost,
@Value("${webwolf.port}") String webWolfPort,
@Value("${webwolf.mail.url}") String webWolfMailURL) {
this.restTemplate = restTemplate;
this.webWolfHost = webWolfHost;
this.webWolfPort = webWolfPort;
this.webWolfMailURL = webWolfMailURL;
}
@PostMapping("/PasswordReset/ForgotPassword/create-password-reset-link")
@ResponseBody
public AttackResult sendPasswordResetLink(@RequestParam String email, HttpServletRequest request) {
String resetLink = UUID.randomUUID().toString();
ResetLinkAssignment.resetLinks.add(resetLink);
String host = request.getHeader("host");
if (ResetLinkAssignment.TOM_EMAIL.equals(email) && (host.contains(webWolfPort) || host.contains(webWolfHost))) { //User indeed changed the host header.
ResetLinkAssignment.userToTomResetLink.put(getWebSession().getUserName(), resetLink);
fakeClickingLinkEmail(host, resetLink);
} else {
try {
sendMailToUser(email, host, resetLink);
} catch (Exception e) {
return failed(this).output("E-mail can't be send. please try again.").build();
}
}
return success(this).feedback("email.send").feedbackArgs(email).build();
}
private void sendMailToUser(String email, String host, String resetLink) {
int index = email.indexOf("@");
String username = email.substring(0, index == -1 ? email.length() : index);
PasswordResetEmail mail = PasswordResetEmail.builder()
.title("Your password reset link")
.contents(String.format(ResetLinkAssignment.TEMPLATE, host, resetLink))
.sender("password-reset@webgoat-cloud.net")
.recipient(username).build();
this.restTemplate.postForEntity(webWolfMailURL, mail, Object.class);
}
private void fakeClickingLinkEmail(String host, String resetLink) {
try {
HttpHeaders httpHeaders = new HttpHeaders();
HttpEntity httpEntity = new HttpEntity(httpHeaders);
new RestTemplate().exchange(String.format("http://%s/PasswordReset/reset/reset-password/%s", host, resetLink), HttpMethod.GET, httpEntity, Void.class);
} catch (Exception e) {
//don't care
}
}
}

View File

@@ -0,0 +1,85 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.password_reset;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.beans.factory.annotation.Autowired;
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;
import java.util.HashMap;
import java.util.Map;
import static java.util.Optional.of;
/**
* Assignment for picking a good security question.
*
* @author Tobias Melzer
* @since 11.12.18
*/
@RestController
public class SecurityQuestionAssignment extends AssignmentEndpoint {
@Autowired
private TriedQuestions triedQuestions;
private static Map<String, String> questions;
static {
questions = new HashMap<>();
questions.put("What is your favorite animal?", "The answer can easily be guessed and figured out through social media.");
questions.put("In what year was your mother born?", "Can be easily guessed.");
questions.put("What was the time you were born?", "This may first seem like a good question, but you most likely dont know the exact time, so it might be hard to remember.");
questions.put("What is the name of the person you first kissed?", "Can be figured out through social media, or even guessed by trying the most common names.");
questions.put("What was the house number and street name you lived in as a child?", "Answer can be figured out through social media, or worse it might be your current address.");
questions.put("In what town or city was your first full time job?", "In times of LinkedIn and Facebook, the answer can be figured out quite easily.");
questions.put("In what city were you born?", "Easy to figure out through social media.");
questions.put("What was the last name of your favorite teacher in grade three?", "Most people would probably not know the answer to that.");
questions.put("What is the name of a college/job you applied to but didn't attend?", "It might not be easy to remember and an hacker could just try some company's/colleges in your area.");
questions.put("What are the last 5 digits of your drivers license?", "Is subject to change, and the last digit of your driver license might follow a specific pattern. (For example your birthday).");
questions.put("What was your childhood nickname?", "Not all people had a nickname.");
questions.put("Who was your childhood hero?", "Most Heroes we had as a child where quite obvious ones, like Superman for example.");
questions.put("On which wrist do you were your watch?", "There are only to possible real answers, so really easy to guess.");
questions.put("What is your favorite color?", "Can easily be guessed.");
}
@PostMapping("/PasswordReset/SecurityQuestions")
@ResponseBody
public AttackResult completed(@RequestParam String question) {
var answer = of(questions.get(question));
if (answer.isPresent()) {
triedQuestions.incr(question);
if (triedQuestions.isComplete()) {
return success(this).output("<b>" + answer + "</b>").build();
}
}
return informationMessage(this)
.feedback("password-questions-one-successful")
.output(answer.orElse("Unknown question, please try again..."))
.build();
}
}

View File

@@ -0,0 +1,100 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.password_reset;
import org.apache.commons.lang3.StringUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
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;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.time.LocalDateTime;
import static java.util.Optional.ofNullable;
/**
* @author nbaars
* @since 8/20/17.
*/
@RestController
public class SimpleMailAssignment extends AssignmentEndpoint {
private final String webWolfURL;
private RestTemplate restTemplate;
public SimpleMailAssignment(RestTemplate restTemplate, @Value("${webwolf.mail.url}") String webWolfURL) {
this.restTemplate = restTemplate;
this.webWolfURL = webWolfURL;
}
@PostMapping(path = "/PasswordReset/simple-mail", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@ResponseBody
public AttackResult login(@RequestParam String email, @RequestParam String password) {
String emailAddress = ofNullable(email).orElse("unknown@webgoat.org");
String username = extractUsername(emailAddress);
if (username.equals(getWebSession().getUserName()) && StringUtils.reverse(username).equals(password)) {
return success(this).build();
} else {
return failed(this).feedbackArgs("password-reset-simple.password_incorrect").build();
}
}
@PostMapping(consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, value = "/PasswordReset/simple-mail/reset")
@ResponseBody
public AttackResult resetPassword(@RequestParam String emailReset) {
String email = ofNullable(emailReset).orElse("unknown@webgoat.org");
return sendEmail(extractUsername(email), email);
}
private String extractUsername(String email) {
int index = email.indexOf("@");
return email.substring(0, index == -1 ? email.length() : index);
}
private AttackResult sendEmail(String username, String email) {
if (username.equals(getWebSession().getUserName())) {
PasswordResetEmail mailEvent = PasswordResetEmail.builder()
.recipient(username)
.title("Simple e-mail assignment")
.time(LocalDateTime.now())
.contents("Thanks for resetting your password, your new password is: " + StringUtils.reverse(username))
.sender("webgoat@owasp.org")
.build();
try {
restTemplate.postForEntity(webWolfURL, mailEvent, Object.class);
} catch (RestClientException e) {
return informationMessage(this).feedback("password-reset-simple.email_failed").output(e.getMessage()).build();
}
return informationMessage(this).feedback("password-reset-simple.email_send").feedbackArgs(email).build();
} else {
return informationMessage(this).feedback("password-reset-simple.email_mismatch").feedbackArgs(username).build();
}
}
}

View File

@@ -0,0 +1,44 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* 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.
*
* 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.
*
* 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.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.password_reset;
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 = new HashSet<>();
public void incr(String question) {
answeredQuestions.add(question);
}
public boolean isComplete() {
return answeredQuestions.size() > 1;
}
}

Some files were not shown because too many files have changed in this diff Show More