HIGH cross site request forgerymutual tls

Cross Site Request Forgery with Mutual Tls

How Cross Site Request Forgery Manifests in Mutual Tls

Cross Site Request Forgery (CSRF) in Mutual TLS (mTLS) environments presents unique challenges that differ from traditional CSRF attacks. While mTLS provides strong authentication through client certificates, CSRF can still compromise authorization when combined with other vulnerabilities.

In mTLS implementations, CSRF attacks exploit the fact that once a client certificate is installed in a browser, it can be automatically used for requests initiated from malicious sites. The attacker doesn't need to steal the certificate—they simply need to trick the victim's browser into making authenticated requests to the target API.

A common attack pattern involves a malicious website hosting a form that submits to an mTLS-protected endpoint. Since the victim's browser already has the client certificate installed, the request is authenticated and processed. For example:

<form action="https://api.example.com/v1/transfer" method="POST" id="csrf-form" style="display:none">
    <input type="hidden" name="from" value="victim-account">
    <input type="hidden" name="to" value="attacker-account">
    <input type="hidden" name="amount" value="1000">
</form>
<script>
document.getElementById('csrf-form').submit();
</script>

This attack works because mTLS authenticates the client certificate but doesn't verify that the request originated from the legitimate application. The server trusts the certificate but has no way to know if the request came from an authorized context.

Another variant involves using <img> tags or AJAX requests to trigger state-changing operations. Since mTLS certificates are often bound to specific user accounts, attackers can perform actions on behalf of the victim without their knowledge.

The risk is particularly acute in enterprise environments where client certificates are widely distributed. Once installed, these certificates can be used across multiple applications, creating a large attack surface for CSRF exploitation.

Mutual Tls-Specific Detection

Detecting CSRF vulnerabilities in mTLS environments requires specialized scanning techniques that understand the unique authentication flow. middleBrick's scanner identifies mTLS-specific CSRF risks by examining how the API handles authenticated requests without proper anti-CSRF tokens.

The scanner tests for CSRF by attempting to submit state-changing requests from different origins while using the mTLS certificate. It looks for endpoints that process requests without verifying the request's origin or presence of anti-CSRF tokens. This includes POST, PUT, DELETE, and PATCH operations that modify data.

Key detection patterns include:

  • Endpoints that accept mTLS authentication but don't require additional request verification
  • State-changing operations accessible via simple form submissions
  • Missing SameSite cookie attributes on session cookies (when used alongside mTLS)
  • Absence of CSRF token validation in the request processing pipeline
  • Endpoints that process requests without checking the Referer header or Origin header

middleBrick's scanner also examines the API specification to identify endpoints that should require additional authorization checks beyond mTLS authentication. It flags operations where the business logic suggests authorization boundaries that aren't enforced at the API level.

For mTLS implementations using Spring Boot, the scanner looks for patterns like:

@RestController
@RequestMapping("/api/v1")
public class TransferController {
    
    @PostMapping("/transfer")
    public ResponseEntity<TransferResponse> transferFunds(@RequestBody TransferRequest request) {
        // No CSRF protection despite mTLS authentication
        return transferService.executeTransfer(request);
    }
}

The scanner identifies this as vulnerable because it relies solely on mTLS authentication without additional request verification mechanisms.

Mutual Tls-Specific Remediation

Remediating CSRF in mTLS environments requires implementing additional request verification mechanisms that work alongside certificate-based authentication. The most effective approach combines mTLS with anti-CSRF tokens or custom request headers.

For Spring Boot applications using mTLS, implement CSRF protection with the Spring Security framework:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .requiresChannel()
                .requestMatchers(r -> r.getHeader("X-Forwarded-Proto") != null)
                .requiresSecure()
            .and()
            .csrf(csrf -> csrf
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .ignoringAntMatchers("/actuator/**")
            )
            .and()
            .x509(x509 -> x509
                .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
            );
    }
}

This configuration enables CSRF protection while maintaining mTLS authentication. The anti-CSRF token is stored in a cookie and must be included in subsequent requests.

For Node.js/Express applications with mTLS, implement CSRF middleware:

const express = require('express');
const csrf = require('csurf');
const helmet = require('helmet');
const https = require('https');

const app = express();

app.use(helmet({
    hsts: {
        maxAge: 31536000,
        includeSubDomains: true,
        preload: true
    }
}));

const csrfProtection = csrf({ cookie: true });

app.post('/api/v1/transfer', csrfProtection, (req, res) => {
    // CSRF token validated before processing mTLS-authenticated request
    res.json({ success: true });
});

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

httpsServer.listen(443);

For APIs that don't use cookies, implement double-submit cookie pattern with custom headers:

// Generate CSRF token on initial request
app.get('/api/v1/csrf-token', (req, res) => {
    const csrfToken = crypto.randomBytes(32).toString('hex');
    res.json({ token: csrfToken });
});

// Validate CSRF token on state-changing requests
app.post('/api/v1/transfer', (req, res, next) => {
    const headerToken = req.headers['x-csrf-token'];
    const cookieToken = req.cookies['csrf-token'];
    
    if (headerToken !== cookieToken) {
        return res.status(403).json({ error: 'CSRF token mismatch' });
    }
    
    next();
}, (req, res) => {
    // Process mTLS-authenticated request
    res.json({ success: true });
});

Additional mitigation strategies include implementing SameSite cookie attributes, validating the Origin header, and using custom request headers that cannot be forged by third-party sites.

Frequently Asked Questions

Can't mTLS alone prevent CSRF attacks?
No, mTLS only authenticates the client certificate but doesn't verify the request's origin or context. Once a certificate is installed in a browser, any website can initiate requests using that certificate. CSRF protection requires additional mechanisms like anti-CSRF tokens or custom headers to verify that requests originate from your legitimate application.
How does middleBrick detect CSRF vulnerabilities in mTLS APIs?
middleBrick's scanner tests mTLS-protected endpoints by attempting to submit state-changing requests from different origins while using the client certificate. It identifies endpoints that process requests without anti-CSRF tokens, validates against the API specification to find authorization gaps, and checks for missing SameSite attributes and Origin header validation. The scanner provides specific findings with severity levels and remediation guidance.