diff --git a/webgoat-container/src/main/resources/application.properties b/webgoat-container/src/main/resources/application.properties index 431dbba99..6ccb8fa93 100644 --- a/webgoat-container/src/main/resources/application.properties +++ b/webgoat-container/src/main/resources/application.properties @@ -39,7 +39,7 @@ webgoat.default.language=en webwolf.host=${WEBWOLF_HOST:localhost} webwolf.port=${WEBWOLF_PORT:8081} webwolf.url=http://${webwolf.host}:${webwolf.port}/WebWolf -webworf.url.landingpage=http://${webwolf.host}:${webwolf.port}/landing +webwolf.url.landingpage=http://${webwolf.host}:${webwolf.port}/landing webwolf.url.mail=http://${webwolf.host}:${webwolf.port}/mail spring.jackson.serialization.indent_output=true diff --git a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/SolutionConstants.java b/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/SolutionConstants.java index 886565dc8..4f5c38eff 100644 --- a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/SolutionConstants.java +++ b/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/SolutionConstants.java @@ -15,6 +15,4 @@ public interface SolutionConstants { String PASSWORD_LARRY = "larryknows"; String JWT_PASSWORD = "victory"; String ADMIN_PASSWORD_LINK = "375afe1104f4a487a73823c50a9292a2"; - String PASSWORD_TOM_9 = "somethingVeryRandomWhichNoOneWillEverTypeInAsPasswordForTom"; - String TOM_EMAIL = "tom@webgoat-cloud.org"; } diff --git a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge9/Challenge9.java b/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge9/Challenge9.java deleted file mode 100644 index c13a6e4c8..000000000 --- a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge9/Challenge9.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.owasp.webgoat.plugin.challenge9; - -import com.google.common.collect.Lists; -import org.owasp.webgoat.lessons.Category; -import org.owasp.webgoat.lessons.NewLesson; - -import java.util.List; - -/** - * @author nbaars - * @since 3/21/17. - */ -public class Challenge9 extends NewLesson { - - @Override - public Category getDefaultCategory() { - return Category.CHALLENGE; - } - - @Override - public List getHints() { - return Lists.newArrayList(); - } - - @Override - public Integer getDefaultRanking() { - return 10; - } - - @Override - public String getTitle() { - return "challenge9.title"; - } - - @Override - public String getId() { - return "Challenge9"; - } -} diff --git a/webgoat-lessons/challenge/src/main/resources/html/Challenge9.html b/webgoat-lessons/challenge/src/main/resources/html/Challenge9.html deleted file mode 100644 index 49cc34ca9..000000000 --- a/webgoat-lessons/challenge/src/main/resources/html/Challenge9.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - -
-
- - -
-
- -
-
-
-

- - Account Access -

-
-
-
-
- @ - -
-
- - - - - -
-
- -

- - Forgot your password? - -

