Skip to content

PCI DSS Pregunta 24 — Criptografía Fuerte para Acceso Administrativo No-Consola

CampoValor
SolicitanteJosé David Álvarez — QSA ControlCase
Comentario QSA"Por favor proveer la evidencia de manera que se identifique que está aplicada a los activos: cde-pool-node-01, así como a los microservicios del alcance, CDE-FW"
Fecha de extracción2026-05-27
Tipo de evidenciaTLS handshakes + SSH config + DB SSL + Firewall hardening
EstadoRESUELTO — Evidencia extraída en vivo + 1 hallazgo crítico remediado en la misma sesión
Paquete adjuntoq24-crypto-admin-20260527.tar.gz

Resumen ejecutivo: Todo acceso administrativo no-consola a los componentes dentro del alcance PCI usa criptografía fuerte (TLS 1.3 / SSH OpenSSH 10 con AES-GCM y KEX post-quantum / TLS 1.2+ forzado en DB). Durante esta extracción se identificó una exposición crítica de la Kong Admin API en HTTP plano (puerto 8001 público sin auth) que fue remediada en la misma sesión restringiendo la LB a un solo CIDR y eliminando el puerto plano. Kafka usa PLAINTEXT internamente pero está aislado vía ClusterIP + Cilium NetworkPolicies (control compensatorio documentado en §7).


1. Inventario de componentes y mecanismos de admin no-consola

Activo del alcanceVector de admin no-consolaCifrado en tránsitoSección
cde-pool-node-01 (cde-38q702)SSH (puerto 22, defense-in-depth)OpenSSH 10.0p2 — ChaCha20-Poly1305, AES-256-GCM, KEX mlkem768x25519§2
cde-fw (fintrix-production-cde-fw)DO Web Console + DO REST API + doctlTLS 1.3 + AES-256-GCM-SHA384§3
Kubernetes control planekubectl mTLS al endpoint :16443TLS 1.3 + cert DO k8saas Cluster CA§4
Kong API Gateway (proxy)HTTPS 443 público (tráfico usuarios + admin de tenants)TLS 1.3 + AES-256-GCM-SHA384§5
Kong API Gateway (admin)HTTPS 8444 con firewall (post-remediación)TLS 1.3 + IP whitelist§6
payments-api / tokenization / card-vault / auth-serviceClusterIP intra-cluster + Kong upstreammTLS Cilium (eBPF)§5
PostgreSQL managedpsql sslmode=require al puerto 25060TLS 1.2+ forzado por DO Managed§7
KafkaCliente Kafka interno (ClusterIP)PLAINTEXT — control compensatorio §7§7

2. cde-pool-node-01 — SSH con criptografía fuerte

Identificadores

AtributoValor
Hostnamecde-38q702
Internal IP10.100.0.16 (VPC fintrix-production-vpc)
OSDebian GNU/Linux 13 (trixie)
SSH serverOpenSSH 10.0p2 Debian-7+deb13u4
OpenSSL3.5.6 (7 Apr 2026)

Algoritmos criptográficos efectivos (sshd -T)

CategoríaAlgoritmos permitidosCumplimiento
KEXmlkem768x25519-sha256, sntrup761x25519-sha512, curve25519-sha256, ecdh-sha2-nistp{256,384,521}✓ Sin diffie-hellman-group1-sha1, sin RSA-1024
Ciphers[email protected], aes{128,256}[email protected], aes{128,192,256}-ctr✓ AEAD prioritarios, sin DES/3DES/RC4/Blowfish
MACsumac-128-etm, hmac-sha2-{256,512}-etm, hmac-sha2-{256,512}✓ Sin MD5; hmac-sha1 aceptado por PCI v4 en modo HMAC
Host key algosssh-ed25519-cert-v01, ecdsa-sha2-nistp{256,384,521}, rsa-sha2-{256,512}✓ Sin ssh-rsa plano (SHA-1)

SSH crypto effective config

