diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java index a6743024f..47545ef35 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java @@ -81,6 +81,39 @@ public class CreateDB { } } + /** + * Description of the Method + * + * @param connection Description of the Parameter + * @throws SQLException Description of the Exception + */ + private void createJWTKeys(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); + + // Drop servers table + try { + String dropTable = "DROP TABLE jwt_keys"; + statement.executeUpdate(dropTable); + } catch (SQLException e) { + System.out.println("Info - Could not drop jwtkeys table"); + } + + // Create the new table + try { + String createTableStatement = "CREATE TABLE jwt_keys" + + " (" + "id varchar(10)," + + "key varchar(20))"; + statement.executeUpdate(createTableStatement); + + String insertData1 = "INSERT INTO jwt_keys VALUES ('webgoat_key', 'qwertyqwerty1234')"; + String insertData2 = "INSERT INTO jwt_keys VALUES ('webwolf_key', 'doesnotreallymatter')"; + statement.executeUpdate(insertData1); + statement.executeUpdate(insertData2); + } catch (SQLException e) { + System.out.println("Error creating product table " + e.getLocalizedMessage()); + } + } + /** * Description of the Method @@ -975,6 +1008,7 @@ public class CreateDB { createTanTable(connection); createMFEImagesTable(connection); createModifyWithSQLLessonTable(connection); + createJWTKeys(connection); System.out.println("Success: creating tables."); } } 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 new file mode 100644 index 000000000..1dd765faf --- /dev/null +++ b/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTFinalEndpoint.java @@ -0,0 +1,85 @@ +package org.owasp.webgoat.plugin; + +import com.google.common.base.Charsets; +import io.jsonwebtoken.*; +import org.apache.commons.lang3.StringUtils; +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.owasp.webgoat.session.DatabaseUtilities; +import org.owasp.webgoat.session.WebSession; +import org.springframework.beans.factory.annotation.Autowired; +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 java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * @author nbaars + * @since 4/23/17. + */ +@AssignmentPath("/JWT/final") +@AssignmentHints({"jwt-final-hint1", "jwt-final-hint2", "jwt-final-hint3", "jwt-final-hint4", "jwt-final-hint5", "jwt-final-hint6"}) +public class JWTFinalEndpoint extends AssignmentEndpoint { + + @Autowired + private WebSession webSession; + + @PostMapping("follow/{user}") + public @ResponseBody + String follow(@PathVariable("user") String user) { + if ("Jerry".equals(user)) { + return "Following yourself seems redundant"; + } else { + return "You are now following Tom"; + } + } + + @PostMapping("delete") + public @ResponseBody + AttackResult resetVotes(@RequestParam("token") String token) { + if (StringUtils.isEmpty(token)) { + return trackProgress(failed().feedback("jwt-invalid-token").build()); + } else { + try { + final String[] errorMessage = {null}; + Jwt jwt = Jwts.parser().setSigningKeyResolver(new SigningKeyResolverAdapter() { + @Override + public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) { + final String kid = (String) header.get("kid"); + try { + Connection connection = DatabaseUtilities.getConnection(webSession); + ResultSet rs = connection.createStatement().executeQuery("SELECT key FROM jwt_keys WHERE id = " + kid); + while (rs.next()) { + return rs.getString(1).getBytes(Charsets.UTF_8); + } + } catch (SQLException e) { + errorMessage[0] = e.getMessage(); + } + return null; + } + }).parse(token); + if (errorMessage[0] != null) { + return trackProgress(failed().output(errorMessage[0]).build()); + } + Claims claims = (Claims) jwt.getBody(); + String username = (String) claims.get("username"); + if ("Jerry".equals(username)) { + return trackProgress(failed().feedback("jwt-final-jerry-account").build()); + } + if ("Tom".equals(username)) { + return trackProgress(success().build()); + } else { + return trackProgress(failed().feedback("jwt-final-not-tom").build()); + } + } catch (JwtException e) { + return trackProgress(failed().feedback("jwt-invalid-token").output(e.toString()).build()); + } + } + } +} diff --git a/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/refresh/RefreshEndpoint.java b/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/refresh/RefreshEndpoint.java new file mode 100644 index 000000000..d04cf8ef7 --- /dev/null +++ b/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/refresh/RefreshEndpoint.java @@ -0,0 +1,9 @@ +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"; + + +} diff --git a/webgoat-lessons/jwt/src/main/resources/css/jwt.css b/webgoat-lessons/jwt/src/main/resources/css/jwt.css index 590e2a4b0..19dd769d0 100644 --- a/webgoat-lessons/jwt/src/main/resources/css/jwt.css +++ b/webgoat-lessons/jwt/src/main/resources/css/jwt.css @@ -9,4 +9,108 @@ a.list-group-item.active small { } .img-responsive { min-width: 100%; +} + + +.card { + font-size: 1em; + overflow: hidden; + padding: 0; + border: none; + border-radius: .28571429rem; + box-shadow: 0 1px 3px 0 #d4d4d5, 0 0 0 1px #d4d4d5; +} + +.card-block { + font-size: 1em; + position: relative; + margin: 0; + padding: 1em; + border: none; + border-top: 1px solid rgba(34, 36, 38, .1); + box-shadow: none; +} + +.card-img-top { + display: block; + width: 100%; + height: auto; +} + +.card-title { + font-size: 1.28571429em; + font-weight: 700; + line-height: 1.2857em; +} + +.card-text { + clear: both; + margin-top: .5em; + color: rgba(0, 0, 0, .68); +} + +.card-footer { + font-size: 1em; + position: static; + top: 0; + left: 0; + max-width: 100%; + padding: .75em 1em; + color: rgba(0, 0, 0, .4); + border-top: 1px solid rgba(0, 0, 0, .05) !important; + background: #fff; +} + +.card-inverse .btn { + border: 1px solid rgba(0, 0, 0, .05); +} + +.profile { + position: absolute; + top: -12px; + display: inline-block; + overflow: hidden; + box-sizing: border-box; + width: 50px; + height: 50px; + margin: 0; + border: 1px solid #fff; + border-radius: 50%; +} + +.profile-avatar { + display: block; + width: 100%; + height: auto; + border-radius: 50%; +} + +.profile-inline { + position: relative; + top: 0; + display: inline-block; +} + +.profile-inline ~ .card-title { + display: inline-block; + margin-left: 4px; + vertical-align: top; +} + +.text-bold { + font-weight: 700; +} + +.meta { + font-size: 1em; + color: rgba(0, 0, 0, .4); +} + +.meta a { + text-decoration: none; + color: rgba(0, 0, 0, .4); +} + +.meta a:hover { + color: rgba(0, 0, 0, .87); } \ No newline at end of file diff --git a/webgoat-lessons/jwt/src/main/resources/html/JWT.html b/webgoat-lessons/jwt/src/main/resources/html/JWT.html index e50b9a405..bd2326f0d 100644 --- a/webgoat-lessons/jwt/src/main/resources/html/JWT.html +++ b/webgoat-lessons/jwt/src/main/resources/html/JWT.html @@ -106,11 +106,11 @@