New lesson working

This commit is contained in:
Nanne Baars 2018-05-26 15:09:18 +02:00
parent eaf68d38c5
commit f8a7a61e85
16 changed files with 172 additions and 231 deletions

View File

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

View File

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

View File

@ -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<String> getHints() {
return Lists.newArrayList();
}
@Override
public Integer getDefaultRanking() {
return 10;
}
@Override
public String getTitle() {
return "challenge9.title";
}
@Override
public String getId() {
return "Challenge9";
}
}

View File

@ -1,109 +0,0 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:Challenge_9.adoc"></div>
<script th:src="@{/lesson_js/challenge9.js}" language="JavaScript"></script>
<div class="attack-container">
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<div class="container-fluid">
<div class="row">
<div class="col-md-6">
<h4 style="border-bottom: 1px solid #c5c5c5;">
<i class="glyphicon glyphicon-user"></i>
Account Access
</h4>
<div style="padding: 20px;" id="form-login">
<form id="login-form" class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/challenge/9/login"
enctype="application/json;charset=UTF-8" role="form">
<fieldset>
<div class="form-group input-group">
<span class="input-group-addon"> @ </span>
<input class="form-control" placeholder="Email" name="email" type="email"
required="" autofocus=""/>
</div>
<div class="form-group input-group">
<span class="input-group-addon">
<i class="glyphicon glyphicon-lock">
</i>
</span>
<input class="form-control" placeholder="Password" name="password" type="password"
value="" required=""/>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-block">
Access
</button>
<p class="help-block">
<a class="pull-right text-muted" href="#" id="login">
<small>Forgot your password?</small>
</a>
</p>
</div>
</fieldset>
</form>
</div>
<div style="display: none;" id="form-login">
<h4 class="">
Forgot your password?
</h4>
<form id="login-form" class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/challenge/9/create-password-reset-link"
enctype="application/json;charset=UTF-8" role="form">
<fieldset>
<span class="help-block">
Email address you use to log in to your account
<br/>
We'll send you an email with instructions to choose a new password.
</span>
<div class="form-group input-group">
<span class="input-group-addon">
@
</span>
<input class="form-control" placeholder="Email" name="email" type="email"
required=""/>
</div>
<button type="submit" class="btn btn-primary btn-block" id="btn-login">
Continue
</button>
<p class="help-block">
<a class="text-muted" href="#" id="forgot">
<small>Account Access</small>
</a>
</p>
</fieldset>
</form>
</div>
</div>
</div>
</div>
<br/>
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-flag-checkered" aria-hidden="true"
style="font-size:20px"></i></div>
<input type="text" class="form-control" id="flag" name="flag"
placeholder="a7179f89-906b-4fec-9d99-f15b796e7208"/>
</div>
<div class="input-group" style="margin-top: 10px">
<button type="submit" class="btn btn-primary">Submit flag</button>
</div>
</div>
</form>
<br/>
<div class="attack-feedback"></div>
<div class="attack-output"></div>
</div>
</div>
</html>

View File

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

View File

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

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.plugin.challenge9;
package org.owasp.webgoat.plugin.resetlink;
import lombok.Getter;
import lombok.Setter;

View File

@ -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<String, String> userToTomResetLink = Maps.newHashMap();
private static Map<String, String> 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 " +
"<a target='_blank' href='http://%s/WebGoat/challenge/9/reset-password/%s'>link</a> to reset your password." +
"<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" +
@ -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")
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(webWolfURL + "/WebWolf/mail", mail, Object.class);
}
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);
}
}

View File