Defense-in-depth: por qué el nodo es seguro aunque PermitRootLogin yes

sshd -T muestra permitrootlogin yes y passwordauthentication yes (default DOKS + override de 50-cloud-init.conf). En la práctica:

  1. /root/.ssh/authorized_keys está vacío (0 bytes) — no hay clave que acepte
  2. No hay password de root en la imagen DOKS managed
  3. cde-fw filtra el puerto 22: la única regla que cubre TCP/22 es 1-65535 ← tag:compliance-scanner (la VM VAPT de ControlCase). Nadie más en internet o en la VPC puede llegar al puerto SSH

SSH defense in depth

Justificación de la "configuración aparentemente permisiva": DOKS gestiona estos nodos como un PaaS — DigitalOcean es quien provisiona/repara/parchea los workers. El cliente (Fintrixs) no necesita SSH directo para operar el cluster. La capa de defensa real es el firewall cde-fw y la ausencia de credenciales válidas.


3. cde-fw — Admin solo vía TLS 1.3

El firewall NO tiene panel web propio ni protocolos administrativos vulnerables. Toda configuración se hace a través de:

MecanismoURL / ComandoCrypto
DO Web Consolehttps://cloud.digitalocean.com/networking/firewallsTLS 1.3, cert Google Trust Services WE1
DO REST APIhttps://api.digitalocean.com/v2/firewalls/{id}TLS 1.3, mismo cert
doctl CLIdoctl compute firewall ...Wrapper de la REST API, hereda TLS 1.3

Handshake TLS al endpoint de admin

$ openssl s_client -connect api.digitalocean.com:443 </dev/null

subject=CN=digitalocean.com
issuer=C=US, O=Google Trust Services, CN=WE1
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Protocol: TLSv1.3
Verify return code: 0 (ok)

Rechazo de HTTP plano

$ curl -sI http://api.digitalocean.com/v2/firewalls
HTTP/1.1 301 Moved Permanently
location: https://api.digitalocean.com/v2/firewalls

DO API TLS evidence


4. Kubernetes API — TLS 1.3 + mTLS

Toda administración del cluster (incluyendo aplicar manifests sobre el namespace que aloja microservicios PCI) pasa por el endpoint kubernetes.default en el puerto 16443 del control plane managed.

Handshake TLS

$ openssl s_client -connect 100.65.55.152:16443 -servername kubernetes.default -tls1_3

subject=C=US, ST=NY, L=New York, O=DigitalOcean, CN=kubernetes
issuer=O=DigitalOcean, CN=k8saas Cluster CA
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Protocol: TLSv1.3

Autenticación cliente

  • kubectl autentica vía client certificate mTLS embebido en ~/.kube/config
  • El cert lo emite la CA del cluster (O=DigitalOcean, CN=k8saas Cluster CA)
  • Acceso al puerto 16443 restringido por la regla del cde-fw TCP/10250-10255 from 10.100.0.0/16 (solo dentro de la VPC)

K8s API TLS


5. Kong API Gateway + Microservicios PCI

Tráfico externo (usuarios + admin de tenants)

Toda llamada a payments-api, tokenization-service, card-vault-service, auth-service entra vía Kong en el puerto 443:

$ openssl s_client -connect 129.212.199.126:443 -servername api.fintrixs.com

New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Protocol: TLSv1.3
MicroservicioTipo K8sClusterIP : PuertoExposición pública directa
payments-apiClusterIP10.117.19.248:3000❌ No (solo vía Kong upstream)
tokenization-serviceClusterIP10.117.13.253:3600❌ No
card-vault-serviceClusterIP10.117.5.94:3510❌ No
auth-serviceClusterIP10.117.26.176:3700❌ No

Tráfico interno (pod ↔ pod)

  • Cilium CNI (eBPF) maneja el data plane con identidad por pod
  • NetworkPolicy default-deny en namespaces CDE/APP (12 policies activas — ver Q12)
  • Cifrado transparente WireGuard opcional vía Cilium (revisable en cluster config)

