HIGH bleichenbacher attackchijwt tokens

Bleichenbacher Attack in Chi with Jwt Tokens

Bleichenbacher Attack in Chi with Jwt Tokens — how this specific combination creates or exposes the vulnerability

A Bleichenbacher attack targets RSA-based padding schemes, most commonly PKCS#1 v1.5 padding used in RS256 tokens. In Chi, if JWT tokens are verified with an RSA public key and the verification logic is implemented with an RSA operation that leaks whether padding is valid (for example, through timing differences or error messages), an attacker can iteratively craft ciphertexts and observe responses to gradually decrypt the token or forge a signature. This is a chosen-ciphertext attack on the asymmetric verification path, not on the HS256 symmetric path.

Chi applications that expose an unauthenticated endpoint which accepts a JWT in the Authorization header as a bearer token can become the oracle required by Bleichenbacher’s attack. If the endpoint returns distinct errors for bad padding versus bad signature, or if verification time varies with padding correctness, the attacker can send many modified tokens and infer the underlying plaintext or forge a valid token. When OpenAPI specs are parsed with full $ref resolution, middleBrick flags this as an authentication configuration issue because the scan tests the unauthenticated attack surface and checks whether responses or timing inadvertently assist an oracle.

An example of a vulnerable Chi handler in a service that decodes and verifies RS256 JWT tokens without constant-time padding checks might look like this, which middleBrick would flag under Authentication and BOLA/IDOR checks:

// Vulnerable example in Chi
import "crypto/rsa"
import "github.com/golang-jwt/jwt/v5"
import "net/http"

func verifyToken(pub *rsa.PublicKey) func(http.Handler) http.Handler {
    return func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            tokenString := r.Header.Get("Authorization")
            // WARNING: No audience/issuer validation, and standard jwt.Parse may leak padding errors
            token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
                if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
                    return nil, fmt.Errorf("unexpected signing method")
                }
                return pub, nil
            })
            if err != nil {
                // Distinct error can act as oracle
                http.Error(w, err.Error(), http.StatusUnauthorized)
                return
            }
            if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
                next.ServeHTTP(w, r)
                return
            }
            http.Error(w, "invalid token", http.StatusUnauthorized)
        })
    }
}

middleBrick’s 12 security checks run in parallel and include Authentication, BOLA/IDOR, and Input Validation, which help surface such weak verification paths. Because the scanner tests the unauthenticated attack surface and cross-references spec definitions with runtime behavior, it can detect whether responses or configurations enable a Bleichenbacher-like oracle for JWT tokens. The scan also tests for LLM/AI Security concerns if any endpoint exposes token introspection or debug endpoints that could leak structured information useful to an attacker.

Jwt Tokens-Specific Remediation in Chi — concrete code fixes

To mitigate Bleichenbacher-style risks with JWT tokens in Chi, ensure verification is constant-time and does not leak padding validity, and enforce strict claims validation. Use a well-audited library and avoid returning low-level errors that differ by padding failure. The following example demonstrates a safer approach that avoids leaking padding information and validates required claims:

// Safer verification in Chi
import "crypto/rsa"
import "github.com/golang-jwt/jwt/v5"
import "net/http"
import "time"

func secureVerifyToken(pub *rsa.PublicKey, issuer string, audience string) func(http.Handler) http.Handler {
    return func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            tokenString := r.Header.Get("Authorization")
            // Always use a constant-time verification path by avoiding early errors on padding
            // Use WithClaims and a strict validator to enforce iss, aud, exp, nbf
            token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
                if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
                    // Return a generic error to avoid oracle behavior
                    return nil, jwt.ErrSignatureInvalid
                }
                return pub, nil
            }, jwt.WithClaims(jwt.MapClaims{}), jwt.WithoutClaimsValidation())
            if err != nil {
                // Generic response to prevent oracle
                http.Error(w, "invalid token", http.StatusUnauthorized)
                return
            }
            if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
                // Validate standard claims explicitly to prevent token substitution across issuers/audiences
                if iss, ok := claims["iss"].(string); !ok || iss != issuer {
                    http.Error(w, "invalid token", http.StatusUnauthorized)
                    return
                }
                if aud, ok := claims["aud"].(string); !ok || aud != audience {
                    http.Error(w, "invalid token", http.StatusUnauthorized)
                    return
                }
                if exp, ok := claims["exp"].(float64); !ok || time.Unix(int64(exp), 0).Before(time.Now()) {
                    http.Error(w, "token expired", http.StatusUnauthorized)
                    return
                }
                next.ServeHTTP(w, r)
                return
            }
            http.Error(w, "invalid token", http.StatusUnauthorized)
        })
    }
}

Complementary practices include using the Pro plan for continuous monitoring so that scans run on a configurable schedule and alert you if any endpoint’s risk score changes, and integrating the GitHub Action to fail builds when a new deployment introduces weaker JWT handling. The MCP Server allows you to scan APIs directly from your AI coding assistant within the IDE, helping catch insecure patterns before code is committed. Remember, middleBrick detects and reports these issues but does not fix or block them; apply the remediation guidance to harden your Chi service.

Frequently Asked Questions

Can a Bleichenbacher attack be used against JWT tokens that use HS256?
No. Bleichenbacher attacks target RSA padding (e.g., PKCS#1 v1.5 with RS256). HS256 uses symmetric HMAC and does not involve RSA padding, so this specific oracle does not apply.
Does middleBrick fix the Bleichenbacher vulnerability it detects?
middleBrick detects and reports the issue with remediation guidance. It does not automatically patch or block; developers must apply the recommended code changes to harden JWT verification.