HIGH bleichenbacher attackchi

Bleichenbacher Attack in Chi

How Bleichenbacher Attack Manifests in Chi

The Bleichenbacher attack exploits RSA PKCS#1 v1.5 padding oracles to decrypt ciphertexts without the private key. In Chi, this manifests when APIs improperly handle RSA decryption errors, leaking information through timing differences or error message variations.

Consider a Chi API endpoint that decrypts RSA-encrypted tokens:

func DecryptToken(c *chi.Context) error {
    ciphertext := c.PostForm("token")
    
    // Vulnerable: timing oracle via error handling
    plaintext, err := rsa.DecryptPKCS1v15(nil, privateKey, ciphertext)
    if err != nil {
        c.JSON(http.StatusBadRequest, map[string]string{
            "error": "Invalid token format"
        })
        return nil
    }
    
    // Process plaintext...
    return c.JSON(http.StatusOK, map[string]string{"status": "ok"})
}

The vulnerability lies in how different padding errors produce different responses. A Bleichenbacher attacker can send modified ciphertexts and observe:

  • Timing differences between "invalid padding" vs "invalid format" responses
  • Response size variations
  • HTTP status code patterns
  • Network-level timing data

Chi-specific manifestation occurs when middleware chains process these errors. For example:

r := chi.NewRouter()

// Vulnerable middleware chain
r.Post("/api/v1/protected", RequireAuth, DecryptToken, HandleRequest)

// RequireAuth might add timing variations
func RequireAuth(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Different execution paths based on auth state
        // Creates timing side-channel
        next.ServeHTTP(w, r)
    })
}

The attack works because PKCS#1 v1.5 padding has a predictable structure. An attacker modifies the ciphertext's first block and observes whether decryption succeeds, gradually recovering the plaintext byte-by-byte.

Chi-Specific Detection

Detecting Bleichenbacher vulnerabilities in Chi applications requires examining both code patterns and runtime behavior. middleBrick's scanner specifically targets these Chi patterns:

# Scan a Chi API endpoint
middlebrick scan https://api.example.com/protected

The scanner analyzes for:

  • Direct PKCS#1 v1.5 usage: Calls to rsa.DecryptPKCS1v15() without constant-time handling
  • Error message analysis: Different error responses for padding vs format errors
  • Timing analysis: Variable response times based on decryption success

Manual detection in Chi codebases should look for these patterns:

// Vulnerable pattern - different error paths
func HandlePayment(c *chi.Context) error {
    data, err := rsa.DecryptPKCS1v15(rand.Reader, priv, encryptedData)
    if err != nil {
        if strings.Contains(err.Error(), "crypto/rsa: decryption error") {
            // Bleichenbacher oracle - different timing
            return c.JSON(http.StatusUnauthorized, map[string]string{
                "error": "Decryption failed"
            })
        }
        return c.JSON(http.StatusBadRequest, map[string]string{
            "error": "Invalid request"
        })
    }
    
    // Process payment...
    return c.JSON(http.StatusOK, map[string]string{"status": "processed"})
}

middleBrick specifically tests for Chi's middleware patterns that might amplify timing differences:

{
  "checks": [
    "PKCS1v15_Usage",
    "Timing_Oracle",
    "Error_Message_Variation",
    "Middleware_Chain_Timing"
  ]
}

The scanner sends crafted ciphertexts and measures response characteristics, looking for the statistical patterns that indicate an active oracle.

Chi-Specific Remediation

Remediating Bleichenbacher vulnerabilities in Chi requires both cryptographic fixes and API design changes. The primary defense is eliminating PKCS#1 v1.5 padding entirely:

import "crypto/rsa"

// Preferred: OAEP padding (secure by design)
func DecryptTokenOAEP(c *chi.Context) error {
    ciphertext := c.PostForm("token")
    
    // OAEP provides semantic security - no padding oracle
    plaintext, err := rsa.DecryptOAEP(
        sha256.New(),
        rand.Reader,
        privateKey,
        ciphertext,
        nil,
    )
    if err != nil {
        // Constant-time error response
        c.JSON(http.StatusBadRequest, map[string]string{
            "error": "Invalid token"
        })
        return nil
    }
    
    // Process plaintext...
    return c.JSON(http.StatusOK, map[string]string{"status": "ok"})
}

For Chi applications that must maintain PKCS#1 v1.5 compatibility, implement these mitigations:

func ConstantTimeDecrypt(c *chi.Context) error {
    ciphertext := c.PostForm("token")
    
    // Always perform full decryption operation
    _, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, ciphertext)
    
    // Constant-time response regardless of error type
    if err != nil {
        // Use constant-time comparison
        expected := []byte("error")
        actual := []byte("invalid")
        
        // Prevent timing attacks via constant-time compare
        if subtle.ConstantTimeCompare(expected, actual) == 1 {
            return c.JSON(http.StatusBadRequest, map[string]string{
                "error": "Invalid token format"
            })
        }
    }
    
    return c.JSON(http.StatusOK, map[string]string{"status": "ok"})
}

Chi middleware can enforce constant-time responses across the entire chain:

func ConstantTimeMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Record start time
        start := time.Now()
        
        // Create a wrapper that enforces constant response time
        rw := &constantResponseWriter{ResponseWriter: w}
        next.ServeHTTP(rw, r)
        
        // Pad response to constant time (e.g., 100ms minimum)
        elapsed := time.Since(start)
        if elapsed < 100*time.Millisecond {
            time.Sleep(100*time.Millisecond - elapsed)
        }
    })
}

// Apply to router
r.Use(ConstantTimeMiddleware)

For comprehensive protection, combine cryptographic fixes with middleBrick's continuous monitoring to verify that no new oracle vulnerabilities are introduced during development.

Frequently Asked Questions

Why is PKCS#1 v1.5 padding vulnerable to Bleichenbacher attacks?
PKCS#1 v1.5 padding has a deterministic structure that reveals information through error responses. When decryption fails due to padding errors, the timing and error messages differ from other failure modes, creating a side-channel. OAEP padding eliminates this by making all valid padding equally likely and all invalid padding indistinguishable.
Can I use middleBrick to scan my Chi API for Bleichenbacher vulnerabilities?
Yes, middleBrick's free plan includes 3 monthly scans that specifically test for PKCS#1 v1.5 oracle vulnerabilities. The scanner sends crafted ciphertexts and analyzes response timing, error messages, and patterns to detect active oracles. Pro plans offer continuous monitoring to catch regressions.