npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
Overview
SSL/TLS inspection (also called SSL decryption, HTTPS inspection, or TLS break-and-inspect) intercepts encrypted traffic between clients and servers to inspect the cleartext content for malware, data exfiltration, policy violations, and command-and-control communications. The inspection device acts as a trusted man-in-the-middle, terminating the TLS session from the client, inspecting the plaintext content, and establishing a new TLS session to the destination server. With over 95% of web traffic now encrypted, organizations without TLS inspection have a massive blind spot. This skill covers configuring TLS inspection on next-generation firewalls, deploying trusted CA certificates, managing exemptions for certificate-pinned applications, and ensuring compliance with privacy regulations.
When to Use
- When conducting security assessments that involve performing ssl tls inspection configuration
- When following incident response procedures for related security events
- When performing scheduled security testing or auditing activities
- When validating security controls through hands-on testing
Prerequisites
- Next-generation firewall or secure web gateway with TLS inspection capability
- Internal Certificate Authority (CA) for signing inspection certificates
- Endpoint certificate management (GPO, MDM, or manual deployment)
- Privacy and legal review for TLS inspection scope
- Understanding of PKI, X.509 certificates, and TLS handshake
Core Concepts
SSL/TLS Inspection Modes
| Mode | Direction | Description |
|---|---|---|
| SSL Forward Proxy | Outbound | Intercepts client-to-internet HTTPS connections |
| SSL Inbound Inspection | Inbound | Decrypts traffic destined for internal servers |
| SSH Proxy | Both | Inspects SSH tunneled traffic |
Forward Proxy Process
Client Firewall/Proxy Web Server
│ │ │
│──TLS ClientHello──────→│ │
│ │──TLS ClientHello───────→│
│ │←─TLS ServerHello────────│
│ │ (real server cert) │
│ │ │
│ │ [Validates server cert] │
│ │ [Generates proxy cert │
│ │ signed by internal CA] │
│ │ │
│←─TLS ServerHello───────│ │
│ (proxy-signed cert) │ │
│ │ │
│──Encrypted data────────→│ [Decrypt, Inspect] │
│ │──Encrypted data────────→│
│←─Encrypted data─────────│ [Decrypt, Inspect] │
│ │←─Encrypted data─────────│Certificate Trust Chain
Enterprise Root CA
└── Subordinate CA (SSL Inspection)
└── Dynamically Generated Server Certificates
(CN matches requested server)Workflow
Step 1: Generate Internal CA for SSL Inspection
# Create private key for SSL Inspection CA
openssl genrsa -aes256 -out ssl-inspect-ca.key 4096
# Create CA certificate (5 year validity)
openssl req -new -x509 -key ssl-inspect-ca.key \
-sha256 -days 1825 \
-out ssl-inspect-ca.crt \
-subj "/C=US/ST=California/O=Corp Inc/OU=Network Security/CN=Corp SSL Inspection CA" \
-extensions v3_ca \
-config <(cat <<EOF
[req]
distinguished_name = req_dn
x509_extensions = v3_ca
[req_dn]
[v3_ca]
basicConstraints = critical,CA:TRUE,pathlen:0
keyUsage = critical,digitalSignature,keyCertSign,cRLSign
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
EOF
)
# Verify certificate
openssl x509 -in ssl-inspect-ca.crt -text -nooutStep 2: Deploy CA Certificate to Endpoints
Windows (Group Policy):
# Import CA cert to trusted root store via GPO
# Computer Configuration > Policies > Windows Settings >
# Security Settings > Public Key Policies > Trusted Root CAs
# Or deploy via PowerShell
Import-Certificate -FilePath "\\server\share\ssl-inspect-ca.crt" `
-CertStoreLocation "Cert:\LocalMachine\Root"
# Verify deployment
Get-ChildItem Cert:\LocalMachine\Root | Where-Object {
$_.Subject -like "*SSL Inspection CA*"
}macOS (MDM profile or manual):
# Install via command line
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain ssl-inspect-ca.crtLinux:
# Ubuntu/Debian
sudo cp ssl-inspect-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
# RHEL/CentOS
sudo cp ssl-inspect-ca.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trustStep 3: Configure Palo Alto SSL Forward Proxy
# Import CA certificate to firewall
# Device > Certificate Management > Certificates > Import
# Set as Forward Trust CA
set shared certificate SSL-Inspect-CA forward-trust-certificate yes
# Create Decryption Profile
set profiles decryption Corporate-Decrypt ssl-forward-proxy block-expired-certificate yes
set profiles decryption Corporate-Decrypt ssl-forward-proxy block-untrusted-issuer yes
set profiles decryption Corporate-Decrypt ssl-forward-proxy block-unknown-cert yes
set profiles decryption Corporate-Decrypt ssl-forward-proxy restrict-cert-exts yes
set profiles decryption Corporate-Decrypt ssl-forward-proxy strip-alpn no
# Minimum TLS version
set profiles decryption Corporate-Decrypt ssl-protocol-settings min-version tls1-2
set profiles decryption Corporate-Decrypt ssl-protocol-settings max-version max
# Decryption policy - decrypt outbound HTTPS
set rulebase decryption rules Decrypt-Outbound from Trust to Untrust
set rulebase decryption rules Decrypt-Outbound source any
set rulebase decryption rules Decrypt-Outbound destination any
set rulebase decryption rules Decrypt-Outbound service any
set rulebase decryption rules Decrypt-Outbound action decrypt
set rulebase decryption rules Decrypt-Outbound type ssl-forward-proxy
set rulebase decryption rules Decrypt-Outbound profile Corporate-DecryptStep 4: Configure Exemptions
Certain applications and categories must be excluded from TLS inspection:
# Exempt certificate-pinned applications
set rulebase decryption rules No-Decrypt-Pinned from Trust to Untrust
set rulebase decryption rules No-Decrypt-Pinned application [ apple-update microsoft-update dropbox-base ]
set rulebase decryption rules No-Decrypt-Pinned action no-decrypt
# Exempt privacy-sensitive categories
set rulebase decryption rules No-Decrypt-Privacy from Trust to Untrust
set rulebase decryption rules No-Decrypt-Privacy category [ health-and-medicine financial-services ]
set rulebase decryption rules No-Decrypt-Privacy action no-decrypt
# Exempt specific high-trust domains
set rulebase decryption rules No-Decrypt-Trusted from Trust to Untrust
set rulebase decryption rules No-Decrypt-Trusted destination [ bank-of-america.com chase.com healthcare.gov ]
set rulebase decryption rules No-Decrypt-Trusted action no-decryptStep 5: Configure Inbound Inspection for Internal Servers
# Import server certificate and private key
# Device > Certificate Management > Certificates > Import
# Inbound inspection policy
set rulebase decryption rules Inspect-WebServers from Untrust to DMZ
set rulebase decryption rules Inspect-WebServers destination [ 10.0.20.10 10.0.20.11 ]
set rulebase decryption rules Inspect-WebServers service service-https
set rulebase decryption rules Inspect-WebServers action decrypt
set rulebase decryption rules Inspect-WebServers type ssl-inbound-inspection
set rulebase decryption rules Inspect-WebServers profile Corporate-DecryptStep 6: Validate SSL Inspection
# Test from client - verify certificate issuer is internal CA
openssl s_client -connect www.google.com:443 -servername www.google.com 2>/dev/null | \
openssl x509 -noout -issuer -subject
# Expected output (with inspection active):
# issuer= /C=US/O=Corp Inc/OU=Network Security/CN=Corp SSL Inspection CA
# subject= /CN=www.google.com
# Verify no certificate errors in browser
# Check firewall decryption logs for errors
# Test with curl
curl -v https://www.example.com 2>&1 | grep "issuer"
# Check decryption statistics on firewall
show system setting ssl-decrypt memory
show system setting ssl-decrypt certificate-cache
show counter global filter category sslPerformance Considerations
| Factor | Impact | Mitigation |
|---|---|---|
| CPU overhead | 50-80% increase per session | Hardware SSL acceleration, dedicated decrypt appliance |
| Throughput reduction | 40-60% typical | Size decryption hardware for peak encrypted traffic |
| Latency increase | 1-5ms additional | Place inspection close to users |
| TLS 1.3 0-RTT | Cannot inspect 0-RTT data | Block 0-RTT or accept risk |
| Certificate pinning | Inspection fails | Add to exemption list |
| QUIC/HTTP3 | Bypasses traditional proxy | Block QUIC, force HTTP/2 |
Compliance and Privacy
- Employee Notice - Notify users that network traffic is subject to inspection
- Privacy Exemptions - Exclude healthcare, financial, and legally privileged traffic
- Data Handling - Inspected cleartext must not be logged or stored unnecessarily
- GDPR Compliance - Document lawful basis for processing encrypted personal data
- Certificate Pinning - Maintain exemption list for applications using HPKP or built-in pins
Best Practices
- Start with Logging - Deploy in detect-only mode first to identify certificate-pinned applications
- Maintain Exemption List - Keep a curated list of applications requiring decryption bypass
- Block QUIC - Block UDP/443 to force HTTP/2 through TLS inspection
- Monitor Certificate Errors - Track decryption errors in firewall logs
- TLS 1.2 Minimum - Enforce TLS 1.2 as minimum version; block SSLv3 and TLS 1.0/1.1
- Key Protection - Store inspection CA private key in HSM for production environments
- Regular CA Rotation - Plan for CA certificate rotation before expiration
References
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 1
api-reference.md2.2 KB
API Reference: SSL/TLS Inspection Configuration
Inspection Validation Commands
| Command | Description |
|---|---|
openssl s_client -connect host:443 -servername host |
Check certificate issuer |
curl -v https://host 2>&1 | grep issuer |
Verify inspection via curl |
show system setting ssl-decrypt memory |
PAN-OS decryption stats |
show counter global filter category ssl |
PAN-OS SSL counters |
CA Deployment Commands
Windows (GPO/PowerShell)
| Command | Description |
|---|---|
Import-Certificate -FilePath ca.crt -CertStoreLocation Cert:\LocalMachine\Root |
Install CA cert |
Get-ChildItem Cert:\LocalMachine\Root | Where Subject -like "*CA*" |
Verify deployment |
Linux
| Command | Description |
|---|---|
cp ca.crt /usr/local/share/ca-certificates/ && update-ca-certificates |
Ubuntu/Debian |
cp ca.crt /etc/pki/ca-trust/source/anchors/ && update-ca-trust |
RHEL/CentOS |
macOS
| Command | Description |
|---|---|
security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ca.crt |
Install CA |
Palo Alto SSL Decryption Policy
| Setting | Description |
|---|---|
ssl-forward-proxy |
Outbound HTTPS inspection |
ssl-inbound-inspection |
Inbound to internal servers |
block-expired-certificate yes |
Block expired server certs |
min-version tls1-2 |
Enforce TLS 1.2 minimum |
Exemption Categories
| Category | Reason |
|---|---|
| Certificate-pinned apps | Apple Update, Microsoft Update, Dropbox |
| Healthcare/Financial | HIPAA/PCI privacy requirements |
| Legal privilege | Attorney-client communication |
Python Libraries
| Library | Version | Purpose |
|---|---|---|
ssl |
stdlib | TLS handshake, version testing |
socket |
stdlib | TCP connections |
subprocess |
stdlib | PowerShell CA verification |
References
- Palo Alto SSL Decryption: https://docs.paloaltonetworks.com/network-security/decryption
- NIST SP 800-52 Rev 2: https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final
- US-CERT HTTPS Inspection: https://www.cisa.gov/news-events/alerts/2017/03/13/https-interception-weakens-tls-security
Scripts 1
agent.py6.3 KB
#!/usr/bin/env python3
"""Agent for SSL/TLS inspection configuration validation.
Verifies TLS inspection is working by comparing certificate issuers,
validates CA deployment on endpoints, checks TLS version enforcement,
audits decryption exemption lists, and monitors inspection health.
"""
import ssl
import socket
import json
import sys
import subprocess
from datetime import datetime
class TLSInspectionAgent:
"""Validates SSL/TLS inspection configuration and health."""
def __init__(self, internal_ca_cn=None):
self.internal_ca_cn = internal_ca_cn or "SSL Inspection CA"
self.results = []
def check_inspection_active(self, hostname, port=443):
"""Connect to external host and check if cert is signed by internal CA."""
try:
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
with ctx.wrap_socket(socket.socket(),
server_hostname=hostname) as s:
s.settimeout(10)
s.connect((hostname, port))
cert = s.getpeercert(binary_form=False)
if not cert:
der = s.getpeercert(binary_form=True)
return {"hostname": hostname, "inspection": "unknown",
"note": "Could not parse certificate"}
issuer = dict(x[0] for x in cert.get("issuer", ()))
issuer_cn = issuer.get("commonName", "")
issuer_org = issuer.get("organizationName", "")
subject = dict(x[0] for x in cert.get("subject", ()))
is_inspected = self.internal_ca_cn.lower() in issuer_cn.lower()
result = {
"hostname": hostname, "port": port,
"subject_cn": subject.get("commonName", ""),
"issuer_cn": issuer_cn,
"issuer_org": issuer_org,
"inspection_active": is_inspected,
"tls_version": s.version() if hasattr(s, "version") else "unknown",
}
self.results.append(result)
return result
except (socket.error, ssl.SSLError, OSError) as exc:
result = {"hostname": hostname, "error": str(exc)}
self.results.append(result)
return result
def check_tls_version(self, hostname, port=443):
"""Check minimum TLS version supported by the inspecting proxy."""
versions_to_test = [
("TLSv1.0", ssl.TLSVersion.TLSv1 if hasattr(ssl.TLSVersion, "TLSv1") else None),
("TLSv1.1", ssl.TLSVersion.TLSv1_1 if hasattr(ssl.TLSVersion, "TLSv1_1") else None),
("TLSv1.2", ssl.TLSVersion.TLSv1_2),
("TLSv1.3", ssl.TLSVersion.TLSv1_3 if hasattr(ssl.TLSVersion, "TLSv1_3") else None),
]
results = []
for name, ver in versions_to_test:
if ver is None:
results.append({"version": name, "status": "not_testable"})
continue
try:
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
ctx.minimum_version = ver
ctx.maximum_version = ver
with ctx.wrap_socket(socket.socket(),
server_hostname=hostname) as s:
s.settimeout(5)
s.connect((hostname, port))
results.append({"version": name, "status": "accepted"})
except (ssl.SSLError, socket.error):
results.append({"version": name, "status": "rejected"})
return results
def verify_ca_deployed(self):
"""Check if the inspection CA certificate is in the local trust store."""
try:
result = subprocess.run(
["powershell", "-NoProfile", "-Command",
f'Get-ChildItem Cert:\\LocalMachine\\Root | '
f'Where-Object {{$_.Subject -like "*{self.internal_ca_cn}*"}} | '
f'Select-Object Subject,NotAfter,Thumbprint | ConvertTo-Json'],
capture_output=True, text=True, timeout=30
)
if result.returncode == 0 and result.stdout.strip():
data = json.loads(result.stdout)
if isinstance(data, dict):
data = [data]
return {"ca_deployed": True, "certificates": data}
except (subprocess.TimeoutExpired, json.JSONDecodeError, FileNotFoundError):
pass
return {"ca_deployed": False}
def audit_exemptions(self, exempt_domains):
"""Verify exempted domains bypass inspection (show original CA)."""
results = []
for domain in exempt_domains:
info = self.check_inspection_active(domain)
results.append({
"domain": domain,
"correctly_exempted": not info.get("inspection_active", True),
"issuer": info.get("issuer_cn", ""),
})
return results
def scan_multiple(self, hostnames):
"""Check inspection status for multiple external hosts."""
for host in hostnames:
self.check_inspection_active(host)
return self.results
def generate_report(self):
"""Generate inspection validation report."""
inspected = sum(1 for r in self.results if r.get("inspection_active"))
not_inspected = sum(1 for r in self.results
if r.get("inspection_active") is False)
errors = sum(1 for r in self.results if "error" in r)
report = {
"report_date": datetime.utcnow().isoformat(),
"internal_ca": self.internal_ca_cn,
"total_tested": len(self.results),
"inspected": inspected,
"not_inspected": not_inspected,
"errors": errors,
"results": self.results,
}
print(json.dumps(report, indent=2, default=str))
return report
def main():
ca_cn = sys.argv[1] if len(sys.argv) > 1 else "SSL Inspection CA"
hosts = sys.argv[2:] if len(sys.argv) > 2 else [
"www.google.com", "github.com", "www.example.com"]
agent = TLSInspectionAgent(internal_ca_cn=ca_cn)
agent.scan_multiple(hosts)
agent.generate_report()
if __name__ == "__main__":
main()