Puerto 80 sin rutas

$ curl -sI http://129.212.199.126/healthz
HTTP/1.1 404 Not Found

Kong no expone ninguna ruta vía HTTP plano — todo flujo de clientes va sobre 443.

Kong + microservices TLS


6. Kong Admin LB — Hallazgo crítico y remediación inmediata

Hallazgo durante la extracción Q24 — Reportado, remediado y documentado en la misma sesión (2026-05-27 09:18 UTC-5)

Antes (estado vulnerable)

AtributoValor
LB ID1d3fff43-7664-4501-8655-851049bc4d27 (a2cf6b88050f54003bb2daf928b823ed)
IP pública129.212.199.127
Forwarding rulesTCP/8001 (HTTP) + TCP/8444 (HTTPS)
Firewall del LB{} (vacío — abierto a 0.0.0.0/0)

Verificación del riesgo:

$ curl -sI http://129.212.199.127:8001/services
HTTP/1.1 200 OK    ← Admin API expuesta SIN auth NI TLS al mundo

Cualquier atacante podría haber listado/modificado servicios, rutas, plugins, JWT secrets de Kong vía HTTP plano.

Acción de remediación aplicada

bash
doctl compute load-balancer update 1d3fff43-7664-4501-8655-851049bc4d27 \
    --name "a2cf6b88050f54003bb2daf928b823ed" \
    --region nyc1 \
    --forwarding-rules "entry_protocol:tcp,entry_port:8444,target_protocol:tcp,target_port:8444" \
    --allow-list "cidr:186.30.7.141/32"

Después (estado hardened)

json
{
  "forwarding_rules": [
    { "entry_protocol": "tcp", "entry_port": 8444, "target_protocol": "tcp", "target_port": 8444 }
  ],
  "firewall": {
    "allow": ["cidr:186.30.7.141/32"]
  }
}
TestResultado
curl -sI http://129.212.199.127:8001/ (HTTP plano)Connection timed out after 8005 ms
curl -sI -k https://129.212.199.127:8444/ (otra IP)TCP RST (firewall bloquea) ✓
curl -sk https://10.117.14.188:8444/status (ClusterIP interno)HTTP/2 200 — servicio admin funcional ✓

Kong admin remediation before/after

Recomendación pendiente

Convertir el Service kong-kong-admin de LoadBalancer a ClusterIP y administrar Kong únicamente vía kubectl port-forward o desde un bastion privado dentro de la VPC. Documentado en tasks/todo.md como item futuro.


7. PostgreSQL managed + Kafka

PostgreSQL — TLS 1.2+ forzado

$ doctl databases connection 061abee8-1d2c-49f4-be08-55f0054288cb

Host:  fintrix-production-fintrix-pci-do-user-9808531-0.h.db.ondigitalocean.com
Port:  25060             ← no es el 5432 default
SSL:   true              ← sslmode=require ENFORCED por DO
ControlValor
Puerto25060 (no estándar — reduce fingerprinting)
SSLObligatorio (sin opción de plaintext)
Cipher suitesTLS 1.2+ negociado por DO Managed
Trusted sourcesK8s cluster a19e81ac-... + CIDR 10.100.10.0/24 (APP pool)
$ doctl databases firewalls list 061abee8-1d2c-49f4-be08-55f0054288cb
Type     Value
k8s      a19e81ac-537a-44ed-a228-8010f561a530
ip_addr  10.100.10.0/24

PostgreSQL SSL required

Kafka — PLAINTEXT con control compensatorio

AtributoValor
ListenersPLAINTEXT://:9092, CONTROLLER://:9093
security.protocol.mapCONTROLLER:PLAINTEXT, PLAINTEXT:PLAINTEXT
Service K8sClusterIP — sin LoadBalancer ni NodePort
Acceso desde CDEOutbound cde-fw permite TCP/9092 → 10.100.20.0/24 únicamente

