JWT Signature Verification Bypass
ID |
go.jwt_signature_verification_bypass |
Severity |
high |
Resource |
Cryptography |
Language |
Go |
Tags |
CWE:347, NIST.SP.800-53, OWASP:2021:A3, OWASP:2021:A7, PCI-DSS:6.5.10, PCI-DSS:6.5.6, PCI-DSS:6.5.8 |
Rationale
JWT signature verification bypass refers to a scenario where a JSON Web Token, designed to be a secure way to transmit information between parties, is not properly checked for a valid signature.
This can allow attackers to forge tokens, gaining unauthorized access to protected resources or services.
A common example is accepting tokens with the algorithm field (alg
) set to none
, which implies no signature. Some libraries or custom implementations may improperly accept such tokens.
Another common flaw is accepting tokens signed with a public key or wrong algorithm due to misconfigured validation logic.
import (
"github.com/golang-jwt/jwt/v5"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
tokenString := r.Header.Get("Authorization")
token, _, err := new(jwt.Parser).ParseUnverified(tokenString, jwt.MapClaims{}) // Vulnerable: no signature validation
if err != nil {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
claims, ok := token.Claims.(jwt.MapClaims)
if ok && token.Valid {
// Proceed with unchecked claims
}
}
In this example, ParseUnverified
is used, which intentionally skips signature validation. If such logic is used in production or accessible paths, attackers can craft tokens with arbitrary claims and bypass authentication or authorization.
Additionally, misconfigured parsing like accepting tokens with alg: none
or not restricting allowed signing methods can open the application to similar bypasses.
Remediation
To remediate the JWT signature verification bypass, ensure that you are properly configuring the JWT parser in use, and always verifying the token signature with a trusted public key or secret.
Furthermore, make sure your JWT libraries are updated to the latest versions, which often address security vulnerabilities and provide enhanced capabilities. Additionally, it’s important to apply similar best practices across all environments where JWTs are used or processed to maintain consistent security assurances.
import (
"github.com/golang-jwt/jwt/v5"
"net/http"
)
var verifyKey = []byte("your-256-bit-secret")
func handler(w http.ResponseWriter, r *http.Request) {
tokenString := r.Header.Get("Authorization")
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
// Ensure token's signing method is what we expect
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return verifyKey, nil
})
if err != nil || !token.Valid {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
claims := token.Claims.(jwt.MapClaims)
// Use claims safely
}
Additional Best Practices:
-
Reject tokens with
alg: none
. -
Always validate the
exp
,nbf
, andiat
claims. -
Use a mature JWT library that performs full verification and avoids deprecated behaviors.
-
Monitor and audit JWT usage patterns in your environment to detect abuse or anomalies.
References
-
CWE-347 : Improper Verification of Cryptographic Signature