compliance governance

Implementing PCI DSS Compliance Controls

PCI DSS 4.0.1 establishes 12 requirements across 6 control objectives for organizations that store, process, or transmit cardholder data. With PCI DSS 3.2.1 retiring April 2024 and 51 new requirements becoming mandatory March 31, 2025, this skill covers implementing all requirements including the new customized validation approach, enhanced authentication, and continuous monitoring controls.

cardholder-datacompliancegovernancepayment-securitypci-dss
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

Overview

PCI DSS 4.0.1 establishes 12 requirements across 6 control objectives for organizations that store, process, or transmit cardholder data. With PCI DSS 3.2.1 retiring April 2024 and 51 new requirements becoming mandatory March 31, 2025, this skill covers implementing all requirements including the new customized validation approach, enhanced authentication, and continuous monitoring controls.

When to Use

  • When deploying or configuring implementing pci dss compliance controls capabilities in your environment
  • When establishing security controls aligned to compliance requirements
  • When building or improving security architecture for this domain
  • When conducting security assessments that require this implementation

Prerequisites

  • Understanding of payment card processing flows and cardholder data environment (CDE)
  • Knowledge of network segmentation and security architecture
  • Access to cardholder data environment for scoping
  • Understanding of PCI compliance validation levels (merchant levels 1-4, service provider levels 1-2)

Core Concepts

12 PCI DSS Requirements by Control Objective

Build and Maintain a Secure Network and Systems

  1. Install and maintain network security controls (firewalls, NSCs)
  2. Apply secure configurations to all system components

Protect Account Data 3. Protect stored account data (encryption, tokenization, truncation) 4. Protect cardholder data with strong cryptography during transmission

Maintain a Vulnerability Management Program 5. Protect all systems and networks from malicious software 6. Develop and maintain secure systems and software

Implement Strong Access Control Measures 7. Restrict access to system components and cardholder data by business need to know 8. Identify users and authenticate access to system components 9. Restrict physical access to cardholder data

Regularly Monitor and Test Networks 10. Log and monitor all access to system components and cardholder data 11. Test security of systems and networks regularly

Maintain an Information Security Policy 12. Support information security with organizational policies and programs

Key PCI DSS 4.0 Changes

  • Customized Approach: Alternative to defined approach, allowing custom control design with objective-based validation
  • MFA for all CDE access: Extended beyond admin to all access to cardholder data (Req 8.4.2)
  • Targeted Risk Analysis: Organizations perform their own risk analysis for flexible requirements
  • Authenticated Vulnerability Scanning: Internal scans must use authenticated scanning (Req 11.3.1.1)
  • Anti-phishing mechanisms: Technical controls to detect and protect against phishing (Req 5.4.1)
  • Automated log review: Automated mechanisms for review of audit logs (Req 10.4.1.1)

Workflow

Phase 1: Scoping and Assessment (Weeks 1-4)

  1. Identify all cardholder data flows (card present, card not present, storage)
  2. Define Cardholder Data Environment (CDE) boundaries
  3. Validate network segmentation effectiveness
  4. Determine compliance validation level
  5. Conduct PCI DSS gap assessment against all 12 requirements

Phase 2: Network and System Security (Weeks 5-12)

  1. Deploy and configure network security controls (Req 1)
  2. Implement network segmentation to minimize CDE scope
  3. Harden system configurations using CIS Benchmarks (Req 2)
  4. Implement WAF for public-facing web applications (Req 6.4.1)
  5. Deploy anti-malware on all in-scope systems (Req 5)

Phase 3: Data Protection (Weeks 13-20)

  1. Implement encryption for stored cardholder data (Req 3)
  2. Deploy tokenization where possible to reduce scope
  3. Enforce TLS 1.2+ for all cardholder data transmission (Req 4)
  4. Implement key management procedures
  5. Deploy data discovery tools to locate unencrypted cardholder data

Phase 4: Access Controls (Weeks 21-28)

  1. Implement RBAC based on business need to know (Req 7)
  2. Deploy MFA for all access to CDE (Req 8)
  3. Implement unique user IDs for all users
  4. Enforce password policies meeting PCI DSS 4.0 requirements
  5. Implement physical access controls for CDE facilities (Req 9)

