HIGH log injectionmutual tls

Log Injection with Mutual Tls

How Log Injection Manifests in Mutual Tls

Log injection in Mutual Tls environments occurs when untrusted data from client certificates or TLS handshake metadata is improperly logged without sanitization. Since Mutual Tls establishes trust through client certificates, attackers can craft certificates with malicious payloads that exploit logging systems.

Consider a Mutual Tls server that logs client certificate details:

func handleRequest(w http.ResponseWriter, r *http.Request) {
    cert := r.TLS.PeerCertificates[0]
    log.Printf("Client: %s, Serial: %s, Issuer: %s", 
        cert.Subject.CommonName, 
        cert.SerialNumber, 
        cert.Issuer.CommonName)
    w.Write([]byte("OK"))
}

An attacker can create a certificate with a CommonName containing newline characters and log injection payloads:

CN=victim.com
ERROR: Panic: deliberate crash
[secret-data]

When logged, this creates:

Client: victim.com
ERROR: Panic: deliberate crash
[secret-data], Serial: ..., Issuer: ...

This corrupts log integrity and can trigger alerts or hide malicious activity. The injection works because TLS certificate fields are treated as trusted input without validation.

Another attack vector involves X.509 extension fields. Custom extensions in certificates can carry arbitrary data:

from cryptography.x509.oid import ExtensionOID
from cryptography import x509
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa

# Create malicious certificate with log injection in extension
key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
cert = x509.CertificateBuilder().subject_name(x509.Name([
    x509.NameAttribute(x509.NameOID.COMMON_NAME, 'victim.com\nALERT: Injection Detected\n')
])).issuer_name(x509.NameOID.COMMON_NAME).add_extension(
    x509.UnrecognizedExtension(
        ExtensionOID.BASIC_CONSTRAINTS.value, 
        b'\n[hidden-data]\n'
    ), critical=False).sign(key, hashes.SHA256())

Servers logging these extension values without sanitization create the same injection vulnerabilities. The Mutual Tls trust model means these certificates are accepted and processed without the scrutiny applied to other untrusted inputs.

Mutual Tls-Specific Detection

Detecting log injection in Mutual Tls requires examining how certificate data flows through your logging pipeline. Start by analyzing certificate parsing and logging code paths.

Static analysis should identify:

# Find certificate field logging
grep -r "PeerCertificates\|clientAuth\|mtls" --include="*.go" | 
  grep -E "(log\.Print|fmt\.Print|logger\.Info)" | 
  head -10

Dynamic testing involves creating test certificates with known injection payloads and observing log output. Use OpenSSL to generate test certificates:

# Generate certificate with newline injection
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem \
  -days 365 -nodes -subj "/CN=victim.com%0ALogInjectionTest%0A"

middleBrick's black-box scanning approach tests Mutual Tls endpoints by establishing connections with crafted certificates and analyzing log responses. The scanner detects:

Detection MethodMutual Tls SpecificDetection Signal
Certificate Field AnalysisNewline characters in CN/Serial fields
Extension ParsingMalformed or oversized extensions
Handshake MetadataAbnormal TLS version/extension data
Log Output AnalysisUnexpected formatting or injection patterns

The scanner's LLM security module also checks for AI-specific injection patterns in certificate fields, as some systems use certificate data for AI model inputs or logging.

Runtime monitoring should watch for:

# Prometheus log monitoring rules
- alert: MutualTlsLogInjection
  expr: increase(log_lines_total{job="mtls-api"} offset 5m) > 100
  for: 2m
  labels:
    severity: critical
  annotations:
    summary: "Suspicious log volume from Mutual Tls endpoint"
    description: "High log volume may indicate injection attack via certificate fields"

Network-based detection can identify abnormal certificate patterns before they reach application layers:

tcpdump -i eth0 -nn -tttt dst port 443 and "(ip[2:2] < 40)" | 
  while read line; do
    if echo "$line" | grep -q "Client Hello"; then
      # Check for abnormal certificate characteristics
      echo "$line" | grep -E "(\n|0x0a)" >/dev/null && 
        echo "Potential injection attempt detected"
    fi
done

Mutual Tls-Specific Remediation

Remediation requires sanitizing certificate data before logging and validating certificate contents. The core principle: treat all certificate fields as untrusted input regardless of Mutual Tls trust model.

Go implementation with proper sanitization:

import (
    "crypto/x509"
    "regexp"
    "strings"
    "log"
)

var logInjectionPattern = regexp.MustCompile(`[\n\r\t\x00-\x1f\x7f-\x9f]`)