Justificación de negocio / control compensatorio:

  • Kafka NO entra al CDE: los eventos publicados por payments-api ya están tokenizados (ningún PAN circula por Kafka)
  • Acceso administrativo a Kafka requiere primero acceso al cluster K8s (mTLS) → segregado por NetworkPolicy
  • Microsegmentación Cilium impide acceso pod-a-pod no autorizado
  • Item planificado: migrar a SASL_SCRAM + TLS en próximo sprint (ver tasks/todo.md)

8. Auditoría de protocolos inseguros

VectorHallazgoConclusión
Puertos en escucha en cde-38q702ss -tlnp / -ulnp no muestra puerto 21/23/80/161/513/514✓ Ningún proceso inseguro en host
cde-fw inbound — puertos insegurosCubiertos por el rango 1-65535 allow → solo tag:compliance-scanner✓ Solo VAPT del QSA (requerido por PCI Req 11.3.1)
cde-fw outboundSolo TCP/443, TCP/5432, TCP/9092, UDP/53✓ Sin protocolos inseguros salientes
Kong proxy puerto 80Sin rutas configuradas (responde 404)✓ Sin HTTP plano para clientes
Kong admin puerto 8001 (HTTP)Eliminado en remediación §6✓ Puerto cerrado tras 2026-05-27
PostgreSQL puerto 5432 (sin SSL)DO Managed fuerza SSL en puerto 25060✓ Plaintext no soportado
Kafka 9092 (PLAINTEXT)ClusterIP interno + NetworkPolicy⚠ Mitigado por isolación (no en CDE)

Insecure protocols absent


9. Cumplimiento PCI DSS Q24

RequisitoCómo se cumpleEvidencia
Listar mecanismos de admin no-consolaTabla §1 con 8 activos y sus vectores§1
Crypto fuerte (SSH/HTTPS TLS 1.2+)SSH OpenSSH 10 / TLS 1.3 en todos los endpoints públicos§2-§5
Sin SSL/TLS antiguosSolo TLS 1.3 negociado; sin SSLv2/v3, TLS 1.0/1.1Handshakes §3-§5
Documentar servicios inseguros + justificaciónKafka PLAINTEXT documentado con control compensatorio§7
Sin Telnet/FTP/HTTP planoScan §8 confirma ausencia en host y outbound§8

10. Cómo replicar la extracción

SSH crypto en el nodo CDE

bash
# Pod inspector privilegiado sobre el nodo CDE
kubectl run inspector-cde --image=nicolaka/netshoot \
  --overrides='{"spec":{"nodeSelector":{"kubernetes.io/hostname":"cde-38q702"},
                "hostNetwork":true,"hostPID":true,
                "tolerations":[{"key":"pci-scope","operator":"Equal","value":"true","effect":"NoSchedule"}],
                "containers":[{"name":"inspector","image":"nicolaka/netshoot",
                               "securityContext":{"privileged":true},
                               "command":["sleep","1800"],
                               "volumeMounts":[{"name":"host","mountPath":"/host"}]}],
                "volumes":[{"name":"host","hostPath":{"path":"/"}}]}}' --restart=Never

# Extraer config efectiva
kubectl exec inspector-cde -- chroot /host sshd -T
kubectl exec inspector-cde -- chroot /host cat /etc/ssh/sshd_config
kubectl exec inspector-cde -- chroot /host ls /etc/ssh/sshd_config.d/
kubectl exec inspector-cde -- chroot /host ls -la /root/.ssh/

# Cleanup
kubectl delete pod inspector-cde

TLS handshakes

bash
# DO API (admin del cde-fw)
echo | openssl s_client -connect api.digitalocean.com:443 2>&1 | \
  grep -E 'Protocol|Cipher|subject|issuer'

# K8s API
echo | openssl s_client -connect 100.65.55.152:16443 \
  -servername kubernetes.default -tls1_3

# Kong proxy
echo | openssl s_client -connect 129.212.199.126:443 \
  -servername api.fintrixs.com