Phase 5: Monitoring and Testing (Weeks 29-36)

  1. Deploy centralized logging for all CDE components (Req 10)
  2. Implement automated log review mechanisms
  3. Conduct internal and external vulnerability scans (Req 11)
  4. Perform penetration testing (internal and external)
  5. Implement file integrity monitoring (FIM) for critical files

Phase 6: Policy and Governance (Weeks 37-42)

  1. Develop comprehensive information security policy (Req 12)
  2. Implement security awareness training including anti-phishing
  3. Establish incident response plan specific to cardholder data
  4. Conduct targeted risk analyses for flexible requirements
  5. Document and validate all controls for assessment

Key Artifacts

  • CDE Scope Documentation and Network Diagrams
  • Self-Assessment Questionnaire (SAQ) or Report on Compliance (ROC)
  • Attestation of Compliance (AOC)
  • Quarterly ASV Scan Reports
  • Annual Penetration Test Report
  • Risk Assessment Documentation
  • Security Policies and Procedures

Common Pitfalls

  • Scope creep due to inadequate network segmentation
  • Storing prohibited data (CVV, full track data) after authorization
  • Missing the March 2025 deadline for new mandatory requirements
  • Treating PCI DSS as annual compliance rather than continuous security
  • Not including cloud and container environments in CDE scope

References

Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 3

api-reference.md6.3 KB

API Reference: PCI DSS Compliance Control Audit

Libraries Used

Library Purpose
requests API calls to scan engines and cloud services
jinja2 Generate compliance assessment reports
json Parse control status and evidence data
subprocess Run network segmentation and encryption checks
csv Export compliance matrices

Installation

pip install requests jinja2

PCI DSS v4.0 Requirements Map

Requirement Title Automated Checks
1 Install and maintain network security controls Firewall rules, segmentation testing
2 Apply secure configurations Default credential scan, hardening baselines
3 Protect stored account data Encryption at rest, key management
4 Protect cardholder data with strong cryptography during transmission TLS version, cipher suites
5 Protect all systems against malware AV status, EDR coverage
6 Develop and maintain secure systems Vulnerability scans, SAST/DAST
7 Restrict access by business need to know RBAC review, access logs
8 Identify users and authenticate access MFA status, password policy
9 Restrict physical access to cardholder data Physical access logs
10 Log and monitor all access Log aggregation, SIEM alerts
11 Test security of systems regularly Penetration tests, IDS/IPS
12 Support information security with policies Policy review dates

Core Compliance Checks

Requirement 2: Default Credentials Check

import requests
 
DEFAULT_CREDS = [
    ("admin", "admin"), ("admin", "password"), ("root", "root"),
    ("admin", ""), ("user", "user"), ("test", "test"),
]
 
def check_default_credentials(target_url):
    findings = []
    for username, password in DEFAULT_CREDS:
        try:
            resp = requests.post(
                f"{target_url}/login",
                data={"username": username, "password": password},
                timeout=10,
                allow_redirects=False,
            )
            if resp.status_code in (200, 302):
                findings.append({
                    "target": target_url,
                    "username": username,
                    "requirement": "2.2.2",
                    "severity": "critical",
                })
        except requests.RequestException:
            pass
    return findings

Requirement 4: TLS Configuration Check

import ssl
import socket
 
def check_tls_config(hostname, port=443):
    findings = []
    context = ssl.create_default_context()
    with socket.create_connection((hostname, port), timeout=10) as sock:
        with context.wrap_socket(sock, server_hostname=hostname) as ssock:
            protocol = ssock.version()
            cipher = ssock.cipher()
            cert = ssock.getpeercert()
 
            # Check TLS version (must be 1.2+)
            if protocol in ("TLSv1", "TLSv1.1"):
                findings.append({
                    "check": "tls_version",
                    "requirement": "4.2.1",
                    "severity": "high",
                    "detail": f"Weak TLS version: {protocol}",
                })
 
            # Check cipher strength
            if cipher and cipher[2] < 128:
                findings.append({
                    "check": "cipher_strength",
                    "requirement": "4.2.1",
                    "severity": "high",
                    "detail": f"Weak cipher: {cipher[0]} ({cipher[2]} bits)",
                })
 
    return {"protocol": protocol, "cipher": cipher[0], "findings": findings}