func sanitizeCertificateField(input string) string {
    return logInjectionPattern.ReplaceAllString(input, " ")
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
    if r.TLS == nil || len(r.TLS.PeerCertificates) == 0 {
        http.Error(w, "Mutual Tls required", http.StatusUnauthorized)
        return
    }
    
    cert := r.TLS.PeerCertificates[0]
    
    // Sanitize all certificate fields before logging
    safeCN := sanitizeCertificateField(cert.Subject.CommonName)
    safeSerial := sanitizeCertificateField(cert.SerialNumber.String())
    safeIssuer := sanitizeCertificateField(cert.Issuer.CommonName)
    
    log.Printf("Client: %s, Serial: %s, Issuer: %s", 
        safeCN, safeSerial, safeIssuer)
    
    w.Write([]byte("OK"))
}

Python with Flask and sanitization:

from flask import Flask, request
import re
import logging
from cryptography import x509
from cryptography.hazmat.primitives import serialization

log_injection_re = re.compile(r'[\n\r\t\x00-\x1f\x7f-\x9f]')

def sanitize_cert_field(value: str) -> str:
    return log_injection_re.sub(' ', value)

def sanitize_cert_extensions(cert: x509.Certificate) -> dict:
    sanitized = {}
    for ext in cert.extensions:
        sanitized[ext.oid.dotted_string] = 
            sanitize_cert_field(str(ext.value))
    return sanitized

app = Flask(__name__)

@app.route('/')
def mtls_endpoint():
    if not request.is_secure:
        return 'Mutual Tls required', 401
    
    cert = request.client_cert
    if cert is None:
        return 'Client certificate required', 401
    
    # Parse and sanitize certificate
    parsed_cert = x509.load_pem_x509_certificate(cert)
    safe_cn = sanitize_cert_field(parsed_cert.subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME)[0].value)
    safe_serial = sanitize_cert_field(str(parsed_cert.serial_number))
    safe_issuer = sanitize_cert_field(parsed_cert.issuer.get_attributes_for_oid(x509.NameOID.COMMON_NAME)[0].value)
    safe_extensions = sanitize_cert_extensions(parsed_cert)
    
    # Log sanitized data
    app.logger.info(f"Client: {safe_cn}, Serial: {safe_serial}, Issuer: {safe_issuer}")
    
    return 'OK', 200

if __name__ == '__main__':
    app.run(ssl_context='mutual')

Certificate validation should reject suspicious certificates before they reach application logic:

func validateCertificate(cert *x509.Certificate) error {
    // Check for injection-prone characters
    if strings.ContainsAny(cert.Subject.CommonName, "\n\r\t") {
        return errors.New("certificate contains newline characters")
    }
    
    // Validate extension lengths
    for _, ext := range cert.Extensions {
        if len(ext.Value) > 1024 {
            return errors.New("extension too large")
        }
    }
    
    return nil
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
    cert := r.TLS.PeerCertificates[0]
    
    if err := validateCertificate(cert); err != nil {
        http.Error(w, "Invalid certificate", http.StatusBadRequest)
        return
    }
    
    // Continue with sanitized logging
}

Network-level filtering with Nginx for Mutual Tls:

server {
    listen 443 ssl http2;
    ssl_certificate /path/to/server.crt;
    ssl_certificate_key /path/to/server.key;
    ssl_client_certificate /path/to/ca.crt;
    ssl_verify_client on;
    
    # Custom filter for suspicious certificates
    location /api {
        if ($ssl_client_s_dn ~* "(\n|\\r|\\t)") {
            return 400 "Invalid certificate";
        }
        
        # Sanitize certificate fields in logs
        log_format mtls_combined '$remote_addr - $ssl_client_s_dn_san_dns '
                                 '$ssl_client_verify $request_uri';
        access_log /var/log/nginx/mtls_access.log mtls_combined;
        
        proxy_pass http://app_server;
    }
}

Frequently Asked Questions

How does Mutual Tls authentication affect log injection risk?
Mutual Tls creates a false sense of security because the client certificate is trusted, leading developers to log certificate fields without sanitization. The trust model means malicious certificates are accepted and processed, allowing attackers to inject payloads through certificate fields that are then logged directly. This combines the injection surface of untrusted input with the trust assumptions of Mutual Tls.
Can middleBrick detect log injection in Mutual Tls environments?
Yes, middleBrick's black-box scanning tests Mutual Tls endpoints by establishing connections with crafted certificates containing injection payloads. The scanner analyzes log responses for injection patterns, checks certificate field handling, and validates that certificate data is properly sanitized before logging. It tests all 12 security categories including authentication bypass and data exposure specific to Mutual Tls configurations.