From 3b050a856a1cb1bfbb51990c25d6988160ad5486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Zubcevic?= Date: Thu, 27 Feb 2020 20:10:45 +0100 Subject: [PATCH] tested solution with unit test and verfied with lesson 5 on ie --- .../owasp/webgoat/jwt/JWTFinalEndpoint.java | 87 ++++++++++++++----- .../jwt/src/main/resources/html/JWT.html | 78 +++++++++++++---- .../lessonPlans/en/JWT_structure.adoc | 39 ++------- .../webgoat/jwt/JWTFinalEndpointTest.java | 45 +++++++--- 4 files changed, 169 insertions(+), 80 deletions(-) diff --git a/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/jwt/JWTFinalEndpoint.java b/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/jwt/JWTFinalEndpoint.java index 3bbe8ed62..44d19a1f2 100644 --- a/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/jwt/JWTFinalEndpoint.java +++ b/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/jwt/JWTFinalEndpoint.java @@ -22,24 +22,34 @@ package org.owasp.webgoat.jwt; -import io.jsonwebtoken.*; -import io.jsonwebtoken.impl.TextCodec; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.sql.ResultSet; +import java.sql.SQLException; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.sql.DataSource; + import org.apache.commons.lang3.StringUtils; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentHints; import org.owasp.webgoat.assignments.AttackResult; import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; -import javax.servlet.http.HttpServletRequest; -import javax.sql.DataSource; - -import java.nio.charset.Charset; -import java.security.NoSuchAlgorithmException; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Base64; -import java.util.Random; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.JwsHeader; +import io.jsonwebtoken.Jwt; +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SigningKeyResolverAdapter; +import io.jsonwebtoken.impl.TextCodec; /** *
@@ -81,17 +91,54 @@ public class JWTFinalEndpoint extends AssignmentEndpoint {
     		@RequestParam("jsonPayload") String jsonPayload,
     		@RequestParam("jsonSecret") String jsonSecret) throws NoSuchAlgorithmException {		
 		
-		String header = Base64.getUrlEncoder().encodeToString(jsonHeader.getBytes(Charset.defaultCharset()));
-		String body = Base64.getUrlEncoder().encodeToString(jsonPayload.getBytes(Charset.defaultCharset()));
-		String signature = "";
-		return "{\"header\":\""+header+"\",\"payload\":\""+body+"\",\"secret\":\""+signature+"\"}";
+    	//System.out.println(jsonHeader);
+    	//System.out.println(jsonPayload);
+		String encodedHeader;
+		String encodedPayload;
+		String encodedSignature;
+		try {
+			encodedHeader = TextCodec.BASE64URL.encode(jsonHeader);
+			encodedPayload = TextCodec.BASE64URL.encode(jsonPayload);
+			if (jsonHeader.toLowerCase().contains("none")) {
+				encodedSignature="";
+			} else {
+				encodedSignature = TextCodec.BASE64URL.encode(getJWTSignature(jsonHeader, encodedHeader, encodedPayload, jsonSecret));
+			}
+		} catch (Exception e) {
+			encodedHeader="";
+			encodedPayload="signature type not supported in this tool, try jwt.io";
+			encodedSignature = "";
+		}
+		String result = "{\"encodedHeader\":\""+encodedHeader+"\",\"encodedPayload\":\""+encodedPayload+"\",\"encodedSignature\":\""+encodedSignature+"\"}";
+		//System.out.println(result);
+		return result;
+    }
+       
+    private byte[] getJWTSignature(String jsonHeader, String encodedHeader, String encodedPayload, String jsonSecret) throws NoSuchAlgorithmException, InvalidKeyException {
+    	String message = encodedHeader+"."+encodedPayload;
+  	  	String algorithm = "HmacSHA256";
+    	if (jsonHeader.equals("HS512")) {
+    		algorithm = "HmacSHA512";
+    	} 
+    	Mac macInstance = Mac.getInstance(algorithm);
+        SecretKeySpec secret_key = new SecretKeySpec(TextCodec.BASE64.decode(jsonSecret), algorithm);
+        macInstance.init(secret_key);
+
+        return macInstance.doFinal(message.getBytes(StandardCharsets.UTF_8));
     }
     
-    @PostMapping(path="/JWT/decode",produces=MediaType.APPLICATION_JSON_VALUE)
+    @PostMapping(path="/JWT/decode",produces=MediaType.TEXT_HTML_VALUE)
     @ResponseBody
-    public String decode(@RequestParam("token") String token) throws NoSuchAlgorithmException {		
-		
-		return new String(Base64.getUrlDecoder().decode(token.getBytes(Charset.defaultCharset())));
+    public String decode(@RequestParam("jwtToken") String jwtToken) throws NoSuchAlgorithmException {		
+		try {
+			String encodedHeader = jwtToken.substring(0, jwtToken.indexOf("."));
+			String encodedPayload = jwtToken.substring(jwtToken.indexOf(".")+1, jwtToken.lastIndexOf("."));
+			String jsonHeader = TextCodec.BASE64URL.decodeToString(encodedHeader);
+			String jsonPayload = TextCodec.BASE64URL.decodeToString(encodedPayload);
+			return "{\"jsonHeader\":\""+jsonHeader.replace("\"", "\\\"")+"\",\"jsonPayload\":\""+jsonPayload.replace("\"", "\\\"").replace("\t","").replace("\r", "").replace("\n", "")+"\"}";
+		} catch (Exception e) {
+			return "{\"jsonHeader\":\"\",\"jsonPayload\":\"\"}";
+		}
     }
     
     @PostMapping("/JWT/final/follow/{user}")
diff --git a/webgoat-lessons/jwt/src/main/resources/html/JWT.html b/webgoat-lessons/jwt/src/main/resources/html/JWT.html
index a75f170aa..01303ea3d 100644
--- a/webgoat-lessons/jwt/src/main/resources/html/JWT.html
+++ b/webgoat-lessons/jwt/src/main/resources/html/JWT.html
@@ -20,22 +20,41 @@ $(document).ready(
 
- - - - - -
-
-
- - - - - -
-
+ + + + + + +
JWT header:
JWT payload: + +
.
encryption key:
+ +
+ + + + +
JWT token: + eyAgImFsZyI6IkhTMjU2IiwgICJ0eXAiOiJKV1QifQ + .//header
+
eyAgCQ0KCSJleHAiOiAxNDE2NDcxOTM0LCAgInVzZXJfbmFtZSI6ICJ1c2Vy + IiwgIA0KCSJzY29wZSI6IFsgICAgInJlYWQiLCAgICAid3JpdGUiICBdLCAg + DQoJImF1dGhvcml0aWVzIjogWyAgICAiUk9MRV9BRE1JTiIsICAgICJST0xF + X1VTRVIiICBdLCAgDQoJImp0aSI6ICI5YmM5MmE0NC0wYjFhLTRjNWUtYmU3 + MC1kYTUyMDc1YjlhODQiLCAgDQoJImNsaWVudF9pZCI6ICJteS1jbGllbnQt + d2l0aC1zZWNyZXQiDQp9DQoJCQk. //payload
+ gc32RepP65NANPLQP31Aq7QPbpWKBOiaS9UXczYVZLE//signature
JWT token:
+
@@ -318,10 +337,37 @@ $(document).ready(