From 3479ee41915a4905b2b302016668c9dbaa0c1505 Mon Sep 17 00:00:00 2001 From: Giorgos Lampadakis <82932062+giorgos-f3@users.noreply.github.com> Date: Fri, 25 Jun 2021 17:10:45 +0300 Subject: [PATCH] Fix security vulnerability Fixes a security vulnerability where a jwt token could potentially be validated having invalid string characters. (cherry picked from commit a211650c6ae1cff6d7347d3e24070d65dcfb1122) https://github.com/form3tech-oss/jwt-go/pull/14 Signed-off-by: Sebastiaan van Stijn --- map_claims.go | 38 +++++++++++++++++++++++++------------- map_claims_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 13 deletions(-) diff --git a/map_claims.go b/map_claims.go index ba290f42..c68ff4a5 100644 --- a/map_claims.go +++ b/map_claims.go @@ -34,30 +34,38 @@ func (m MapClaims) VerifyAudience(cmp string, req bool) bool { // Compares the exp claim against cmp. // If required is false, this method will return true if the value matches or is unset func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool { - switch exp := m["exp"].(type) { + exp, ok := m["exp"] + if !ok { + return !req + } + switch expType := exp.(type) { case float64: - return verifyExp(int64(exp), cmp, req) + return verifyExp(int64(expType), cmp, req) case json.Number: - v, _ := exp.Int64() + v, _ := expType.Int64() return verifyExp(v, cmp, req) } - return !req + return false } // Compares the iat claim against cmp. // If required is false, this method will return true if the value matches or is unset func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool { - switch iat := m["iat"].(type) { + iat, ok := m["iat"] + if !ok { + return !req + } + switch iatType := iat.(type) { case float64: - return verifyIat(int64(iat), cmp, req) + return verifyIat(int64(iatType), cmp, req) case json.Number: - v, _ := iat.Int64() + v, _ := iatType.Int64() return verifyIat(v, cmp, req) } - return !req + return false } -// Compares the iss claim against cmp. +// Compares the iss claim against cmp.`` // If required is false, this method will return true if the value matches or is unset func (m MapClaims) VerifyIssuer(cmp string, req bool) bool { iss, _ := m["iss"].(string) @@ -67,14 +75,18 @@ func (m MapClaims) VerifyIssuer(cmp string, req bool) bool { // Compares the nbf claim against cmp. // If required is false, this method will return true if the value matches or is unset func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool { - switch nbf := m["nbf"].(type) { + nbf, ok := m["nbf"] + if !ok { + return !req + } + switch nbfType := nbf.(type) { case float64: - return verifyNbf(int64(nbf), cmp, req) + return verifyNbf(int64(nbfType), cmp, req) case json.Number: - v, _ := nbf.Int64() + v, _ := nbfType.Int64() return verifyNbf(v, cmp, req) } - return !req + return false } // Validates time based claims "exp, iat, nbf". diff --git a/map_claims_test.go b/map_claims_test.go index ff65913f..340381c7 100644 --- a/map_claims_test.go +++ b/map_claims_test.go @@ -66,3 +66,37 @@ func TestVerifyAud(t *testing.T) { }) } } + +func Test_mapclaims_verify_issued_at_invalid_type_string(t *testing.T) { + mapClaims := MapClaims{ + "iat": "foo", + } + want := false + got := mapClaims.VerifyIssuedAt(0, false) + if want != got { + t.Fatalf("Failed to verify claims, wanted: %v got %v", want, got) + } +} + +func Test_mapclaims_verify_not_before_invalid_type_string(t *testing.T) { + mapClaims := MapClaims{ + "nbf": "foo", + } + want := false + got := mapClaims.VerifyNotBefore(0, false) + if want != got { + t.Fatalf("Failed to verify claims, wanted: %v got %v", want, got) + } +} + +func Test_mapclaims_verify_expires_at_invalid_type_string(t *testing.T) { + mapClaims := MapClaims{ + "exp": "foo", + } + want := false + got := mapClaims.VerifyExpiresAt(0, false) + + if want != got { + t.Fatalf("Failed to verify claims, wanted: %v got %v", want, got) + } +}