HIGH integrity failuresmutual tls

Integrity Failures with Mutual Tls

How Integrity Failures Manifests in Mutual Tls

Integrity Failures in Mutual TLS (mTLS) contexts often stem from improper certificate validation, leading to man-in-the-middle attacks where an attacker intercepts and potentially modifies encrypted traffic. The most common manifestation occurs when applications fail to properly validate the server's certificate chain or when client certificates are not correctly authenticated by the server.

A critical vulnerability arises when mTLS implementations accept self-signed certificates or certificates from untrusted CAs. For example, a Node.js server using the https module might be configured with:

const https = require('https');
const fs = require('fs');

const options = {
  cert: fs.readFileSync('server-cert.pem'),
  key: fs.readFileSync('server-key.pem'),
  requestCert: true,
  rejectUnauthorized: false, // SECURITY VULNERABILITY
};

https.createServer(options, (req, res) => {
  // Handle request
}).listen(443);

The rejectUnauthorized: false setting disables certificate validation entirely, allowing any client to connect regardless of certificate authenticity. This creates a perfect scenario for integrity failures where an attacker can present a forged certificate and intercept sensitive data.

Another manifestation occurs in certificate pinning failures. When applications don't verify that the presented certificate matches expected values, attackers can substitute valid but unauthorized certificates. Consider this vulnerable Go code:

package main

import (
    "crypto/tls"
    "crypto/x509"
    "io/ioutil"
    "net/http"
)

func main() {
    pool := x509.NewCertPool()
    // Missing: pool.AppendCertsFromPEM(certBytes)
    
    client := &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{
                RootCAs:            pool,
                InsecureSkipVerify: true, // SECURITY VULNERABILITY
            },
        },
    }
    
    resp, _ := client.Get("https://api.example.com")
    // Vulnerable to integrity attacks
}

The InsecureSkipVerify: true flag bypasses all certificate validation, making the client susceptible to integrity failures through certificate substitution attacks.

Certificate expiration handling represents another integrity failure vector. Applications that don't properly check certificate validity periods can accept expired certificates, which may have been compromised. A vulnerable Java implementation might look like:

SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");

// Missing: proper certificate validation
sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
SSLContext.setDefault(sslContext);

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

// Vulnerable: accepts expired or revoked certificates

These integrity failures in mTLS implementations can lead to data tampering, session hijacking, and unauthorized access to protected resources.

Mutual Tls-Specific Detection

Detecting integrity failures in mTLS requires both static analysis of configuration files and dynamic testing of certificate validation logic. The first step involves examining configuration files for dangerous settings like rejectUnauthorized: false, InsecureSkipVerify: true, or missing certificate validation callbacks.

Using middleBrick's CLI tool, you can scan mTLS endpoints for integrity failures:

npx middlebrick scan https://api.example.com:443 \
  --mtls \
  --client-cert client-cert.pem \
  --client-key client-key.pem

This command tests the mTLS endpoint and specifically checks for certificate validation issues. middleBrick's scanner examines the certificate chain, verifies that the server presents a valid certificate from a trusted CA, and tests whether the client certificate is properly authenticated.

For automated detection in CI/CD pipelines, the GitHub Action integration provides continuous monitoring:

name: API Security Scan
on: [push, pull_request]

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Run middleBrick Scan
      uses: middlebrick/middlebrick-action@v1
      with:
        target: 'https://api.example.com:443'
        mtls: true
        client_cert: './client-cert.pem'
        client_key: './client-key.pem'
        fail_if_score_below: 80
      env:
        MIDDLEBRICK_API_KEY: ${{ secrets.MIDDLEBRICK_API_KEY }}

The scanner identifies specific integrity failure patterns including:

  • Missing or weak certificate validation
  • Expired or revoked certificates in the chain
  • Incorrect certificate usage (e.g., server certificates used for client authentication)
  • Weak cryptographic algorithms in certificates
  • Missing certificate pinning configurations

middleBrick's OpenAPI analysis also cross-references mTLS configurations in your API specifications with runtime findings, ensuring that documented security requirements match actual implementation.

