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