@ -111,7 +111,8 @@
</div>
<div class="form-group">
<label>What is your favorite color?</label>
<input class="form-control" placeholder="Answer security question" type="text" name="securityQuestion"/>
<input class="form-control" placeholder="Answer security question" type="text"
name="securityQuestion"/>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-block"> Submit</button>
@ -130,5 +131,108 @@
</div>
</div>
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:PasswordReset_host_header.adoc"></div>
<div class="attack-container">
<img th:src="@{/images/wolf-enabled.png}" class="webwolf-enabled"/>
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<div class="container-fluid">
<div class="row">
<div class="col-md-3">
<h4 style="border-bottom: 1px solid #c5c5c5;">
<i class="glyphicon glyphicon-user"></i>
Account Access
</h4>
<div style="padding: 20px;" id="password-login">
<form id="login-form" class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/PasswordReset/reset/login"
enctype="application/json;charset=UTF-8" role="form">
<fieldset>
<div class="form-group input-group">
<span class="input-group-addon"> @ </span>
<input class="form-control" placeholder="Email" name="email" type="email"
required="" autofocus=""/>
</div>
<div class="form-group input-group">
<span class="input-group-addon">
<i class="glyphicon glyphicon-lock">
</i>
</span>
<input class="form-control" placeholder="Password" name="password" type="password"
value="" required=""/>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-block">
Access
</button>
<p class="help-block">
<a class="pull-right text-muted" href="#" onclick="showPasswordReset()">
<small>Forgot your password?</small>
</a>
</p>
</div>
</fieldset>
</form>
</div>
<div style="display: none;" id="password-reset">
<h4 class="">
Forgot your password?
</h4>
<form class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/PasswordReset/reset/create-password-reset-link"
enctype="application/json;charset=UTF-8" role="form">
<fieldset>
<span class="help-block">
Email address you use to log in to your account
<br/>
We'll send you an email with instructions to choose a new password.
</span>
<div class="form-group input-group">
<span class="input-group-addon">
@
</span>
<input class="form-control" placeholder="Email" name="email" type="email"
required=""/>
</div>
<button type="submit" class="btn btn-primary btn-block" id="btn-login">
Continue
</button>
<p class="help-block">
<a class="text-muted" href="#" onclick="showPassword()">
<small>Account Access</small>
</a>
</p>
</fieldset>
</form>
</div>
</div>
</div>
</div>
<br/>
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-flag-checkered" aria-hidden="true"
style="font-size:20px"></i></div>
<input type="text" class="form-control" id="flag" name="flag"
placeholder="a7179f89-906b-4fec-9d99-f15b796e7208"/>
</div>
<div class="input-group" style="margin-top: 10px">
<button type="submit" class="btn btn-primary">Submit flag</button>
</div>
</div>
</form>
<br/>
<div class="attack-feedback"></div>
<div class="attack-output"></div>
</div>
</div>
</html>

View File

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

View File

@ -8,3 +8,15 @@ $(document).ready(function() {
$('div#form-olvidado').toggle('500');
});
});
function showPasswordReset() {
console.log("clicking")
$('#password-reset').show();
$('#password-login').hide();
}
function showPassword() {
console.log("clicking")
$('#password-login').show();
$('#password-reset').hide();
}

View File

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

View File

@ -9,16 +9,8 @@
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-8 col-md-6 col-sm-offset-2 col-md-offset-3">
<form role="form" method="POST" action="/WebGoat/challenge/9/change-password" th:object="${form}">
<form role="form" method="POST" action="/WebGoat/PasswordReset/reset/change-password" th:object="${form}">
<h2 class="sign_up_title">Reset your password</h2>
<!--<div class="form-group" th:classappend="${#fields.hasErrors('email')}? 'has-error'">-->
<!--<div class="form-group">-->
<!--<label for="email" class="control-label">Email</label>-->
<!--<input autofocus="dummy_for_thymeleaf_parser" type="text" class="form-control"-->
<!--th:field="*{email}"-->
<!--id="email" placeholder="email" name='email'/>-->
<!--<span th:if="${#fields.hasErrors('email')}" th:errors="*{email}">Email error</span>-->
<!--</div>-->
<div class="form-group" th:classappend="${#fields.hasErrors('password')}? 'has-error'">
<input type="hidden" name="resetLink" th:field="*{resetLink}" />
<label for="password" class="control-label" th:text="#{password}">Password</label>
@ -26,14 +18,6 @@
name='password' th:value="*{password}"/>
<span th:if="${#fields.hasErrors('password')}" th:errors="*{password}">Password error</span>
</div>
<!---->
<!--<div class="form-group">-->
<!--<input type="email" required="" autofocus="" name="email" id="email" class="form-control input-lg" placeholder="Email"-->
<!--tabindex="4"/>-->
<!--<input type="newPassword" required="" autofocus="" name="newPassword" id="newPassword" class="form-control input-lg" placeholder="New password"-->
<!--tabindex="4"/>-->
<!--</div>-->
<div class="row">
<div class="col-xs-12 col-md-12">
<button type="submit" class="btn btn-success btn-block btn-lg">Save</button>

View File

@ -20,6 +20,7 @@ import java.util.*;
public class WebWolfTraceRepository implements TraceRepository {
private final EvictingQueue<Trace> traces = EvictingQueue.create(10000);
private List<String> exclusionList = Lists.newArrayList("/WebWolf/mail","/WebWolf/files", "/login", "/favicon.ico", "/js/", "/webjars/", "/WebWolf/requests", "/css/");
@Override
public List<Trace> 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<String, Object> map) {
Optional<String> 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));
}
}