Requirement 8: MFA and Password Policy

def check_password_policy(identity_provider_url, headers):
    resp = requests.get(
        f"{identity_provider_url}/api/v1/policies/password",
        headers=headers,
        timeout=30,
    )
    policy = resp.json()
 
    findings = []
    if policy.get("minLength", 0) < 12:
        findings.append({
            "check": "password_length",
            "requirement": "8.3.6",
            "severity": "medium",
            "detail": f"Min password length {policy['minLength']} < 12",
        })
    if not policy.get("requireUppercase"):
        findings.append({
            "check": "password_complexity",
            "requirement": "8.3.6",
            "severity": "low",
            "detail": "Uppercase not required",
        })
    return findings

Requirement 10: Log Monitoring Check

def check_logging_coverage(siem_url, siem_headers):
    """Verify all CDE systems forward logs to SIEM."""
    resp = requests.get(
        f"{siem_url}/api/sources",
        headers=siem_headers,
        timeout=30,
    )
    active_sources = resp.json().get("sources", [])
    return {
        "total_sources": len(active_sources),
        "requirement": "10.2",
        "active": [s for s in active_sources if s.get("status") == "active"],
        "inactive": [s for s in active_sources if s.get("status") != "active"],
    }

Generate Compliance Report

from jinja2 import Template
 
REPORT_TEMPLATE = """
# PCI DSS v4.0 Compliance Assessment
 
Generated: {{ timestamp }}
Scope: {{ scope }}
 
## Summary
- Total Controls: {{ total }}
- Compliant: {{ compliant }}
- Non-Compliant: {{ non_compliant }}
- Compliance Rate: {{ rate }}%
 
## Findings
{% for finding in findings %}
### {{ finding.requirement }} — {{ finding.check }}
- **Severity**: {{ finding.severity }}
- **Detail**: {{ finding.detail }}
{% endfor %}
"""
 
def generate_report(findings, scope, timestamp):
    compliant = sum(1 for f in findings if not f.get("findings"))
    template = Template(REPORT_TEMPLATE)
    return template.render(
        timestamp=timestamp,
        scope=scope,
        total=len(findings),
        compliant=compliant,
        non_compliant=len(findings) - compliant,
        rate=round(compliant / len(findings) * 100, 1),
        findings=[f for f in findings if f.get("findings")],
    )

Output Format

{
  "assessment_date": "2025-01-15",
  "pci_dss_version": "4.0",
  "scope": "Cardholder Data Environment",
  "total_requirements": 12,
  "compliant": 9,
  "non_compliant": 3,
  "findings": [
    {
      "requirement": "4.2.1",
      "check": "tls_version",
      "severity": "high",
      "detail": "Payment gateway using TLSv1.1",
      "remediation": "Upgrade to TLS 1.2 or higher"
    }
  ]
}
standards.md1.1 KB

Implementing PCI DSS Compliance Controls - Standards Reference

Primary Standard

  • Standard: PCI DSS v4.0.1
  • Governing Body: PCI Security Standards Council

Key Requirements

  • Requirement 1: Install and maintain network security controls
  • Requirement 2: Apply secure configurations to all system components
  • Requirement 3: Protect stored account data
  • Requirement 4: Protect cardholder data with strong cryptography during transmission
  • Requirement 5: Protect all systems and networks from malicious software
  • Requirement 6: Develop and maintain secure systems and software
  • Requirement 7: Restrict access by business need to know
  • Requirement 8: Identify users and authenticate access
  • Requirement 9: Restrict physical access to cardholder data
  • Requirement 10: Log and monitor all access to system components
  • Requirement 11: Test security of systems and networks regularly
  • Requirement 12: Support information security with policies and programs

Cross-References

  • ISO/IEC 27001:2022
  • NIST Cybersecurity Framework 2.0
  • CIS Controls v8.1
  • COBIT 2019
workflows.md1.6 KB

Implementing PCI DSS Compliance Controls - Workflows

Workflow 1: Assessment and Planning

Start
  |
  v
[Scope Definition]
  - Define boundaries and objectives
  - Identify stakeholders
  - Gather existing documentation
  |
  v
