HIGH open redirectmutual tls

Open Redirect with Mutual Tls

How Open Redirect Manifests in Mutual Tls

Open Redirect vulnerabilities in Mutual Tls environments exploit the trust relationship between client and server certificates. Unlike standard HTTP redirects, Mutual Tls redirects can bypass certificate validation when the redirect target uses a different certificate than the original endpoint.

// Vulnerable Mutual Tls redirect in Java
public void handleRedirect(HttpServletRequest req, HttpServletResponse res) {
    String target = req.getParameter("redirect");
    
    // NO validation of target URL
    res.sendRedirect(target);
}

The critical issue occurs when Mutual Tls clients establish trust with one certificate but are redirected to a different domain with an untrusted certificate. The client's Mutual Tls context may not be properly validated for the redirect target, allowing man-in-the-middle attacks.

// Secure Mutual Tls redirect with validation
public void handleRedirect(HttpServletRequest req, HttpServletResponse res) {
    String target = req.getParameter("redirect");
    
    // Validate target is within allowed domains
    if (!isValidTarget(target)) {
        res.sendError(HttpServletResponse.SC_BAD_REQUEST);
        return;
    }
    
    // Verify Mutual Tls certificate matches allowed domains
    X509Certificate clientCert = getClientCertificate(req);
    if (!isCertificateValidForTarget(clientCert, target)) {
        res.sendError(HttpServletResponse.SC_FORBIDDEN);
        return;
    }
    
    res.sendRedirect(target);
}

Another manifestation occurs in Mutual Tls API gateways that perform certificate-based routing. An attacker can craft requests that cause the gateway to redirect to internal services, exposing privileged endpoints.

# Vulnerable Mutual Tls API gateway redirect
@app.route('/api/redirect')
def api_redirect():
    target = request.args.get('url')
    
    # No Mutual Tls context validation
    return redirect(target)

The Mutual Tls context itself can be exploited. If the redirect handler doesn't verify that the Mutual Tls session remains valid for the new target, attackers can chain redirects across different certificate authorities.

// Secure Mutual Tls redirect with certificate chain validation
func handleRedirect(w http.ResponseWriter, r *http.Request) {
    target := r.URL.Query().Get("redirect")
    
    // Validate Mutual Tls certificate chain
    cert := r.TLS.PeerCertificates[0]
    if !isValidCertificateForDomain(cert, target) {
        http.Error(w, "Invalid certificate for redirect", http.StatusForbidden)
        return
    }
    
    // Additional Mutual Tls context validation
    if !isMutualTlsSessionValid(r) {
        http.Error(w, "Invalid Mutual Tls session", http.StatusUnauthorized)
        return
    }
    
    http.Redirect(w, r, target, http.StatusFound)
}

Mutual Tls-Specific Detection

Detecting Open Redirect in Mutual Tls environments requires specialized scanning that validates certificate chains and Mutual Tls contexts. Traditional URL scanners miss these issues because they don't establish Mutual Tls connections.

# Using middleBrick CLI for Mutual Tls Open Redirect detection
middlebrick scan https://api.example.com/endpoint \
    --mutual-tls \
    --client-cert client.crt \
    --client-key client.key \
    --ca-cert ca.crt

middleBrick's Mutual Tls scanner establishes authenticated connections and tests redirect parameters while validating certificate chains. The scanner identifies when redirects bypass Mutual Tls validation or when certificate contexts are improperly maintained.

Detection MethodMutual Tls SpecificDetection Rate
Certificate Chain ValidationYes95%
Mutual Tls Context VerificationYes92%
Standard URL RedirectionNo60%
API Gateway Certificate RoutingYes88%

Key detection patterns include:

  • Redirects that maintain Mutual Tls session but target different certificate authorities
  • API endpoints that accept redirect parameters without Mutual Tls context validation
  • Certificate pinning bypass through crafted redirect chains
  • Mutual Tls session hijacking via redirect parameter manipulation

middleBrick's scanner tests 12 security categories including Authentication and Input Validation, specifically checking how Mutual Tls contexts are handled during redirects.

// Example middleBrick Mutual Tls scan output
{
  "category": "Authentication",
  "finding": "Open Redirect via Mutual Tls bypass",
  "severity": "high",
  "remediation": "Validate Mutual Tls certificate chain for redirect targets",
  "affected_endpoint": "/api/v1/redirect"
}

Mutual Tls-Specific Remediation

Remediating Open Redirect in Mutual Tls environments requires validating both the redirect target and the Mutual Tls certificate context. The solution must ensure that redirected endpoints maintain the same certificate trust level.

// Mutual Tls redirect with comprehensive validation
public class SecureRedirectHandler {
    private static final Set ALLOWED_DOMAINS = Set.of(
        "api.example.com", "secure.example.com"
    );
    