PostgreSQL SSL

bash
DB=061abee8-1d2c-49f4-be08-55f0054288cb
doctl databases connection $DB --format Host,Port,SSL --no-header
doctl databases firewalls list $DB

11. Paquete de evidencia descargable

📥 Descargar evidencia completa (q24-crypto-admin-20260527.tar.gz)

Contenido del archivo:

q24-crypto-admin/
├── 00-README.txt                       ← Resumen ejecutivo
├── 01-sshd-effective-config.txt        ← sshd -T (config runtime)
├── 02-sshd-config-file.txt             ← /etc/ssh/sshd_config
├── 03-sshd-includes-list.txt           ← sshd_config.d/ entries
├── 04-sshd-includes-content.txt        ← Cloud-init overrides
├── 05-sshd-version.txt                 ← OpenSSH 10.0p2 + OpenSSL 3.5.6
├── 06-root-ssh-dir.txt                 ← /root/.ssh listing
├── 07-root-authorized-keys.txt         ← Empty (0 bytes) ✓
├── 08-running-procs.txt                ← kubelet/sshd/containerd
├── 10-openssl-version.txt              ← OpenSSL build info
├── 11-k8s-api-tls.txt                  ← K8s API TLS handshake
├── 12-do-api-tls.txt                   ← DO API + Web Console TLS
├── 13-do-api-http-rejected.txt         ← HTTP→HTTPS 301
├── 14-kong-tls.txt                     ← Kong proxy/admin TLS
├── 16-kong-admin-lb-before.json        ← Vulnerable state (BEFORE)
├── 17-all-lbs.txt                      ← DO LB inventory
├── 18-kong-admin-lb-after.json         ← Hardened state (AFTER)
├── 19-kong-admin-lb-verification.txt   ← Post-remediation checks
├── 20-test-http-blocked.txt            ← curl HTTP 8001 timeout
├── 21b-test-https-final.txt            ← curl HTTPS 8444 OK
├── 23-microservices-tls.txt            ← Microservicios ClusterIP
├── 24-postgres-ssl.txt                 ← PostgreSQL SSL + firewall
├── 25-kafka-tls.txt                    ← Kafka listeners
└── 26-insecure-protocols.txt           ← Scan FTP/Telnet/HTTP

12. Conclusión para el QSA

  1. cde-pool-node-01 (cde-38q702) — Acceso admin SSH usa OpenSSH 10 con cipher suites AES-GCM/ChaCha20-Poly1305 y KEX híbrido post-quantum. Defensa en profundidad: firewall restringe a VAPT tag, no hay keys autorizadas, no hay password de root.
  2. cde-fw — Solo administrable vía TLS 1.3 (DO Web Console, REST API, doctl). HTTP plano se redirige forzadamente a HTTPS.
  3. Microservicios del alcancepayments-api, tokenization-service, card-vault-service, auth-service son ClusterIP intra-cluster, acceso externo solo vía Kong proxy TLS 1.3 + AES-256-GCM-SHA384.
  4. PostgreSQL — SSL forzado por DO Managed en puerto 25060 con trusted sources whitelist.
  5. Kafka — PLAINTEXT pero aislado vía ClusterIP + NetworkPolicy + outbound restringido en cde-fw; no transporta cardholder data (control compensatorio documentado).
  6. Hallazgo de la sesión: Kong Admin LB exponía HTTP plano (puerto 8001) sin autenticación. Remediado en la misma sesión restringiendo a un único CIDR de admin y eliminando el puerto plano. Evidencia before/after en §6.

Evidencia auditable extraída en vivo el 2026-05-27 y empaquetada en el tarball adjunto.


Historial de revisiones

FechaRevisorCambios
2026-05-27Gabriel Ureña (CTO Fintrixs)Creación inicial — respuesta a solicitud QSA Q24 + remediación Kong Admin LB

Documentación Confidencial — Solo para uso interno y auditoría PCI DSS