La seguridad del sistema bancario se implementa mediante una estrategia de Defense in Depth con múltiples capas de protección, siguiendo el modelo Zero Trust donde "nunca confiar, siempre verificar" es el principio fundamental.
---
config:
layout: dagre
---
flowchart BT
subgraph C7["📱 Capa 7: Usuarios"]
U1["MFA Obligatorio"]
U2["Biometría"]
U3["Security Awareness"]
end
subgraph C6["🌐 Capa 6: Aplicación Web"]
W1["WAF"]
W2["Rate Limiting"]
W3["CORS"]
W4["CSP"]
W5["Input Validation"]
end
subgraph C5["🔌 Capa 5: API Gateway"]
A1["JWT Validation"]
A2["OAuth 2.0"]
A3["Throttling"]
A4["API Keys"]
end
subgraph C4["⚙️ Capa 4: Microservicios"]
M1["Service Mesh - mTLS"]
M2["RBAC"]
M3["Input Sanitization"]
end
subgraph C3["💾 Capa 3: Base de Datos"]
D1["Encryption at Rest"]
D2["Row-Level Security"]
D3["Audit Logs"]
end
subgraph C2["🌍 Capa 2: Red y Infraestructura"]
N1["Network Policies"]
N2["Firewalls"]
N3["IDS/IPS"]
N4["VPN"]
end
subgraph C1["🖥️ Capa 1: Físico/Cloud"]
P1["Cifrado de Disco"]
P2["TPM"]
P3["Secure Boot"]
P4["Cloud Security"]
end
C1 --> C2
C2 --> C3
C3 --> C4
C4 --> C5
C5 --> C6
C6 --> C7
U1:::item
U2:::item
U3:::item
W1:::item
W2:::item
W3:::item
W4:::item
W5:::item
A1:::item
A2:::item
A3:::item
A4:::item
M1:::item
M2:::item
M3:::item
D1:::item
D2:::item
D3:::item
N1:::item
N2:::item
N3:::item
N4:::item
P1:::item
P2:::item
P3:::item
P4:::item
C1:::capa1
C2:::capa2
C3:::capa3
C4:::capa4
C5:::capa5
C6:::capa6
C7:::capa7
classDef capa1 fill:#FFE0E0,stroke:#D32F2F,stroke-width:2px,rx:15,ry:15
classDef capa2 fill:#E3F2FD,stroke:#1976D2,stroke-width:2px,rx:15,ry:15
classDef capa3 fill:#E8F5E9,stroke:#388E3C,stroke-width:2px,rx:15,ry:15
classDef capa4 fill:#FFF3E0,stroke:#F57C00,stroke-width:2px,rx:15,ry:15
classDef capa5 fill:#F3E5F5,stroke:#7B1FA2,stroke-width:2px,rx:15,ry:15
classDef capa6 fill:#E0F2F1,stroke:#00796B,stroke-width:2px,rx:15,ry:15
classDef capa7 fill:#FFF8E1,stroke:#FF8F00,stroke-width:2px,rx:15,ry:15
classDef item fill:#FFFFFF,stroke:#666666,stroke-width:1px,rx:8,ry:8
flowchart TB
%% === API GATEWAY ===
APIGateway[API GATEWAY
+ Auth Server]
%% === MICROSERVICES ===
MS1[Microservice A]
MS2[Microservice B]
MS3[Microservice C]
%% === SERVICE MESH ===
ServiceMesh[SERVICE MESH
Istio]
%% === FEATURES ===
subgraph Features[Características de Seguridad]
F1[mTLS entre servicios]
F2[Certificate Rotation
cada 1 hora]
F3[Network Policies]
F4[Traffic Management]
end
%% === CONNECTIONS ===
APIGateway --> MS1
APIGateway --> MS2
APIGateway --> MS3
MS1 --> ServiceMesh
MS2 --> ServiceMesh
MS3 --> ServiceMesh
ServiceMesh --> Features
%% === STYLES ===
classDef gateway fill:#E3F2FD,stroke:#1976D2,stroke-width:3px,rx:15,ry:15
classDef microservice fill:#E8F5E9,stroke:#4CAF50,stroke-width:2px,rx:10,ry:10
classDef serviceMesh fill:#FFF3E0,stroke:#FF9800,stroke-width:3px,rx:15,ry:15
classDef features fill:#FFF9C4,stroke:#FBC02D,stroke-width:2px,rx:8,ry:8
classDef featureItem fill:#FFFDE7,stroke:#FBC02D,stroke-width:1px,rx:5,ry:5
class APIGateway gateway
class MS1,MS2,MS3 microservice
class ServiceMesh serviceMesh
class Features features
class F1,F2,F3,F4 featureItem
| Componente | Tecnología | Configuración |
|---|---|---|
| Identity Provider | Keycloak / Auth0 | OAuth 2.0 + OIDC + PKCE |
| Token Lifetime | JWT Access Token | 15 minutos (rotación) |
| Refresh Token | Secure Cookie | 7 días (revocable) |
| Service-to-Service | mTLS Certificates | 1 hora (auto-renovación) |
| API Authorization | OPA (Open Policy Agent) | Rego Policies |
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: accounts-service-policy
namespace: banking-prod
spec:
podSelector:
matchLabels:
app: accounts-service
policyTypes:
- Ingress
- Egress
# Solo recibe tráfico del API Gateway
ingress:
- from:
- podSelector:
matchLabels:
app: api-gateway
ports:
- protocol: TCP
port: 3000
# Solo puede hablar con PostgreSQL y Message Bus
egress:
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432
- to:
- podSelector:
matchLabels:
app: kafka
ports:
- protocol: TCP
port: 9092
# DNS resolution
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: banking-prod
spec:
mtls:
mode: STRICT # Solo mTLS, rechazar tráfico sin cifrar
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: accounts-service-authz
namespace: banking-prod
spec:
selector:
matchLabels:
app: accounts-service
action: ALLOW
rules:
# Solo API Gateway puede llamar
- from:
- source:
principals: ["cluster.local/ns/banking-prod/sa/api-gateway"]
to:
- operation:
methods: ["GET", "POST", "PUT"]
paths: ["/accounts/*"]
when:
- key: request.auth.claims[role]
values: ["api-service"]
| Protección | Reglas Implementadas | Acción |
|---|---|---|
| SQL Injection | OWASP Core Rule Set 3.3 | Block + Log + Alert |
| XSS | Content-Type validation, CSP | Block + Sanitize |
| CSRF | SameSite Cookies + Tokens | Reject requests |
| DDoS Layer 7 | Rate limiting por IP/User | Throttle + Captcha |
| Geo-Blocking | Permitir solo países autorizados | Block by GeoIP |
| Bot Detection | Cloudflare Bot Management | Challenge/Block |
// Rate Limiting Rules
{
"id": "rl_login_endpoint",
"expression": "(http.request.uri.path eq \"/api/auth/login\")",
"action": "challenge",
"ratelimit": {
"characteristics": ["ip.src"],
"period": 60,
"requests_per_period": 5,
"mitigation_timeout": 600 // 10 min ban
}
}
// Geographic Restrictions
{
"id": "geo_restriction",
"expression": "(not ip.geoip.country in {\"US\" \"CA\" \"MX\" \"EC\" \"CO\" \"PE\"})",
"action": "block"
}
// OWASP Top 10
{
"id": "owasp_protection",
"expression": "(cf.waf.score gt 30)",
"action": "block",
"description": "Block high-risk OWASP threats"
}
// Rate Limiting por Endpoint
plugins:
- name: rate-limiting
config:
minute: 100
hour: 5000
policy: redis
fault_tolerant: true
hide_client_headers: false
redis:
host: redis-cluster
port: 6379
timeout: 2000
database: 0
// Rate Limiting por Usuario (más permisivo)
- name: rate-limiting
config:
minute: 500
hour: 20000
limit_by: credential
policy: redis
// Protección de endpoints críticos
routes:
- name: transfer_money
plugins:
- name: rate-limiting
config:
minute: 10 # Solo 10 transferencias por minuto
hour: 100 # 100 por hora
policy: redis
limit_by: credential
| Vulnerabilidad | Mitigación Implementada | Herramientas |
|---|---|---|
| A01: Broken Access Control |
• RBAC con OPA • JWT con scopes • Row-Level Security en DB |
Keycloak, PostgreSQL RLS |
| A02: Cryptographic Failures |
• TLS 1.3 obligatorio • AES-256-GCM para datos • Bcrypt para passwords • Secrets en Vault |
Vault, AWS KMS |
| A03: Injection |
• Prepared Statements • Input validation (Joi/Zod) • GraphQL query complexity limits • WAF rules |
TypeORM, GraphQL Shield |
| A04: Insecure Design |
• Threat Modeling (STRIDE) • Security by Design • Code Reviews obligatorios |
Microsoft Threat Modeling Tool |
| A05: Security Misconfiguration |
• Infrastructure as Code • Security scanning automático • Hardened Docker images |
Terraform, Trivy, Snyk |
| A06: Vulnerable Components |
• npm audit en CI/CD • Dependabot alerts • Container scanning |
Snyk, Trivy, Dependabot |
| A07: Identification/Authentication |
• MFA obligatorio • Biometría • Session timeout • Brute-force protection |
Auth0, Keycloak |
| A08: Software/Data Integrity |
• Signed container images • Git commit signing • Checksums de dependencias |
Cosign, GPG |
| A09: Security Logging/Monitoring |
• ELK Stack • Audit logs inmutables • SIEM (Splunk/Wazuh) |
ELK, Wazuh, Grafana |
| A10: SSRF |
• Whitelist de URLs • Network policies • URL validation |
Kong, Network Policies |
import Joi from 'joi';
import DOMPurify from 'isomorphic-dompurify';
// Schema de validación
const transferSchema = Joi.object({
fromAccount: Joi.string().alphanum().length(20).required(),
toAccount: Joi.string().alphanum().length(20).required(),
amount: Joi.number().positive().max(1000000).precision(2).required(),
description: Joi.string().max(200).optional(),
otp: Joi.string().length(6).pattern(/^[0-9]+$/).required()
});
// Middleware de validación
export const validateTransfer = (req, res, next) => {
const { error, value } = transferSchema.validate(req.body, {
abortEarly: false,
stripUnknown: true // Eliminar campos no esperados
});
if (error) {
return res.status(400).json({
error: 'Validation Error',
details: error.details.map(d => d.message)
});
}
// Sanitizar strings
if (value.description) {
value.description = DOMPurify.sanitize(value.description);
}
req.validatedData = value;
next();
};
graph TD
KUBERNETES["KUBERNETES CLUSTER"]
subgraph KUBERNETES
B["Microservice A
(needs secrets)"]
C["Vault Agent
(Sidecar)"]
B --> C
end
subgraph D[VAULT CLUSTER HA]
E[Vault]
F[Vault]
G[Vault]
end
H["STORAGE BACKEND
(Encrypted Consul)"]
C -->|mTLS| D
D --> H
classDef k8s fill:#E3F2FD,stroke:#1976D2,stroke-width:2px
classDef microservice fill:#E8F5E9,stroke:#4CAF50,stroke-width:2px
classDef vaultagent fill:#FFF9C4,stroke:#F57C00,stroke-width:2px
classDef vault fill:#FFE0B2,stroke:#EF6C00,stroke-width:2px
classDef storage fill:#F3E5F5,stroke:#7B1FA2,stroke-width:2px
class A k8s
class B microservice
class C vaultagent
class E,F,G vault
class D vault
class H storage
# Política para Accounts Service
path "secret/data/banking/accounts/*" {
capabilities = ["read"]
}
path "database/creds/accounts-role" {
capabilities = ["read"] # Credenciales dinámicas de DB
}
path "pki/issue/banking-intermediate" {
capabilities = ["create", "update"] # Generar certificados
}
# No puede leer secretos de otros servicios
path "secret/data/banking/payments/*" {
capabilities = ["deny"]
}
# Deployment con Vault Sidecar
apiVersion: apps/v1
kind: Deployment
metadata:
name: accounts-service
spec:
template:
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "accounts-service"
vault.hashicorp.com/agent-inject-secret-db: "database/creds/accounts-role"
vault.hashicorp.com/agent-inject-template-db: |
{{- with secret "database/creds/accounts-role" -}}
export DB_USERNAME="{{ .Data.username }}"
export DB_PASSWORD="{{ .Data.password }}"
{{- end -}}
spec:
serviceAccountName: accounts-service
containers:
- name: accounts-api
image: accounts-service:v1.2.0
env:
- name: VAULT_ADDR
value: "https://vault.banking.svc:8200"
| Tipo | Almacenamiento | Rotación | Lifetime |
|---|---|---|---|
| DB Credentials | Vault Dynamic Secrets | Automática | 1 hora |
| API Keys | Vault KV v2 | Manual (quarterly) | 90 días |
| TLS Certificates | Vault PKI Engine | Automática | 24 horas |
| Encryption Keys | AWS KMS + Vault Transit | Automática (versioning) | 1 año |
| OAuth Secrets | Vault KV v2 | Manual | 180 días |
graph LR
%% === COMPONENTES PRINCIPALES ===
CLIENT[📱
CLIENTE]
LB[🌐
LOAD BALANCER]
API[🔌
API GATEWAY]
MS[⚙️
MICROSERVICES]
DB[🐘
POSTGRESQL]
DISK[💾
DISK STORAGE]
BACKUP[📦
BACKUPS]
%% === CONEXIONES CON CIFRADO ===
CLIENT -.->|TLS 1.3| LB
LB -.->|mTLS| API
API -.->|mTLS| MS
MS -.->|TLS| DB
DB -.->|TDE| DISK
DISK -.->|AES-256-XTS| BACKUP
%% === CAPAS DE CIFRADO ===
subgraph EN_TRANSITO[🌐 Cifrado en Tránsito]
T1[TLS 1.3]
T2[mTLS]
T3[TLS]
end
subgraph EN_BASE_DATOS[🗄️ Cifrado Base de Datos]
B1[PostgreSQL TDE]
end
subgraph EN_ALMACENAMIENTO[💾 Cifrado en Reposo]
A1[AES-256-XTS]
end
subgraph EN_BACKUPS[🛡️ Cifrado de Backups]
BK1[AES-256-GCM]
BK2[GPG]
end
%% === RELACIONES DE CIFRADO ===
CLIENT --> T1
LB --> T2
API --> T2
MS --> T3
DB --> B1
DISK --> A1
BACKUP --> BK1
BACKUP --> BK2
%% === ESTILOS ===
classDef title fill:#1565C0,stroke:#0D47A1,stroke-width:3px,color:#FFFFFF
classDef component fill:#E3F2FD,stroke:#1976D2,stroke-width:2px,rx:8,ry:8
classDef transit fill:#E8F5E9,stroke:#4CAF50,stroke-width:1px
classDef database fill:#FFF3E0,stroke:#FF9800,stroke-width:1px
classDef storage fill:#F3E5F5,stroke:#9C27B0,stroke-width:1px
classDef backup fill:#FFEBEE,stroke:#D32F2F,stroke-width:1px
classDef connection stroke:#666,stroke-width:2px,stroke-dasharray:5 5
class CLIENT,LB,API,MS,DB,DISK,BACKUP component
class EN_TRANSITO transit
class EN_BASE_DATOS database
class EN_ALMACENAMIENTO storage
class EN_BACKUPS backup
class T1,T2,T3 transit
class B1 database
class A1 storage
class BK1,BK2 backup
linkStyle 0,1,2,3,4,5 stroke:#1976D2,stroke-width:2px,stroke-dasharray:5 5
| Conexión | Protocolo | Cipher Suite |
|---|---|---|
| Client → LoadBalancer | TLS 1.3 | TLS_AES_256_GCM_SHA384 |
| LoadBalancer → API Gateway | mTLS (Istio) | ECDHE-RSA-AES256-GCM-SHA384 |
| Service-to-Service | mTLS (Istio) | Auto-rotación cada 1h |
| App → PostgreSQL | TLS 1.2+ | ssl_prefer + verify-ca |
| App → Redis | TLS 1.2+ | tls-auth-clients yes |
# postgresql.conf
ssl = on
ssl_cert_file = '/etc/ssl/certs/server.crt'
ssl_key_file = '/etc/ssl/private/server.key'
ssl_ca_file = '/etc/ssl/certs/ca.crt'
# Requerir TLS para todas las conexiones
ssl_min_protocol_version = 'TLSv1.2'
ssl_prefer_server_ciphers = on
ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL'
# Connection string en aplicación
DATABASE_URL=postgresql://user:pass@host:5432/db?sslmode=verify-full&sslrootcert=/path/to/ca.crt
| Componente | Método | Key Management |
|---|---|---|
| PostgreSQL | TDE (Transparent Data Encryption) | AWS KMS / Vault Transit |
| MongoDB (eventos) | Encryption at Rest (WiredTiger) | AWS KMS |
| Kubernetes Secrets | etcd encryption at rest | KMS plugin |
| EBS Volumes | AES-256-XTS | AWS KMS |
| S3 Backups | SSE-KMS | AWS KMS + GPG envelope |
// Cifrado de datos sensibles en aplicación
import crypto from 'crypto';
class EncryptionService {
private algorithm = 'aes-256-gcm';
private keyId: string;
async encrypt(plaintext: string): Promise {
// Obtener DEK (Data Encryption Key) desde Vault
const dek = await this.vault.getDataKey(this.keyId);
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(this.algorithm, dek, iv);
let ciphertext = cipher.update(plaintext, 'utf8', 'hex');
ciphertext += cipher.final('hex');
const authTag = cipher.getAuthTag();
return {
ciphertext,
iv: iv.toString('hex'),
authTag: authTag.toString('hex'),
keyId: this.keyId,
algorithm: this.algorithm
};
}
async decrypt(encrypted: EncryptedData): Promise {
const dek = await this.vault.getDataKey(encrypted.keyId);
const decipher = crypto.createDecipheriv(
encrypted.algorithm,
dek,
Buffer.from(encrypted.iv, 'hex')
);
decipher.setAuthTag(Buffer.from(encrypted.authTag, 'hex'));
let plaintext = decipher.update(encrypted.ciphertext, 'hex', 'utf8');
plaintext += decipher.final('utf8');
return plaintext;
}
}
// Uso en modelo de datos
class User {
id: string;
email: string; // Plain
ssn: EncryptedData; // Cifrado
phone: EncryptedData; // Cifrado
async setSsn(ssn: string) {
this.ssn = await encryptionService.encrypt(ssn);
}
async getSsn(): Promise {
return encryptionService.decrypt(this.ssn);
}
}
graph LR
%% === FUENTES DE LOGS ===
subgraph FUENTES[🔍 Fuentes de Logs]
APP[📱 Aplicaciones]
WAF[🌐 Web Application Firewall]
API[🔌 API Gateway]
K8S[⚙️ Kubernetes]
DB[💾 Bases de Datos]
OS[🖥️ Sistemas Operativos]
end
%% === COLECTORES ===
subgraph COLECTORES[🔄 Colectores de Logs]
FB[Filebeat]
FL[Fluentd]
end
%% === PROCESAMIENTO ===
subgraph PROCESAMIENTO[⚡ Procesamiento]
LS[Logstash
• Parseo
• Enriquecimiento
• Filtrado]
KF[Kafka
Buffer de Mensajes]
end
%% === ALMACENAMIENTO ===
subgraph ALMACENAMIENTO[💾 Almacenamiento]
ES[Elasticsearch
• Búsqueda
• Indexación
• Replicación]
end
%% === VISUALIZACIÓN ===
subgraph VISUALIZACION[📊 Visualización]
KB[Kibana
• Dashboards
• Discover
• Visualizations]
end
%% === SEGURIDAD ===
subgraph SEGURIDAD[🛡️ Seguridad]
WZ[Wazuh
• Threat Intelligence
• Detección de Anomalías
• Cumplimiento]
end
%% === ALERTAS ===
subgraph ALERTAS[🚨 Sistema de Alertas]
PD[PagerDuty]
SL[Slack]
EM[Email]
end
%% === CONEXIONES ===
APP --> FB
WAF --> FB
API --> FL
K8S --> FL
DB --> FB
OS --> FL
FB --> LS
FL --> LS
LS --> KF
KF --> ES
ES --> KB
KB --> WZ
WZ --> PD
WZ --> SL
WZ --> EM
%% === ESTILOS ===
classDef fuentes fill:#E3F2FD,stroke:#1976D2,stroke-width:2px
classDef colectores fill:#E8F5E9,stroke:#4CAF50,stroke-width:2px
classDef procesamiento fill:#FFF3E0,stroke:#FF9800,stroke-width:2px
classDef almacenamiento fill:#F3E5F5,stroke:#9C27B0,stroke-width:2px
classDef visualizacion fill:#E1F5FE,stroke:#0288D1,stroke-width:2px
classDef seguridad fill:#FFEBEE,stroke:#D32F2F,stroke-width:2px
classDef alertas fill:#FCE4EC,stroke:#C2185B,stroke-width:2px
classDef items fill:#FFFFFF,stroke:#666666,stroke-width:1px
class FUENTES fuentes
class COLECTORES colectores
class PROCESAMIENTO procesamiento
class ALMACENAMIENTO almacenamiento
class VISUALIZACION visualizacion
class SEGURIDAD seguridad
class ALERTAS alertas
class APP,WAF,API,K8S,DB,OS,FB,FL,LS,KF,ES,KB,WZ,PD,SL,EM items
| Categoría | Eventos | Severidad | Respuesta |
|---|---|---|---|
| Autenticación |
• Múltiples login fallidos (5 en 5 min) • Login desde IP nueva • Login desde país no autorizado |
🔴 High | Block IP + Alert + Require MFA |
| Autorización |
• Acceso denegado repetido • Privilege escalation attempt • Acceso a recursos no autorizados |
🔴 Critical | Block user + Alert Security Team |
| Datos |
• Exportación masiva de datos • Acceso a >100 cuentas en 1 hora • Queries SQL sospechosas |
🔴 Critical | Block + Forensics + Incident |
| Red |
• Port scanning • DDoS attempts • Conexiones a IPs maliciosas |
🟠 High | WAF Block + Alert |
| Aplicación |
• SQL Injection attempts • XSS attempts • Path traversal attempts |
🟠 High | WAF Block + Log + Alert |
| Infraestructura |
• Pod crashes frecuentes • Unauthorized K8s API calls • Container escape attempts |
🔴 Critical | Kill pod + Alert + Investigate |
| Transacciones |
• Transferencias >$10k sin MFA • Patrón inusual de transacciones • Velocidad sospechosa |
🟡 Medium | Require additional auth |
5710
Multiple authentication failures from same IP
5
300
authentication_failures,pci_dss_10.2.4,
86002
!^(US|CA|MX|EC|CO|PE)$
Login from unauthorized country
authentication,geographic_restriction,
web-log
union.*select|concat.*char|exec.*sp_|';.*drop.*table
Possible SQL injection attack
web,attack,sql_injection,
31100
\d{4,}
10
3600
Massive data export detected
database,data_exfiltration,
Este diagrama representa nuestro Pipeline de Seguridad Continua (Continuous Security Scanning), una estrategia integral que implementamos en cada etapa del ciclo de desarrollo. El flujo comienza con tres tipos de escaneo automatizado: Análisis de Código (SAST/SCA), Escaneo de Contenedores Docker y Revisión de Infraestructura como Código. Todas las vulnerabilidades detectadas se consolidan en una base de datos centralizada donde son evaluadas mediante scoring CVSS y priorizadas según su criticidad. Finalmente, el sistema genera planes de remediación automatizados cuando es posible, o guía al equipo en la resolución manual de issues de seguridad, asegurando compliance y reduciendo riesgos en producción.
graph TD
A[CONTINUOUS SECURITY SCANNING]
subgraph SCANNING[🔍 Security Scanning]
B[CODE SCANNING]
C[DOCKER SCANNING]
D[INFRA SCANNING]
end
subgraph CODE[Code Analysis]
B1[• SAST]
B2[• SCA]
B3[• Semgrep]
end
subgraph DOCKER[Container Analysis]
C1[• Trivy]
C2[• Snyk]
C3[• Grype]
end
subgraph INFRA[Infrastructure Analysis]
D1[• Terraform]
D2[• Checkov]
D3[• tfsec]
end
E[VULNERABILITY DATABASE
• CVEs
• Risk Score CVSS
• Remediation Steps]
F[RISK ASSESSMENT
• Prioritization
• SLA Assignment]
G[REMEDIATION
• Auto-patch
• Manual fix
• Risk acceptance]
A --> B
A --> C
A --> D
B --> B1
B --> B2
B --> B3
C --> C1
C --> C2
C --> C3
D --> D1
D --> D2
D --> D3
B1 --> E
B2 --> E
B3 --> E
C1 --> E
C2 --> E
C3 --> E
D1 --> E
D2 --> E
D3 --> E
E --> F
F --> G
classDef main fill:#FFEBEE,stroke:#D32F2F,stroke-width:3px
classDef scanning fill:#E3F2FD,stroke:#1976D2,stroke-width:2px
classDef code fill:#E8F5E9,stroke:#4CAF50,stroke-width:2px
classDef docker fill:#FFF3E0,stroke:#FF9800,stroke-width:2px
classDef infra fill:#F3E5F5,stroke:#9C27B0,stroke-width:2px
classDef vuln fill:#E1F5FE,stroke:#0288D1,stroke-width:2px
classDef risk fill:#FFF9C4,stroke:#FBC02D,stroke-width:2px
classDef remediation fill:#E8F5E9,stroke:#2E7D32,stroke-width:2px
classDef tools fill:#FFFFFF,stroke:#666666,stroke-width:1px
class A main
class SCANNING scanning
class B,C,D scanning
class CODE code
class DOCKER docker
class INFRA infra
class E vuln
class F risk
class G remediation
class B1,B2,B3,C1,C2,C3,D1,D2,D3 tools
| Tipo | Herramienta | Frecuencia | Scope |
|---|---|---|---|
| SAST (Static Application Security Testing) | SonarQube, Semgrep | Cada commit | Código fuente |
| SCA (Software Composition Analysis) | Snyk, npm audit, Dependabot | Cada build | Dependencias |
| Container Scanning | Trivy, Grype, Snyk Container | Cada imagen | Docker images |
| IaC Scanning | Checkov, tfsec, Terrascan | Cada PR | Terraform, K8s YAML |
| DAST (Dynamic Application Security Testing) | OWASP ZAP, Burp Suite | Weekly | Running apps |
| Secrets Scanning | TruffleHog, GitGuardian | Cada commit | Git history |
# .github/workflows/security-scan.yml
name: Security Scanning Pipeline
on: [push, pull_request]
jobs:
sast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Semgrep
run: |
semgrep --config=auto --sarif > semgrep.sarif
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: semgrep.sarif
sca:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Snyk
run: |
npx snyk test --severity-threshold=high
- name: Npm Audit
run: npm audit --audit-level=moderate
container-scan:
runs-on: ubuntu-latest
steps:
- name: Build image
run: docker build -t app:${{ github.sha }} .
- name: Run Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: 'app:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
exit-code: '1' # Fallar si hay vulnerabilidades
iac-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Checkov
uses: bridgecrewio/checkov-action@master
with:
directory: ./terraform
framework: terraform
soft_fail: false # Fallar en vulnerabilidades
secrets-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Full history
- name: TruffleHog Scan
run: |
trufflehog git file://. --json > trufflehog-results.json
- name: Fail if secrets found
run: |
if [ -s trufflehog-results.json ]; then
echo "Secrets found!"
exit 1
fi
| Severidad CVSS | Score | SLA | Acción |
|---|---|---|---|
| 🔴 Critical | 9.0 - 10.0 | 24 horas | Hotfix inmediato + Post-mortem |
| 🟠 High | 7.0 - 8.9 | 7 días | Patch en próximo release |
| 🟡 Medium | 4.0 - 6.9 | 30 días | Incluir en backlog |
| 🟢 Low | 0.1 - 3.9 | 90 días | Opcional / Risk acceptance |
Este diagrama describe nuestro Proceso de Respuesta a Incidentes de Seguridad, estructurado en seis fases críticas basadas en el framework NIST. Comenzando con la Preparación proactiva del equipo y herramientas, el flujo avanza hacia la Detección y Análisis mediante monitoreo continuo e inteligencia de amenazas. La fase de Contención actúa inmediatamente para limitar el impacto, seguida de la Erradicación completa de la causa raíz. El Recuperación asegura el retorno seguro a operaciones normales, culminando con el Análisis Post-Incidente para mejorar continuamente nuestras defensas y procedimientos.
flowchart TD
subgraph PROCESS["🚨 INCIDENT RESPONSE PROCESS"]
A["🛡️ 1. PREPARATION"]
B["🔍 2. DETECTION & ANALYSIS"]
C["🚫 3. CONTAINMENT"]
D["🧹 4. ERADICATION"]
E["🔄 5. RECOVERY"]
F["📊 6. POST-INCIDENT REVIEW"]
end
subgraph A_Details["Preparation Details"]
A1["👥 IR Team Activation"]
A2["📚 Runbooks & Playbooks"]
A3["🛠️ Tools & Systems Ready"]
A4["📞 Contact List Updated"]
end
subgraph B_Details["Detection & Analysis"]
B1["⚠️ SIEM Alerts"]
B2["📋 Log Analysis & Forensics"]
B3["👤 User Reports & Escalations"]
B4["🌐 Threat Intelligence Feeds"]
end
subgraph C_Details["Containment Actions"]
C1["🖥️ Isolate Affected Systems"]
C2["🌐 Block Malicious IPs/Domains"]
C3["🔐 Revoke Compromised Credentials"]
C4["📊 Preserve Evidence"]
end
subgraph D_Details["Eradication Steps"]
D1["🐛 Remove Malware & Artifacts"]
D2["🔧 Patch Vulnerabilities"]
D3["🔑 Reset Passwords & Keys"]
D4["🏗️ Rebuild Compromised Systems"]
end
subgraph E_Details["Recovery Process"]
E1["💾 Restore from Clean Backups"]
E2["👀 Intensive Monitoring"]
E3["📈 Gradual Service Restoration"]
E4["✅ Validate System Integrity"]
end
subgraph F_Details["Post-Incident Activities"]
F1["📝 Comprehensive Post-Mortem"]
F2["⚙️ Update Procedures & Runbooks"]
F3["📋 Regulatory Reporting"]
F4["🛡️ Enhance Security Controls"]
end
A --> B & A_Details
B --> C & B_Details
C --> D & C_Details
D --> E & D_Details
E --> F & E_Details
F --> F_Details
A:::phase
B:::phase
C:::phase
D:::phase
E:::phase
F:::phase
A1:::details
A2:::details
A3:::details
A4:::details
B1:::details
B2:::details
B3:::details
B4:::details
C1:::details
C2:::details
C3:::details
C4:::details
D1:::details
D2:::details
D3:::details
D4:::details
E1:::details
E2:::details
E3:::details
E4:::details
F1:::details
F2:::details
F3:::details
F4:::details
A_Details:::preparation
B_Details:::detection
C_Details:::containment
D_Details:::eradication
E_Details:::recovery
F_Details:::postincident
classDef process fill:#1565C0,stroke:#1976D2,stroke-width:3px,color:#FFFFFF
classDef phase fill:#E3F2FD,stroke:#1976D2,stroke-width:3px,rx:10,ry:10
classDef preparation fill:#E3F2FD,stroke:#1976D2,stroke-width:2px,rx:8,ry:8
classDef detection fill:#FFF3E0,stroke:#FF9800,stroke-width:2px,rx:8,ry:8
classDef containment fill:#FFEBEE,stroke:#D32F2F,stroke-width:2px,rx:8,ry:8
classDef eradication fill:#E8F5E9,stroke:#4CAF50,stroke-width:2px,rx:8,ry:8
classDef recovery fill:#F3E5F5,stroke:#9C27B0,stroke-width:2px,rx:8,ry:8
classDef postincident fill:#E1F5FE,stroke:#0288D1,stroke-width:2px,rx:8,ry:8
classDef details fill:#FAFAFA,stroke:#BDBDBD,stroke-width:1px,rx:5,ry:5
style PROCESS stroke:#C8E6C9,fill:#C8E6C9
| Rol | Responsabilidades | Contact |
|---|---|---|
| Incident Commander | Toma decisiones, coordina respuesta | On-call 24/7 |
| Security Lead | Análisis técnico, forensics | PagerDuty P1 |
| DevOps Lead | Containment, recovery de sistemas | PagerDuty P1 |
| Legal/Compliance | Requerimientos regulatorios, notificaciones | Email + Phone |
| Communications | Comunicación con clientes, PR | Email + Phone |
| Executive Sponsor | Aprobaciones, escalamiento | Critical only |
| Level | Descripción | Response Time | Ejemplos |
|---|---|---|---|
| 🔴 P0 - Critical | Breach activo, data loss, servicio completamente caído | 15 minutos | Ransomware, Exfiltración de datos, Total outage |
| 🟠 P1 - High | Intrusión detectada, servicio degradado significativamente | 1 hora | Compromiso de cuenta admin, DDoS attack |
| 🟡 P2 - Medium | Actividad sospechosa, vulnerabilidad crítica descubierta | 4 horas | Múltiples login failures, Port scanning |
| 🟢 P3 - Low | Anomalía menor, sin impacto inmediato | 24 horas | Single failed login, Minor config issue |
## P1 - Account Compromise
### Detección
- SIEM Alert: Multiple logins from different countries
- User report: Unauthorized transactions
### Respuesta Inmediata (< 15 min)
1. **Disable Account**
```bash
kubectl exec -it keycloak-0 -- \
/opt/keycloak/bin/kcadm.sh update users/USER_ID \
-s enabled=false
```
2. **Revoke All Sessions**
```bash
redis-cli KEYS "session:USER_ID:*" | xargs redis-cli DEL
```
3. **Block Source IPs**
```bash
# En Cloudflare WAF
cf-cli firewall create-rule \
--expression "ip.src == MALICIOUS_IP" \
--action block
```
### Investigación (< 1 hora)
4. **Collect Logs**
```bash
# Últimas 24h de actividad
curl -X POST "elastic:9200/logs-*/_search" -d '{
"query": {
"bool": {
"must": [
{"term": {"user_id": "USER_ID"}},
{"range": {"@timestamp": {"gte": "now-24h"}}}
]
}
}
}'
```
5. **Timeline de Eventos**
- Login times & locations
- API calls realizados
- Transacciones ejecutadas
- Cambios de configuración
### Containment (< 2 horas)
6. **Revert Unauthorized Changes**
- Rollback transactions (si es posible)
- Revertir cambios de permisos
- Notificar a compliance
7. **Reset Credentials**
- Force password reset
- Regenerate API keys
- Rotate encryption keys si es necesario
### Notificaciones
8. **Comunicación**
- Cliente: Email + SMS dentro de 1 hora
- Compliance: Reporte dentro de 72 horas (GDPR)
- Regulador: Si >500 usuarios afectados
### Post-Mortem (< 5 días)
9. **Lessons Learned**
- ¿Cómo ocurrió el compromiso?
- ¿Qué controles fallaron?
- Acciones correctivas
| Control | Configuración | Status |
|---|---|---|
| RBAC Enabled | Least privilege por defecto | OK |
| Pod Security Policies | Restringir privileged, hostPath, hostNetwork | OK |
| Network Policies | Deny all por defecto, allow explícito | OK |
| Secrets Encryption | etcd encryption at rest | OK |
| Admission Controllers | PodSecurityPolicy, ImagePolicyWebhook | OK |
| Audit Logging | Log all API server requests | OK |
| Image Scanning | Bloquear imágenes con CVE Critical/High | OK |
# Multi-stage build
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# Runtime image - distroless
FROM gcr.io/distroless/nodejs18-debian11
# Non-root user
USER nonroot:nonroot
# Read-only root filesystem
WORKDIR /app
COPY --from=builder --chown=nonroot:nonroot /app/node_modules ./node_modules
COPY --chown=nonroot:nonroot . .
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD ["/nodejs/bin/node", "healthcheck.js"]
# Drop all capabilities
# Run with --cap-drop=ALL --security-opt=no-new-privileges
EXPOSE 3000
CMD ["index.js"]
apiVersion: v1
kind: Pod
metadata:
name: accounts-service
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: accounts-service:v1.2.0
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL # Drop todas las capabilities
resources:
limits:
memory: "512Mi"
cpu: "500m"
requests:
memory: "256Mi"
cpu: "250m"
volumeMounts:
- name: tmp
mountPath: /tmp
readOnly: false # Solo /tmp es writable
volumes:
- name: tmp
emptyDir: {}
| Control | Configuración |
|---|---|
| Strong Authentication | SCRAM-SHA-256, no MD5 |
| Row-Level Security | Enabled en todas las tablas sensibles |
| SSL/TLS | sslmode=verify-full requerido |
| Audit Logging | pgAudit extension habilitada |
| Least Privilege | Roles separados por microservicio |
| Connection Limits | max_connections por usuario |
-- pg_hba.conf - Solo SSL
hostssl all all 0.0.0.0/0 scram-sha-256
-- postgresql.conf
ssl = on
ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL'
password_encryption = scram-sha-256
-- Row-Level Security
CREATE POLICY user_data_policy ON accounts
USING (account_owner_id = current_setting('app.user_id')::uuid);
ALTER TABLE accounts ENABLE ROW LEVEL SECURITY;
-- Audit Logging (pgAudit)
CREATE EXTENSION pgaudit;
ALTER SYSTEM SET pgaudit.log = 'write, ddl';
ALTER SYSTEM SET pgaudit.log_catalog = off;