[Current State Assessment]
  - Review existing controls
  - Identify gaps against requirements
  - Document findings
  |
  v
[Gap Analysis]
  - Compare current vs required state
  - Prioritize gaps by risk
  - Estimate remediation effort
  |
  v
[Remediation Planning]
  - Define action items with owners
  - Set timelines and milestones
  - Allocate resources and budget
  |
  v
End

Workflow 2: Implementation

Start
  |
  v
[Policy and Procedure Development]
  - Draft policies aligned to standard
  - Review with stakeholders
  - Obtain management approval
  |
  v
[Technical Control Deployment]
  - Implement technical controls
  - Configure monitoring and alerting
  - Validate control effectiveness
  |
  v
[Training and Awareness]
  - Train relevant personnel
  - Communicate policy changes
  - Document training completion
  |
  v
[Verification and Testing]
  - Test controls against requirements
  - Document evidence of operation
  - Address deficiencies
  |
  v
End

Workflow 3: Ongoing Compliance

Start
  |
  v
[Continuous Monitoring]
  - Monitor control effectiveness
  - Track compliance metrics
  - Report to management
  |
  v
[Periodic Review]
  - Annual reassessment
  - Update for regulatory changes
  - Incorporate lessons learned
  |
  v
[Audit and Certification]
  - Internal audit programme
  - External audit/assessment
  - Address findings
  |
  v
End

Scripts 1

agent.py12.0 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""PCI DSS compliance control audit agent.

