feat: implement JWT jku example (#1552)

Closes #1539
This commit is contained in:
Nanne Baars
2023-08-08 17:18:22 +02:00
committed by GitHub
parent 8f6e47e6d4
commit a9b1fd66b8
16 changed files with 544 additions and 32 deletions

View File

@ -0,0 +1,95 @@
package org.owasp.webgoat.lessons.jwt.claimmisuse;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
import static io.jsonwebtoken.SignatureAlgorithm.RS256;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import io.jsonwebtoken.Jwts;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
import org.jose4j.jwk.JsonWebKeySet;
import org.jose4j.jwk.RsaJsonWebKey;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.jwt.JWT;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
class JWTHeaderJKUEndpointTest extends LessonTest {
private KeyPair keyPair;
private WireMockServer webwolfServer;
private int port;
@BeforeEach
public void setup() throws Exception {
when(webSession.getCurrentLesson()).thenReturn(new JWT());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
setupWebWolf();
this.keyPair = generateRsaKey();
}
private void setupWebWolf() {
this.webwolfServer = new WireMockServer(options().dynamicPort());
webwolfServer.start();
this.port = webwolfServer.port();
}
private KeyPair generateRsaKey() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
return keyPairGenerator.generateKeyPair();
}
@Test
void solve() throws Exception {
setupJsonWebKeySetInWebWolf();
var token = createTokenAndSignIt();
mockMvc
.perform(MockMvcRequestBuilders.post("/JWT/jku/delete").param("token", token).content(""))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(true)));
}
@Test
@DisplayName("When JWKS is not present in WebWolf then the call should fail")
void shouldFailNotPresent() throws Exception {
var token = createTokenAndSignIt();
mockMvc
.perform(MockMvcRequestBuilders.post("/JWT/jku/delete").param("token", token).content(""))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(false)));
}
private String createTokenAndSignIt() {
Map<String, Object> claims = new HashMap<>();
claims.put("username", "Tom");
var token =
Jwts.builder()
.setHeaderParam("jku", "http://localhost:%d/files/jwks".formatted(port))
.setClaims(claims)
.signWith(RS256, this.keyPair.getPrivate())
.compact();
return token;
}
private void setupJsonWebKeySetInWebWolf() {
var jwks = new JsonWebKeySet(new RsaJsonWebKey((RSAPublicKey) keyPair.getPublic()));
webwolfServer.stubFor(
WireMock.get(WireMock.urlMatching("/files/jwks"))
.willReturn(aResponse().withStatus(200).withBody(jwks.toJson())));
}
}

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.lessons.jwt;
package org.owasp.webgoat.lessons.jwt.claimmisuse;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.when;
@ -14,10 +14,11 @@ import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.jwt.JWT;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
public class JWTFinalEndpointTest extends LessonTest {
public class JWTHeaderKIDEndpointTest extends LessonTest {
private static final String TOKEN_JERRY =
"eyJraWQiOiJ3ZWJnb2F0X2tleSIsImFsZyI6IkhTNTEyIn0.eyJhdWQiOiJ3ZWJnb2F0Lm9yZyIsImVtYWlsIjoiamVycnlAd2ViZ29hdC5jb20iLCJ1c2VybmFtZSI6IkplcnJ5In0.xBc5FFwaOcuxjdr_VJ16n8Jb7vScuaZulNTl66F2MWF1aBe47QsUosvbjWGORNcMPiPNwnMu1Yb0WZVNrp2ZXA";
@ -42,7 +43,7 @@ public class JWTFinalEndpointTest extends LessonTest {
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, key)
.compact();
mockMvc
.perform(MockMvcRequestBuilders.post("/JWT/final/delete").param("token", token).content(""))
.perform(MockMvcRequestBuilders.post("/JWT/kid/delete").param("token", token).content(""))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(true)));
}
@ -51,9 +52,7 @@ public class JWTFinalEndpointTest extends LessonTest {
public void withJerrysKeyShouldNotSolveAssignment() throws Exception {
mockMvc
.perform(
MockMvcRequestBuilders.post("/JWT/final/delete")
.param("token", TOKEN_JERRY)
.content(""))
MockMvcRequestBuilders.post("/JWT/kid/delete").param("token", TOKEN_JERRY).content(""))
.andExpect(status().isOk())
.andExpect(
jsonPath(
@ -64,7 +63,7 @@ public class JWTFinalEndpointTest extends LessonTest {
public void shouldNotBeAbleToBypassWithSimpleToken() throws Exception {
mockMvc
.perform(
MockMvcRequestBuilders.post("/JWT/final/delete")
MockMvcRequestBuilders.post("/JWT/kid/delete")
.param("token", ".eyJ1c2VybmFtZSI6IlRvbSJ9.")
.content(""))
.andExpect(status().isOk())