CWE-295 in APIs
- CWE ID
- CWE-295
- Category
- Encryption
- Severity
- HIGH
- Short Name
- Certificate Issues
What is CWE-295?
CWE-295, officially titled Improper Certificate Validation, describes a vulnerability where software fails to properly validate certificates used for authentication or encryption. This weakness allows attackers to present fraudulent certificates that appear legitimate to the application, enabling man-in-the-middle attacks, data interception, or impersonation of trusted services.
The core issue stems from incomplete or incorrect certificate validation logic. Applications might accept certificates with expired dates, self-signed certificates from untrusted authorities, or certificates that don't match the expected hostname. Without proper validation, the cryptographic assurances that TLS/SSL certificates provide become meaningless.
According to the CWE description, this weakness occurs when "the software does not validate, or incorrectly validates, a certificate." This can manifest in various ways: failing to check certificate chains, accepting certificates from untrusted CAs, or not verifying certificate revocation status.
CWE-295 in API Contexts
APIs are particularly vulnerable to improper certificate validation because they often communicate with external services, third-party APIs, and cloud infrastructure. Several API-specific scenarios commonly exhibit this weakness:
- Third-party service integration: When an API calls external services (payment processors, analytics platforms, cloud storage), it must validate those services' certificates to ensure it's not connecting to an imposter.
- Microservices communication: In distributed architectures, services communicate over internal networks but still require proper certificate validation to prevent lateral movement attacks.
- Webhook implementations: APIs that receive webhooks from external providers must validate those providers' certificates to prevent webhook spoofing.
- Client-side certificate authentication: APIs using mutual TLS for client authentication must validate client certificates properly to prevent unauthorized access.
A common mistake occurs when developers disable certificate validation during development and forget to re-enable it in production. Another frequent issue is accepting self-signed certificates in staging environments without proper controls to prevent those configurations from leaking into production.
Detection
Detecting improper certificate validation requires both static analysis and dynamic testing approaches. Here's how to identify this weakness:
- Code review for validation logic: Look for certificate validation calls and verify they check all required properties (expiration, issuer, hostname matching, revocation status).
- Network traffic analysis: Use tools like Wireshark or mitmproxy to intercept TLS connections and verify certificate validation is occurring.
Automated scanning with middleBrick: middleBrick's Encryption category specifically tests for certificate validation issues. The scanner attempts to intercept connections using self-signed certificates and verifies whether the API accepts them. This black-box approach catches configuration issues that code review might miss.
middlebrick scan https://api.example.comThe scan tests whether the API properly validates certificates presented by the server, checking for acceptance of self-signed certificates, expired certificates, and hostname mismatches.
- Certificate pinning verification: If your API implements certificate pinning, verify that it properly validates pinned certificates and handles certificate rotation.
- Environment-specific testing: Test API clients in all environments (dev, staging, prod) to ensure certificate validation isn't disabled in production.
middleBrick's encryption tests run in parallel with other security checks, providing a comprehensive view of certificate validation weaknesses alongside other API security concerns.
Remediation
Fixing improper certificate validation requires implementing comprehensive certificate validation logic. Here are code-level solutions for different scenarios:
Server-side certificate validation
When your API acts as a client connecting to external services:
import requests
from requests.adapters import HTTPAdapter
from urllib3.poolmanager import PoolManager
from urllib3.util.ssl_ import create_urllib3_context
class ValidatedTLSAdapter(HTTPAdapter):
"""Adapter that enforces strict certificate validation."""
def init_poolmanager(self, *args, **kwargs):
# Create SSL context with strict validation
context = create_urllib3_context()
context.check_hostname = True
context.verify_mode = ssl.CERT_REQUIRED
# Verify certificate chain
kwargs['ssl_context'] = context
return super().init_poolmanager(*args, **kwargs)Mutual TLS client authentication
When your API requires clients to present certificates:
const express = require('express');
const https = require('https');
const fs = require('fs');
const app = express();
app.use((req, res, next) => {
const cert = req.connection.getPeerCertificate();
// Check certificate validity
if (!cert || !cert.validity) {
return res.status(401).json({ error: 'Invalid certificate' });
}
const now = new Date();
if (now < new Date(cert.valid_from) || now > new Date(cert.valid_to)) {
return res.status(401).json({ error: 'Certificate expired' });
}
// Check certificate issuer
if (cert.issuer.CN !== 'Expected CA Name') {
return res.status(401).json({ error: 'Untrusted certificate authority' });
}
next();
});Certificate revocation checking
Verify certificates haven't been revoked:
import java.security.cert.*;
import java.net.URI;
public class CertificateValidator {
public static void validateCertificate(X509Certificate cert) throws CertificateException {
// Check expiration
cert.checkValidity();
// Verify certificate chain
CertificateFactory cf = CertificateFactory.getInstance("X.509");
CertPathValidator validator = CertPathValidator.getInstance("PKIX");
// Build certification path
CertPath certPath = cf.generateCertPath(Collections.singletonList(cert));
// Perform revocation checking
PKIXParameters params = new PKIXParameters(trustedAnchors);
params.setRevocationEnabled(true);
params.addCertStore(CertStore.getInstance("Collection",
new CollectionCertStoreParameters(revocationList)));
validator.validate(certPath, params);
}
}Configuration best practices
Beyond code, ensure proper configuration:
- Never disable certificate validation in production (common anti-patterns:
verify=False,sslVerifyPeer: false) - Use certificate pinning for critical connections to prevent MITM attacks
- Implement certificate rotation procedures with proper validation
- Monitor certificate expiration dates and set up alerts
- Test certificate validation in all environments before deployment