Audits systems and configurations against PCI DSS v4.0 requirements
including network segmentation, encryption, access controls, logging,
vulnerability management, and secure configuration checks.
"""
import argparse
import json
import os
import re
import socket
import ssl
import subprocess
import sys
from datetime import datetime, timezone


def check_tls_configuration(host, port=443):
    """PCI DSS Req 4.2.1 - Strong cryptography for transmission."""
    findings = []
    print(f"[*] Req 4.2.1: Checking TLS on {host}:{port}")
    try:
        context = ssl.create_default_context()
        with socket.create_connection((host, port), timeout=10) as sock:
            with context.wrap_socket(sock, server_hostname=host) as ssock:
                protocol = ssock.version()
                cipher = ssock.cipher()
                if protocol in ("TLSv1.0", "TLSv1.1", "SSLv3", "SSLv2"):
                    findings.append({
                        "requirement": "4.2.1", "check": "TLS Protocol Version",
                        "status": "FAIL", "severity": "CRITICAL",
                        "detail": f"Deprecated protocol: {protocol}",
                    })
                else:
                    findings.append({
                        "requirement": "4.2.1", "check": "TLS Protocol Version",
                        "status": "PASS", "severity": "INFO",
                        "detail": f"Protocol: {protocol}",
                    })
                if cipher:
                    weak_ciphers = ["RC4", "DES", "3DES", "NULL", "EXPORT", "MD5"]
                    if any(w in cipher[0] for w in weak_ciphers):
                        findings.append({
                            "requirement": "4.2.1", "check": "Cipher Strength",
                            "status": "FAIL", "severity": "HIGH",
                            "detail": f"Weak cipher: {cipher[0]}",
                        })
                    else:
                        findings.append({
                            "requirement": "4.2.1", "check": "Cipher Strength",
                            "status": "PASS", "severity": "INFO",
                            "detail": f"Cipher: {cipher[0]} ({cipher[2]} bits)",
                        })
    except Exception as e:
        findings.append({
            "requirement": "4.2.1", "check": "TLS Connection",
            "status": "ERROR", "severity": "HIGH", "detail": str(e)[:100],
        })
    return findings


def check_password_policy():
    """PCI DSS Req 8.3.6 - Password complexity requirements."""
    findings = []
    print("[*] Req 8.3.6: Checking password policy")

    if sys.platform != "win32":
        # Check PAM password quality
        pam_files = ["/etc/pam.d/common-password", "/etc/pam.d/system-auth",
                     "/etc/security/pwquality.conf"]
        for pam_file in pam_files:
            if os.path.isfile(pam_file):
                with open(pam_file, "r") as f:
                    content = f.read()
                if "minlen" in content:
                    match = re.search(r'minlen\s*=\s*(\d+)', content)
                    if match and int(match.group(1)) >= 12:
                        findings.append({
                            "requirement": "8.3.6", "check": "Min password length",
                            "status": "PASS", "severity": "INFO",
                            "detail": f"minlen={match.group(1)} in {pam_file}",
                        })
                    else:
                        findings.append({
                            "requirement": "8.3.6", "check": "Min password length",
                            "status": "FAIL", "severity": "HIGH",
                            "detail": f"Password minlen < 12 in {pam_file}",
                        })
                break
        else:
            findings.append({
                "requirement": "8.3.6", "check": "Password policy config",
                "status": "WARN", "severity": "MEDIUM",
                "detail": "Could not find PAM password config",
            })
    return findings


def check_audit_logging():
    """PCI DSS Req 10.2 - Audit logging configuration."""
    findings = []
    print("[*] Req 10.2: Checking audit logging")

    if sys.platform != "win32":
        # Check auditd
        result = subprocess.run(
            ["systemctl", "is-active", "auditd"],
            capture_output=True, text=True, timeout=10,
        )
        if result.stdout.strip() == "active":
            findings.append({
                "requirement": "10.2", "check": "Audit daemon running",
                "status": "PASS", "severity": "INFO",
            })
        else:
            findings.append({
                "requirement": "10.2", "check": "Audit daemon running",
                "status": "FAIL", "severity": "CRITICAL",
                "detail": "auditd is not running",
            })

        # Check syslog
        for syslog in ["rsyslog", "syslog-ng"]:
            result = subprocess.run(
                ["systemctl", "is-active", syslog],
                capture_output=True, text=True, timeout=10,
            )
            if result.stdout.strip() == "active":
                findings.append({
                    "requirement": "10.2", "check": f"{syslog} running",
                    "status": "PASS", "severity": "INFO",
                })
                break
    return findings


def check_file_integrity():
    """PCI DSS Req 11.5.2 - File integrity monitoring."""
    findings = []
    print("[*] Req 11.5.2: Checking file integrity monitoring")

    fim_tools = {
        "aide": ["/usr/bin/aide", "/usr/sbin/aide"],
        "ossec": ["/var/ossec/bin/ossec-syscheckd"],
        "tripwire": ["/usr/sbin/tripwire"],
        "samhain": ["/usr/local/sbin/samhain"],
    }

    found_fim = False
    for tool_name, paths in fim_tools.items():
        for path in paths:
            if os.path.isfile(path):
                findings.append({
                    "requirement": "11.5.2", "check": f"FIM tool: {tool_name}",
                    "status": "PASS", "severity": "INFO",
                    "detail": f"Found at {path}",
                })
                found_fim = True
                break

    if not found_fim:
        findings.append({
            "requirement": "11.5.2", "check": "File integrity monitoring",
            "status": "FAIL", "severity": "HIGH",
            "detail": "No FIM tool detected (AIDE, OSSEC, Tripwire, Samhain)",
        })

    return findings


def check_default_credentials():
    """PCI DSS Req 2.2.2 - Change vendor defaults."""
    findings = []
    print("[*] Req 2.2.2: Checking for default credentials")

    # Check for common default accounts
    if os.path.isfile("/etc/passwd"):
        with open("/etc/passwd", "r") as f:
            for line in f:
                parts = line.strip().split(":")
                if len(parts) >= 7:
                    username = parts[0]
                    shell = parts[6]
                    if username in ("guest", "test", "demo", "admin") and shell not in ("/usr/sbin/nologin", "/bin/false"):
                        findings.append({
                            "requirement": "2.2.2", "check": f"Default account: {username}",
                            "status": "FAIL", "severity": "HIGH",
                            "detail": f"Account '{username}' has login shell: {shell}",
                        })

    return findings


def check_network_segmentation(target_ip, ports=None):
    """PCI DSS Req 1.3 - Network segmentation check."""
    findings = []
    if not ports:
        ports = [22, 80, 443, 3306, 5432, 1433, 6379, 9200, 27017]
    print(f"[*] Req 1.3: Checking network segmentation to {target_ip}")

    for port in ports:
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(3)
            result = sock.connect_ex((target_ip, port))
            sock.close()
            if result == 0:
                findings.append({
                    "requirement": "1.3", "check": f"Port {port} reachable",
                    "status": "WARN", "severity": "MEDIUM",
                    "detail": f"{target_ip}:{port} is open from this network segment",
                })
        except Exception:
            pass

    if not findings:
        findings.append({
            "requirement": "1.3", "check": "Network segmentation",
            "status": "PASS", "severity": "INFO",
            "detail": f"No tested ports reachable on {target_ip}",
        })

    return findings


def format_summary(all_findings):
    """Print PCI DSS audit summary."""
    print(f"\n{'='*60}")
    print(f"  PCI DSS v4.0 Compliance Audit Report")
    print(f"{'='*60}")

    pass_count = sum(1 for f in all_findings if f["status"] == "PASS")
    fail_count = sum(1 for f in all_findings if f["status"] == "FAIL")
    warn_count = sum(1 for f in all_findings if f["status"] == "WARN")

    print(f"  Total Checks : {len(all_findings)}")
    print(f"  Passed       : {pass_count}")
    print(f"  Failed       : {fail_count}")
    print(f"  Warnings     : {warn_count}")

    by_req = {}
    for f in all_findings:
        req = f.get("requirement", "unknown")
        by_req.setdefault(req, []).append(f)

    print(f"\n  Results by Requirement:")
    for req in sorted(by_req.keys()):
        items = by_req[req]
        failed = sum(1 for i in items if i["status"] == "FAIL")
        passed = sum(1 for i in items if i["status"] == "PASS")
        status = "FAIL" if failed > 0 else "PASS"
        print(f"    Req {req:8s}: [{status:4s}] {passed} passed, {failed} failed")

    if fail_count > 0:
        print(f"\n  Failed Checks:")
        for f in all_findings:
            if f["status"] == "FAIL":
                print(f"    [{f['severity']:8s}] Req {f['requirement']}: {f['check']} - {f.get('detail', '')}")

    severity_counts = {}
    for f in all_findings:
        if f["status"] == "FAIL":
            sev = f.get("severity", "MEDIUM")
            severity_counts[sev] = severity_counts.get(sev, 0) + 1
    return severity_counts


def main():
    parser = argparse.ArgumentParser(description="PCI DSS compliance control audit agent")
    parser.add_argument("--tls-host", help="Host to check TLS configuration")
    parser.add_argument("--tls-port", type=int, default=443)
    parser.add_argument("--segment-target", help="IP to check network segmentation")
    parser.add_argument("--skip-password", action="store_true")
    parser.add_argument("--skip-logging", action="store_true")
    parser.add_argument("--skip-fim", action="store_true")
    parser.add_argument("--output", "-o", help="Output JSON report")
    parser.add_argument("--verbose", "-v", action="store_true")
    args = parser.parse_args()

    all_findings = []

    if args.tls_host:
        all_findings.extend(check_tls_configuration(args.tls_host, args.tls_port))
    if not args.skip_password:
        all_findings.extend(check_password_policy())
    if not args.skip_logging:
        all_findings.extend(check_audit_logging())
    if not args.skip_fim:
        all_findings.extend(check_file_integrity())
    all_findings.extend(check_default_credentials())
    if args.segment_target:
        all_findings.extend(check_network_segmentation(args.segment_target))

    if not all_findings:
        print("[!] No checks performed. Use --tls-host or other options.", file=sys.stderr)
        sys.exit(1)

    severity_counts = format_summary(all_findings)

    report = {
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "tool": "PCI DSS Audit",
        "standard": "PCI DSS v4.0",
        "findings": all_findings,
        "severity_counts": severity_counts,
        "risk_level": (
            "CRITICAL" if severity_counts.get("CRITICAL", 0) > 0
            else "HIGH" if severity_counts.get("HIGH", 0) > 0
            else "MEDIUM" if severity_counts.get("MEDIUM", 0) > 0
            else "LOW"
        ),
    }

    if args.output:
        with open(args.output, "w") as f:
            json.dump(report, f, indent=2)
        print(f"\n[+] Report saved to {args.output}")
    elif args.verbose:
        print(json.dumps(report, indent=2))


if __name__ == "__main__":
    main()

Assets 1

template.mdtext/markdown · 4.2 KB
Keep exploring