fixed and improved first two jwt challenges

This commit is contained in:
Rene Zubcevic
2019-09-17 08:35:34 +02:00
committed by Nanne Baars
parent fb2e11fe11
commit 57e6a84cef
7 changed files with 191 additions and 18 deletions

View File

@ -6,15 +6,23 @@ import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.web.bind.annotation.ResponseBody;
import java.time.Instant;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Random;
/**
* @author nbaars
@ -24,10 +32,26 @@ import java.util.List;
@AssignmentHints({"jwt-secret-hint1", "jwt-secret-hint2", "jwt-secret-hint3"})
public class JWTSecretKeyEndpoint extends AssignmentEndpoint {
public static final String JWT_SECRET = TextCodec.BASE64.encode("victory");
public static final String[] SECRETS = {"victory","business","available", "shipping", "washington"};
public static final String JWT_SECRET = TextCodec.BASE64.encode(SECRETS[new Random().nextInt(SECRETS.length)]);
private static final String WEBGOAT_USER = "WebGoat";
private static final List<String> expectedClaims = Lists.newArrayList("iss", "iat", "exp", "aud", "sub", "username", "Email", "Role");
@RequestMapping(path="/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
@ResponseBody
public AttackResult login(@RequestParam String token) {
@ -46,6 +70,7 @@ public class JWTSecretKeyEndpoint extends AssignmentEndpoint {
}
}
} catch (Exception e) {
e.printStackTrace();
return trackProgress(failed().feedback("jwt-invalid-token").output(e.getMessage()).build());
}
}

View File

@ -38,13 +38,13 @@ import static java.util.stream.Collectors.toList;
@AssignmentPath("/JWT/votings")
@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 = Maps.newHashMap();
@PostConstruct
public void initVotes() {
votes.put("Admin lost password", new Vote("Admin lost password",
@ -109,7 +109,7 @@ public class JWTVotesEndpoint extends AssignmentEndpoint {
return value;
}
@PostMapping(value = "{title}")
@PostMapping(value = "/vote/{title}")
@ResponseBody
@ResponseStatus(HttpStatus.ACCEPTED)
public ResponseEntity<?> vote(@PathVariable String title, @CookieValue(value = "access_token", required = false) String accessToken) {
@ -132,7 +132,7 @@ public class JWTVotesEndpoint extends AssignmentEndpoint {
}
}
@PostMapping("reset")
@PostMapping
public @ResponseBody
AttackResult resetVotes(@CookieValue(value = "access_token", required = false) String accessToken) {
if (StringUtils.isEmpty(accessToken)) {

View File

@ -1,7 +1,16 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<header>
<script>
$(document).ready(
function(){
$("#secrettoken").load('/WebGoat/JWT/secret/gettoken');
}
);
</script>
</header>
<body>
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:JWT_plan.adoc"></div>
</div>
@ -24,7 +33,7 @@
<form class="attack-form" accept-charset="UNKNOWN"
method="POST"
successCallback="jwtSigningCallback"
action="/WebGoat/JWT/votings/reset"
action="/WebGoat/JWT/votings"
enctype="application/json;charset=UTF-8">
<div class="container-fluid">
@ -78,6 +87,7 @@
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:JWT_weak_keys"></div>
<div id="secrettoken" ></div>
<div class="attack-container">
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
@ -285,5 +295,6 @@
<div class="attack-output"></div>
</div>
</div>
</body>
</html>

View File

@ -76,7 +76,7 @@ function vote(title) {
} else {
$.ajax({
type: 'POST',
url: 'JWT/votings/' + title
url: 'JWT/votings/vote/' + title
}).then(
function () {
getVotings();

View File

@ -6,8 +6,5 @@ dictionary attack is not feasible. Once you have a token you can start an offlin
=== Assignment
Given we have the following token try to find out secret key and submit a new key with the userId changed to WebGoat.
Given we have the following token try to find out secret key and submit a new key with the username changed to WebGoat.
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJXZWJHb2F0IFRva2VuIEJ1aWxkZXIiLCJpYXQiOjE1MjQyMTA5MDQsImV4cCI6MTYxODkwNTMwNCwiYXVkIjoid2ViZ29hdC5vcmciLCJzdWIiOiJ0b21Ad2ViZ29hdC5jb20iLCJ1c2VybmFtZSI6IlRvbSIsIkVtYWlsIjoidG9tQHdlYmdvYXQuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.vPe-qQPOt78zK8wrbN1TjNJj3LeX9Qbch6oo23RUJgM
```