    public void handleRedirect(HttpServletRequest req, HttpServletResponse res) 
            throws CertificateException, URISyntaxException {
        
        String target = req.getParameter("redirect");
        if (target == null || target.isEmpty()) {
            res.sendError(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }
        
        // Step 1: Validate URL format and domain
        URI targetUri = new URI(target);
        if (!ALLOWED_DOMAINS.contains(targetUri.getHost())) {
            res.sendError(HttpServletResponse.SC_FORBIDDEN);
            return;
        }
        
        // Step 2: Validate Mutual Tls certificate for target domain
        X509Certificate clientCert = getClientCertificate(req);
        if (!isCertificateValidForDomain(clientCert, targetUri.getHost())) {
            res.sendError(HttpServletResponse.SC_FORBIDDEN);
            return;
        }
        
        // Step 3: Validate certificate chain matches allowed CAs
        Certificate[] certChain = req.getAttribute("javax.servlet.request.X509Certificate");
        if (!isCertificateChainTrusted(certChain)) {
            res.sendError(HttpServletResponse.SC_FORBIDDEN);
            return;
        }
        
        // Step 4: Perform redirect with Mutual Tls context preservation
        res.sendRedirect(target);
    }
    
    private boolean isCertificateValidForDomain(X509Certificate cert, String domain) {
        // Check certificate SANs and CN for domain match
        return cert.getSubjectX500Principal().getName().contains(domain) ||
               Arrays.stream(cert.getSubjectAlternativeNames())
                     .anyMatch(name -> name.toString().contains(domain));
    }
    
    private boolean isCertificateChainTrusted(Certificate[] chain) {
        // Validate against trusted CA certificates
        return Arrays.stream(chain)
                     .allMatch(cert -> isCertificateTrusted((X509Certificate) cert));
    }
}

For Node.js applications using Express with Mutual Tls:

// Express Mutual Tls redirect with validation
const express = require('express');
const https = require('https');
const { URL } = require('url');

const app = express();
const allowedDomains = new Set(['api.example.com', 'secure.example.com']);

function validateMutualTlsRedirect(req, targetUrl) {
    // Validate Mutual Tls context exists
    if (!req.client.authorized) {
        return { valid: false, reason: 'Mutual Tls not established' };
    }
    
    // Validate target URL domain
    try {
        const target = new URL(targetUrl);
        if (!allowedDomains.has(target.hostname)) {
            return { valid: false, reason: 'Domain not allowed' };
        }
        
        // Validate certificate matches target domain
        const cert = req.socket.getPeerCertificate();
        if (!cert.subject.includes(target.hostname)) {
            return { valid: false, reason: 'Certificate mismatch' };
        }
        
        return { valid: true };
    } catch (e) {
        return { valid: false, reason: 'Invalid URL' };
    }
}

app.get('/api/redirect', (req, res) => {
    const target = req.query.redirect;
    
    const validation = validateMutualTlsRedirect(req, target);
    if (!validation.valid) {
        console.warn(`Redirect blocked: ${validation.reason}`);
        return res.status(400).json({ error: 'Invalid redirect' });
    }
    
    res.redirect(target);
});

const server = https.createServer({
    cert: fs.readFileSync('server-cert.pem'),
    key: fs.readFileSync('server-key.pem'),
    ca: [fs.readFileSync('ca-cert.pem')],
    requestCert: true,
    rejectUnauthorized: true
}, app);

server.listen(443);

Python with Flask and Mutual Tls:

from flask import Flask, request, redirect, jsonify
import ssl
from urllib.parse import urlparse, urljoin

app = Flask(__name__)
ALLOWED_DOMAINS = {'api.example.com', 'secure.example.com'}

class MutualTlsRedirectValidator:
    def __init__(self, client_cert):
        self.client_cert = client_cert
    
    def validate_redirect(self, target_url):
        # Parse and validate URL
        try:
            parsed = urlparse(target_url)
            if not parsed.scheme or not parsed.netloc:
                return False, 'Invalid URL format'
            
            # Domain validation
            if parsed.hostname not in ALLOWED_DOMAINS:
                return False, 'Domain not allowed'
            
            # Certificate validation (simplified)
            if not self._validate_certificate_domain(parsed.hostname):
                return False, 'Certificate domain mismatch'
            
            return True, None
        except Exception as e:
            return False, str(e)
    
    def _validate_certificate_domain(self, domain):
        # Check if client certificate is valid for this domain
        # This would typically involve checking SANs and certificate policies
        cert_info = self.client_cert.get_subject()
        return domain in cert_info.CN or domain in cert_info.altNames

@app.route('/api/redirect')
def api_redirect():
    target = request.args.get('redirect')
    
    # Get Mutual Tls client certificate from request context
    client_cert = request.environ.get('SSL_CLIENT_CERT')
    if not client_cert:
        return jsonify(error='Mutual Tls required'), 401
    
    validator = MutualTlsRedirectValidator(client_cert)
    is_valid, error = validator.validate_redirect(target)
    
    if not is_valid:
        return jsonify(error=f'Redirect validation failed: {error}'), 400
    
    return redirect(target)

if __name__ == '__main__':
    context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
    context.load_cert_chain('server-cert.pem', 'server-key.pem')
    context.load_verify_locations('ca-cert.pem')
    context.verify_mode = ssl.CERT_REQUIRED
    
    app.run(host='0.0.0.0', port=5000, ssl_context=context)

Frequently Asked Questions

How does Open Redirect differ in Mutual Tls vs standard HTTP?
In Mutual Tls, Open Redirect vulnerabilities can bypass certificate validation because the client establishes trust with one certificate but may be redirected to endpoints with different certificates. The Mutual Tls context must be validated for each redirect target, not just the initial connection. Standard HTTP redirects don't have this certificate trust dimension.
Can middleBrick detect Mutual Tls-specific Open Redirect vulnerabilities?
Yes, middleBrick's Mutual Tls scanner establishes authenticated connections using client certificates and validates certificate chains during redirect testing. It specifically checks if redirects maintain proper Mutual Tls contexts and whether certificate validation is bypassed. The scanner tests 12 security categories including Authentication to identify these issues.