Added testcases for all JWT endpoints

This commit is contained in:
Nanne Baars
2018-05-23 12:51:57 +02:00
parent e0cf5b4a84
commit 8d7ecb19d7
8 changed files with 329 additions and 32 deletions

View File

@ -1,14 +1,19 @@
package org.owasp.webgoat.plugin;
import com.google.common.collect.Lists;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.Jwts;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
/**
* @author nbaars
@ -18,23 +23,29 @@ import io.jsonwebtoken.Jwts;
@AssignmentHints({"jwt-secret-hint1", "jwt-secret-hint2", "jwt-secret-hint3"})
public class JWTSecretKeyEndpoint extends AssignmentEndpoint {
private static final String JWT_SECRET = "victory";
public static final String JWT_SECRET = "victory";
private static final String WEBGOAT_USER = "WebGoat";
private static final List<String> expectedClaims = Lists.newArrayList("iss", "iat", "exp", "aud", "sub", "username", "Email", "Role");
@PostMapping()
public void login(@RequestParam String token) {
@PostMapping
@ResponseBody
public AttackResult login(@RequestParam String token) {
try {
Jwt jwt = Jwts.parser().setSigningKey(JWT_SECRET).parseClaimsJwt(token);
Jwt jwt = Jwts.parser().setSigningKey(JWT_SECRET).parse(token);
Claims claims = (Claims) jwt.getBody();
String user = (String) claims.get("username");
if (WEBGOAT_USER.equalsIgnoreCase(user)) {
trackProgress(success().build());
if (!claims.keySet().containsAll(expectedClaims)) {
return trackProgress(failed().feedback("jwt-secret-claims-missing").build());
} else {
trackProgress(failed().feedback("jwt-secret.not-correct").feedbackArgs(user).build());
String user = (String) claims.get("username");
if (WEBGOAT_USER.equalsIgnoreCase(user)) {
return trackProgress(success().build());
} else {
return trackProgress(failed().feedback("jwt-secret-incorrect-user").feedbackArgs(user).build());
}
}
} catch (Exception e) {
trackProgress(failed().feedback("jwt-invalid-token").output(e.getMessage()).build());
return trackProgress(failed().feedback("jwt-invalid-token").output(e.getMessage()).build());
}
}
}

View File

@ -21,6 +21,8 @@ import org.springframework.web.bind.annotation.*;
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.Map;
import java.util.concurrent.TimeUnit;
@ -37,7 +39,7 @@ import static java.util.stream.Collectors.toList;
@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 {
private static final String JWT_PASSWORD = "victory";
public static final String JWT_PASSWORD = "victory";
private static String validUsers = "TomJerrySylvester";
private static int totalVotes = 38929;
@ -65,11 +67,10 @@ public class JWTVotesEndpoint extends AssignmentEndpoint {
@GetMapping("/login")
public void login(@RequestParam("user") String user, HttpServletResponse response) {
if (validUsers.contains(user)) {
Map<String, Object> claims = Maps.newHashMap();
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()
.setIssuedAt(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toDays(10)))
.setClaims(claims)
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, JWT_PASSWORD)
.compact();
@ -96,11 +97,11 @@ public class JWTVotesEndpoint extends AssignmentEndpoint {
Jwt jwt = Jwts.parser().setSigningKey(JWT_PASSWORD).parse(accessToken);
Claims claims = (Claims) jwt.getBody();
String user = (String) claims.get("user");
boolean isAdmin = Boolean.valueOf((String) claims.get("admin"));
if ("Guest".equals(user) || !validUsers.contains(user)) {
value.setSerializationView(Views.GuestView.class);
} else {
value.setSerializationView(Views.UserView.class);
}
value.setSerializationView(isAdmin ? Views.AdminView.class : Views.UserView.class);
} catch (JwtException e) {
value.setSerializationView(Views.GuestView.class);
}
@ -132,7 +133,8 @@ public class JWTVotesEndpoint extends AssignmentEndpoint {
}
@PostMapping("reset")
public @ResponseBody AttackResult resetVotes(@CookieValue(value = "access_token", required = false) String accessToken) {
public @ResponseBody
AttackResult resetVotes(@CookieValue(value = "access_token", required = false) String accessToken) {
if (StringUtils.isEmpty(accessToken)) {
return trackProgress(failed().feedback("jwt-invalid-token").build());
} else {

View File

@ -1,9 +0,0 @@
package org.owasp.webgoat.plugin.refresh;
public class RefreshEndpoint {
private static final String TOKEN = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE0OTUyODU3NDUsImV4cCI6MTQ5NTI4NTc0NSwiYXVkIjoid2ViZ29hdC5vcmciLCJzdWIiOiJ0b21Ad2ViZ29hdC5vcmciLCJuYW1lIjoiVG9tIiwiZW1haWwiOiJ0b21Ad2ViZ29hdC5jb20iLCJyb2xlIjoiQ2F0In0.NTd3E17JZlVKZk52Wq_AWZ0RDafV5KDRMuJner_zUn4";
private static final String JWT_KEY = "qwertyuiopasdfghjklzxcvbnm123456";
}

View File

@ -10,7 +10,4 @@ public class Views {
public interface UserView extends GuestView {
}
public interface AdminView extends UserView {
}
}

View File

@ -20,9 +20,6 @@ public class Vote {
private final String imageBig;
@JsonView(Views.UserView.class)
private int numberOfVotes;
@JsonView(Views.AdminView.class)
@Setter
private String flag;
@JsonView(Views.UserView.class)
private boolean votingAllowed = true;
@JsonView(Views.UserView.class)

View File

@ -13,11 +13,13 @@ jwt-change-token-hint5=Submit the token by changing the algorithm to None and re
jwt-secret-hint1=Save the token and try to verify the token locally
jwt-secret-hint2=Download a word list dictionary (https://github.com/first20hours/google-10000-english)
jwt-secret-hint3=Write a small program or use HashCat for brute forcing the token according the word list
jwt-secret-claims-missing=You are missing some claims, you should keep all the claims in the token
jwt-secret-incorrect-user=The user is {0}, you need to change it to WebGoat
jwt-refresh-hint1=Look at the access log you will find a token there
jwt-refresh-hint2=The token from the access log is no longer valid, can you find a way to refresh it?
jwt-refresh-hint3=The endpoint for refreshing a token is 'jwt/refresh/newToken'
jwt-refresh-hint4=Use the found access token in the Authorization: Bearer header and use your refresh token
jwt-refresh-hint4=Use the found access token in the Authorization: Bearer header and use your own refresh token
jwt-refresh-not-tom=User is not Tom but {0}, please try again
jwt-final-jerry-account=Yikes, you are removing Jerry's account, try to delete the account of Tom