Mutual Tls-Specific Remediation

Remediating integrity failures in mTLS implementations requires strict certificate validation and proper configuration. The first step is always enabling certificate validation and rejecting unauthorized connections.

For Node.js applications, the secure configuration should look like:

const https = require('https');
const fs = require('fs');

const options = {
  cert: fs.readFileSync('server-cert.pem'),
  key: fs.readFileSync('server-key.pem'),
  requestCert: true,
  rejectUnauthorized: true, // SECURITY FIX
  ca: fs.readFileSync('ca-cert.pem'), // Specify trusted CA
};

https.createServer(options, (req, res) => {
  const cert = req.connection.getPeerCertificate();
  if (!cert || !cert.subject) {
    res.writeHead(401);
    res.end('Unauthorized');
    return;
  }
  
  // Verify client certificate against expected values
  if (cert.subject.CN !== 'expected-client-cn') {
    res.writeHead(403);
    res.end('Forbidden');
    return;
  }
  
  res.writeHead(200);
  res.end('Authorized');
}).listen(443);

This configuration ensures that only clients presenting valid certificates from the trusted CA can connect, and performs additional verification of the client certificate subject.

For Go applications, proper certificate validation requires:

package main

import (
    "crypto/tls"
    "crypto/x509"
    "io/ioutil"
    "net/http"
)

func loadCA(caCertPath string) *x509.CertPool {
    pool := x509.NewCertPool()
    caCert, err := ioutil.ReadFile(caCertPath)
    if err != nil {
        panic(err)
    }
    pool.AppendCertsFromPEM(caCert)
    return pool
}

func main() {
    pool := loadCA("ca-cert.pem")
    
    client := &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{
                RootCAs:            pool,
                InsecureSkipVerify: false, // SECURITY FIX
                VerifyPeerCertificate: func(certificates [][]byte, _ [][]*x509.Certificate) error {
                    // Additional custom validation
                    return nil
                },
            },
        },
    }
    
    resp, err := client.Get("https://api.example.com")
    if err != nil {
        // Handle error
    }
    defer resp.Body.Close()
}

The Java implementation should use proper SSLContext configuration:

KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(new FileInputStream("keystore.p12"), "password".toCharArray());

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "password".toCharArray());

TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
KeyStore ts = KeyStore.getInstance("JKS");
ts.load(new FileInputStream("truststore.jks"), "password".toCharArray());
tmf.init(ts);

SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

// Certificate pinning for additional integrity
public static void verifyCertificate(URL url, SSLSession session) throws CertificateException {
    Certificate[] certs = session.getPeerCertificates();
    if (certs.length == 0) {
        throw new CertificateException("No certificates found");
    }
    
    X509Certificate cert = (X509Certificate) certs[0];
    byte[] expectedCertHash = ...; // Pre-shared hash
    byte[] actualCertHash = MessageDigest.getInstance("SHA-256").digest(cert.getEncoded());
    
    if (!MessageDigest.isEqual(expectedCertHash, actualCertHash)) {
        throw new CertificateException("Certificate hash mismatch");
    }
}

These remediation techniques ensure that mTLS implementations maintain data integrity by properly validating certificates and rejecting unauthorized connections.

Frequently Asked Questions

How does middleBrick detect integrity failures in mTLS implementations?

middleBrick scans mTLS endpoints by establishing test connections with both valid and invalid certificates. It attempts to connect with expired certificates, certificates from untrusted CAs, and self-signed certificates to verify that the implementation properly rejects these connections. The scanner also examines configuration files and runtime behavior to identify settings like rejectUnauthorized: false or InsecureSkipVerify: true that indicate integrity vulnerabilities.

What are the business risks of integrity failures in mTLS?

Integrity failures in mTLS can lead to complete compromise of supposedly secure communications. Attackers can intercept and modify sensitive data, bypass authentication mechanisms, and gain unauthorized access to protected resources. This can result in data breaches, financial losses, regulatory violations (HIPAA, PCI-DSS, GDPR), and reputational damage. For APIs handling financial transactions or personal data, these failures can have severe legal and financial consequences.