-
-
-
-
- -
-
-
- -
-
-
-
-
- -
-
- -
-
- -
- -
-
-
-
-
- - \ No newline at end of file diff --git a/webgoat-lessons/challenge/src/main/resources/js/challenge9.js b/webgoat-lessons/challenge/src/main/resources/js/challenge9.js deleted file mode 100644 index eccbd7d33..000000000 --- a/webgoat-lessons/challenge/src/main/resources/js/challenge9.js +++ /dev/null @@ -1,10 +0,0 @@ -$(document).ready(function() { - $('#login').click(function(e) { - e.preventDefault(); - $('div#form-login').toggle('500'); - }); - $('#forgot').click(function(e) { - e.preventDefault(); - $('div#form-login').toggle('500'); - }); -}); \ No newline at end of file diff --git a/webgoat-lessons/challenge/src/main/resources/lessonPlans/en/Challenge_9.adoc b/webgoat-lessons/challenge/src/main/resources/lessonPlans/en/Challenge_9.adoc deleted file mode 100644 index f2e2c1c9b..000000000 --- a/webgoat-lessons/challenge/src/main/resources/lessonPlans/en/Challenge_9.adoc +++ /dev/null @@ -1,3 +0,0 @@ -Tom always resets his password immediately after receiving the email with the link. -Try to reset the password of Tom (tom@webgoat-cloud.org) to your own choice and login as Tom with -that password. diff --git a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge9/PasswordChangeForm.java b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/resetlink/PasswordChangeForm.java similarity index 88% rename from webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge9/PasswordChangeForm.java rename to webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/resetlink/PasswordChangeForm.java index bfe2d3625..3c1afccd7 100644 --- a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge9/PasswordChangeForm.java +++ b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/resetlink/PasswordChangeForm.java @@ -1,4 +1,4 @@ -package org.owasp.webgoat.plugin.challenge9; +package org.owasp.webgoat.plugin.resetlink; import lombok.Getter; import lombok.Setter; diff --git a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge9/Assignment9.java b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/resetlink/ResetLinkAssignment.java similarity index 71% rename from webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge9/Assignment9.java rename to webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/resetlink/ResetLinkAssignment.java index 0ef786bf8..4b3fdfab2 100644 --- a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge9/Assignment9.java +++ b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/resetlink/ResetLinkAssignment.java @@ -1,22 +1,16 @@ -package org.owasp.webgoat.plugin.challenge9; +package org.owasp.webgoat.plugin.resetlink; -import com.beust.jcommander.internal.Lists; -import com.beust.jcommander.internal.Maps; import com.google.common.collect.EvictingQueue; -import lombok.extern.slf4j.Slf4j; +import com.google.common.collect.Maps; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AttackResult; -import org.owasp.webgoat.plugin.Email; -import org.owasp.webgoat.users.UserRepository; -import org.owasp.webgoat.users.WebGoatUser; -import org.springframework.beans.factory.annotation.Autowired; +import org.owasp.webgoat.plugin.PasswordResetEmail; 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.ui.Model; -import org.springframework.util.StringUtils; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; @@ -26,25 +20,23 @@ import java.time.LocalDateTime; import java.util.Map; import java.util.UUID; -import static org.owasp.webgoat.plugin.Flag.FLAGS; -import static org.owasp.webgoat.plugin.SolutionConstants.PASSWORD_TOM_9; -import static org.owasp.webgoat.plugin.SolutionConstants.TOM_EMAIL; import static org.springframework.web.bind.annotation.RequestMethod.POST; /** * @author nbaars - * @since 4/8/17. + * @since 8/20/17. */ -@AssignmentPath("/challenge/9") -@Slf4j -public class Assignment9 extends AssignmentEndpoint { +@AssignmentPath("/PasswordReset/reset") +public class ResetLinkAssignment extends AssignmentEndpoint { + private static final String PASSWORD_TOM_9 = "somethingVeryRandomWhichNoOneWillEverTypeInAsPasswordForTom"; + private static final String TOM_EMAIL = "tom@webgoat-cloud.org"; private static Map userToTomResetLink = Maps.newHashMap(); private static Map usersToTomPassword = Maps.newHashMap(); private static EvictingQueue resetLinks = EvictingQueue.create(1000); private static final String TEMPLATE = "Hi, you requested a password reset link, please use this " + - "link to reset your password." + + "link to reset your password." + "\n \n\n" + "If you did not request this password change you can ignore this message." + "\n" + @@ -52,12 +44,15 @@ public class Assignment9 extends AssignmentEndpoint { "\n\n" + "Kind regards, \nTeam WebGoat"; - @Autowired - private RestTemplate restTemplate; - @Autowired - private UserRepository userRepository; - @Value("${webwolf.url}") - private String webWolfURL; + private final RestTemplate restTemplate; + private final String webWolfMailURL; + private final String webwolfLandingURL; + + public ResetLinkAssignment(RestTemplate restTemplate, @Value("${webwolf.url.mail}") String webWolfMailURL, @Value("${webwolf.url.landingpage}") String webwolfLandingURL) { + this.restTemplate = restTemplate; + this.webWolfMailURL = webWolfMailURL; + this.webwolfLandingURL = webwolfLandingURL; + } @RequestMapping(method = POST, value = "/create-password-reset-link") @ResponseBody @@ -65,7 +60,7 @@ public class Assignment9 extends AssignmentEndpoint { String resetLink = UUID.randomUUID().toString(); resetLinks.add(resetLink); String host = request.getHeader("host"); - if (StringUtils.hasText(email)) { + if (org.springframework.util.StringUtils.hasText(email)) { if (email.equals(TOM_EMAIL) && host.contains("8081")) { //User indeed changed the host header. userToTomResetLink.put(getWebSession().getUserName(), resetLink); fakeClickingLinkEmail(cookie, host, resetLink); @@ -77,18 +72,15 @@ public class Assignment9 extends AssignmentEndpoint { } private void sendMailToUser(@RequestParam String email, String host, String resetLink) { - String username; - WebGoatUser webGoatUser = userRepository.findByUsername(email.substring(0, email.indexOf("@"))); - if (webGoatUser != null) { - username = webGoatUser.getUsername(); - Email mail = Email.builder() - .title("Your password reset link for challenge 9") - .contents(String.format(TEMPLATE, host, resetLink)) - .sender("password-reset@webgoat-cloud.net") - .recipient(username) - .time(LocalDateTime.now()).build(); - restTemplate.postForEntity(webWolfURL + "/WebWolf/mail", mail, Object.class); - } + 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(TEMPLATE, host, resetLink)) + .sender("password-reset@webgoat-cloud.net") + .recipient(username) + .time(LocalDateTime.now()).build(); + restTemplate.postForEntity(webWolfMailURL, mail, Object.class); } /** @@ -98,11 +90,9 @@ public class Assignment9 extends AssignmentEndpoint { */ private void fakeClickingLinkEmail(String cookie, String host, String resetLink) { try { - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.put(HttpHeaders.COOKIE, Lists.newArrayList("JSESSIONID=" + cookie)); HttpEntity httpEntity = new HttpEntity(httpHeaders); - new RestTemplate().exchange(String.format("http://%s/challenge/9/reset-password/%s", host, resetLink), HttpMethod.GET, httpEntity, Void.class); + 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 } @@ -116,7 +106,7 @@ public class Assignment9 extends AssignmentEndpoint { if (passwordTom.equals(PASSWORD_TOM_9)) { return failed().feedback("login_failed").build(); } else if (passwordTom.equals(password)) { - return success().feedback("challenge.solved").feedbackArgs(FLAGS.get(9)).build(); + return success().feedback("challenge.solved").feedbackArgs("test").build(); } } return failed().feedback("login_failed.tom").build(); @@ -137,7 +127,7 @@ public class Assignment9 extends AssignmentEndpoint { @PostMapping("/change-password") public String changePassword(@ModelAttribute("form") PasswordChangeForm form, BindingResult bindingResult) { - if (!StringUtils.hasText(form.getPassword())) { + if (!org.springframework.util.StringUtils.hasText(form.getPassword())) { bindingResult.rejectValue("password", "not.empty"); } if (bindingResult.hasErrors()) { @@ -156,6 +146,4 @@ public class Assignment9 extends AssignmentEndpoint { String resetLink = userToTomResetLink.getOrDefault(getWebSession().getUserName(), "unknown"); return resetLink.equals(resetLinkFromForm); } - } - diff --git a/webgoat-lessons/password-reset/src/main/resources/html/PasswordReset.html b/webgoat-lessons/password-reset/src/main/resources/html/PasswordReset.html index 4b5373a0f..d4a652c70 100644 --- a/webgoat-lessons/password-reset/src/main/resources/html/PasswordReset.html +++ b/webgoat-lessons/password-reset/src/main/resources/html/PasswordReset.html @@ -111,7 +111,8 @@
- +
@@ -130,5 +131,108 @@
+
+
+
+ +
+ +
+
+
+

+ + Account Access +

+
+
+
+
+ @ + +
+
+ + + + + +
+
+ +

+ + Forgot your password? + +

+
+
+
+
+ +
+
+
+ +
+
+
+
+
+ +
+
+ +
+
+ +
+ +
+
+
+
+
+ \ No newline at end of file diff --git a/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties index cb073b35a..5cc0406b1 100644 --- a/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties +++ b/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties @@ -7,3 +7,13 @@ password-reset-simple.email_mismatch=Of course you can send mail to user {0} how password-questions-wrong-user=You need to find a different user you are logging in with 'webgoat'. password-questions-unknown-user=User {0} is not a valid user. + +password-reset-no-user=Please supply a valid e-mail address. +password-reset-solved=Congratulations you solved the assignment, please type in the following code in the e-mail field: {0} +password-reset-not-solved=Sorry but you did not redirect the reset link to WebWolf + +password-reset-hint1=Try to send a password reset link to your own account at {user}@webgoat.org, you can read this e-mail in WebWolf. +password-reset-hint2=Look at the link, can you think how the server creates this link? +password-reset-hint3=Tom clicks all the links he receives in his mailbox, you can use the landing page in WebWolf to get the reset link... +password-reset-hint4=The link points to localhost:8080/PasswordReset/.... can you change the host to localhost:8081 +password-reset-hint5=Intercept the request and change the host header \ No newline at end of file diff --git a/webgoat-lessons/password-reset/src/main/resources/js/password-reset-simple.js b/webgoat-lessons/password-reset/src/main/resources/js/password-reset-simple.js index 0073c693b..bf374ac7f 100644 --- a/webgoat-lessons/password-reset/src/main/resources/js/password-reset-simple.js +++ b/webgoat-lessons/password-reset/src/main/resources/js/password-reset-simple.js @@ -7,4 +7,16 @@ $(document).ready(function() { e.preventDefault(); $('div#form-olvidado').toggle('500'); }); -}); \ No newline at end of file +}); + +function showPasswordReset() { + console.log("clicking") + $('#password-reset').show(); + $('#password-login').hide(); +} + +function showPassword() { + console.log("clicking") + $('#password-login').show(); + $('#password-reset').hide(); +} \ No newline at end of file diff --git a/webgoat-lessons/password-reset/src/main/resources/lessonPlans/en/PasswordReset_host_header.adoc b/webgoat-lessons/password-reset/src/main/resources/lessonPlans/en/PasswordReset_host_header.adoc index 46c8666ee..fa0261e73 100644 --- a/webgoat-lessons/password-reset/src/main/resources/lessonPlans/en/PasswordReset_host_header.adoc +++ b/webgoat-lessons/password-reset/src/main/resources/lessonPlans/en/PasswordReset_host_header.adoc @@ -12,6 +12,7 @@ The time out is necessary to restrict the attack window, having a link opens up == Assignment -In this assignment Tom uses the password reset functionality, can you try to find a way to e-mail the password -reset link to your own inbox at user@webwolf.org. Use WebWolf to read the email and paste the token in the box -below. +Tom always resets his password immediately after receiving the email with the link. +Try to reset the password of Tom (tom@webgoat-cloud.org) to your own choice and login as Tom with +that password. If you did submit is in the e-mail address and submit again. + diff --git a/webgoat-lessons/challenge/src/main/resources/templates/password_link_not_found.html b/webgoat-lessons/password-reset/src/main/resources/templates/password_link_not_found.html similarity index 100% rename from webgoat-lessons/challenge/src/main/resources/templates/password_link_not_found.html rename to webgoat-lessons/password-reset/src/main/resources/templates/password_link_not_found.html diff --git a/webgoat-lessons/challenge/src/main/resources/templates/password_reset.html b/webgoat-lessons/password-reset/src/main/resources/templates/password_reset.html similarity index 52% rename from webgoat-lessons/challenge/src/main/resources/templates/password_reset.html rename to webgoat-lessons/password-reset/src/main/resources/templates/password_reset.html index a0d073a09..28c7c2f58 100644 --- a/webgoat-lessons/challenge/src/main/resources/templates/password_reset.html +++ b/webgoat-lessons/password-reset/src/main/resources/templates/password_reset.html @@ -9,16 +9,8 @@
-
+ - - - - - - - -
@@ -26,14 +18,6 @@ name='password' th:value="*{password}"/> Password error
- - - - - - - -
diff --git a/webgoat-lessons/challenge/src/main/resources/templates/success.html b/webgoat-lessons/password-reset/src/main/resources/templates/success.html similarity index 100% rename from webgoat-lessons/challenge/src/main/resources/templates/success.html rename to webgoat-lessons/password-reset/src/main/resources/templates/success.html diff --git a/webwolf/src/main/java/org/owasp/webwolf/requests/WebWolfTraceRepository.java b/webwolf/src/main/java/org/owasp/webwolf/requests/WebWolfTraceRepository.java index 43a04b1af..d4d292290 100644 --- a/webwolf/src/main/java/org/owasp/webwolf/requests/WebWolfTraceRepository.java +++ b/webwolf/src/main/java/org/owasp/webwolf/requests/WebWolfTraceRepository.java @@ -20,6 +20,7 @@ import java.util.*; public class WebWolfTraceRepository implements TraceRepository { private final EvictingQueue traces = EvictingQueue.create(10000); + private List exclusionList = Lists.newArrayList("/WebWolf/mail","/WebWolf/files", "/login", "/favicon.ico", "/js/", "/webjars/", "/WebWolf/requests", "/css/"); @Override public List findAll() { @@ -33,11 +34,15 @@ public class WebWolfTraceRepository implements TraceRepository { return Lists.newArrayList(traces); } + private boolean isInExclusionList(String path) { + return exclusionList.stream().anyMatch(e -> path.contains(e)); + } + @Override public void add(Map map) { Optional host = getFromHeaders("host", map); String path = (String) map.getOrDefault("path", ""); - if (host.isPresent() && path.contains("/landing")) { + if (host.isPresent() && !isInExclusionList(path)) { traces.add(new Trace(new Date(), map)); } }