Cómo hacer una auditoría de seguridad en AWS: guía práctica para equipos DevOps
Procedimiento de auditoría de seguridad de un entorno AWS: desde la revisión de IAM, pasando por la configuración de red, hasta el cifrado y el monitoreo. Un checklist listo para evaluaciones periódicas.
Si necesita apoyo externo para ejecutar una auditoría de seguridad cloud, consulte nuestro servicio de consultoría de DevOps y seguridad cloud.
Cuándo ejecutar una auditoría
- Antes de migrar producción a una cuenta AWS nueva
- Después de un incidente de seguridad o una brecha sospechada
- En un ciclo trimestral (cada seis meses como mínimo)
- Antes de una auditoría de cumplimiento (SOC 2, ISO 27001, NIS2)
- Después de cambios significativos en la infraestructura (nueva VPC, nueva cuenta en la organización)
Herramientas de automatización
Antes de empezar una revisión manual, ejecute escáneres automatizados:
# AWS Security Hub - comprobación de cumplimiento nativa
aws securityhub get-findings --filters '{"RecordState":[{"Value":"ACTIVE","Comparison":"EQUALS"}]}' \
--query 'Findings[?Severity.Label==`CRITICAL`].[Title,Resources[0].Id]' --output table
# Prowler - auditoría de AWS open-source (instalación: pip install prowler)
prowler aws --severity critical high --output-formats json-ocsf html
# ScoutSuite - auditoría de seguridad multi-cloud
scout aws --report-dir ./audit-$(date +%Y%m%d)
# AWS Trusted Advisor (requiere soporte Business/Enterprise)
aws support describe-trusted-advisor-checks --language en \
--query 'checks[?category==`security`].name'
Prowler cubre más de 300 comprobaciones de CIS AWS Benchmark, PCI-DSS y GDPR. Si solo puede ejecutar una herramienta, elija Prowler.
Checklist: IAM y acceso
Cuenta root
# Comprobar si root tiene claves de API (NO debería tenerlas)
aws iam get-account-summary --query 'SummaryMap.AccountAccessKeysPresent'
# Resultado esperado: 0
# Comprobar si el MFA está activado en root
aws iam get-account-summary --query 'SummaryMap.AccountMFAEnabled'
# Resultado esperado: 1
| Punto de control | Estado esperado | Cómo comprobarlo |
|---|---|---|
| La cuenta root no tiene claves de API | AccountAccessKeysPresent = 0 | aws iam get-account-summary |
| MFA en la cuenta root | AccountMFAEnabled = 1 | aws iam get-account-summary |
| Cuenta root sin uso durante >90 días | Sin inicio de sesión reciente | Credential Report |
| MFA en todos los usuarios IAM con acceso a consola | Cobertura del 100% | aws iam generate-credential-report |
| Sin políticas inline en los usuarios | Todo a través de grupos/roles | prowler aws -c iam_inline_policy_no_administrative_privileges |
| Rotación de claves de API <90 días | Sin claves obsoletas | Columna access_key_last_rotated del Credential Report |
Políticas y roles
# Encontrar usuarios con AdministratorAccess
aws iam list-entities-for-policy \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess \
--query '[PolicyUsers[].UserName, PolicyGroups[].GroupName, PolicyRoles[].RoleName]'
# Encontrar políticas con comodín (*) en acciones y recursos
aws iam list-policies --scope Local --query 'Policies[].Arn' --output text | \
xargs -I {} aws iam get-policy-version --policy-arn {} \
--version-id $(aws iam get-policy --policy-arn {} --query 'Policy.DefaultVersionId' --output text) \
--query 'PolicyVersion.Document'
# Roles sin uso (sin assume en los últimos 90 días)
aws iam generate-service-last-accessed-details --arn arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME
Checklist: red y acceso
# Security Groups con 0.0.0.0/0 abierto en puertos distintos de 80/443
aws ec2 describe-security-groups \
--filters Name=ip-permission.cidr,Values='0.0.0.0/0' \
--query 'SecurityGroups[].{Name:GroupName,ID:GroupId,Rules:IpPermissions[?IpRanges[?CidrIp==`0.0.0.0/0`]].{Port:FromPort,Proto:IpProtocol}}' \
--output table
# Subredes públicas sin NAT Gateway (posible vector de ataque)
aws ec2 describe-route-tables --query 'RouteTables[].Routes[?GatewayId!=null && DestinationCidrBlock==`0.0.0.0/0`]'
# VPC Flow Logs - comprobar si están activados en todas las VPC
aws ec2 describe-flow-logs --query 'FlowLogs[].{VPC:ResourceId,Status:FlowLogStatus,Dest:LogDestination}'
| Punto de control | Estado esperado |
|---|---|
| Ningún SG con 0.0.0.0/0 en SSH (22) o RDP (3389) | Cero resultados |
| VPC Flow Logs activados en cada VPC | 100% |
| Sin IP públicas en instancias de base de datos | Cero resultados |
| NACL que bloqueen rangos de IP maliciosos conocidos | Configurado |
| Ninguna VPC por defecto en uso para producción | Eliminada o vacía |
Checklist: cifrado y almacenamiento
# Buckets S3 sin cifrado por defecto
aws s3api list-buckets --query 'Buckets[].Name' --output text | tr '\t' '\n' | while read bucket; do
enc=$(aws s3api get-bucket-encryption --bucket "$bucket" 2>&1)
if echo "$enc" | grep -q "ServerSideEncryptionConfigurationNotFoundError"; then
echo "SIN CIFRADO: $bucket"
fi
done
# Buckets S3 con acceso público
aws s3api list-buckets --query 'Buckets[].Name' --output text | tr '\t' '\n' | while read bucket; do
status=$(aws s3api get-public-access-block --bucket "$bucket" 2>&1)
if echo "$status" | grep -q "NoSuchPublicAccessBlockConfiguration"; then
echo "SIN BLOQUEO DE ACCESO PÚBLICO: $bucket"
fi
done
# Volúmenes EBS sin cifrado
aws ec2 describe-volumes --filters Name=encrypted,Values=false \
--query 'Volumes[].{ID:VolumeId,Size:Size,State:State}' --output table
# RDS sin cifrado en reposo
aws rds describe-db-instances \
--query 'DBInstances[?StorageEncrypted==`false`].{ID:DBInstanceIdentifier,Engine:Engine}' --output table
Checklist: logging y monitoreo
# CloudTrail - comprobar si está activo y es multi-región
aws cloudtrail describe-trails --query 'trailList[].{Name:Name,MultiRegion:IsMultiRegionTrail,Logging:HasCustomEventSelectors}'
aws cloudtrail get-trail-status --name default --query '{IsLogging:IsLogging,LatestDelivery:LatestDeliveryTime}'
# Config - comprobar si AWS Config está registrando
aws configservice describe-configuration-recorders \
--query 'ConfigurationRecorders[].{Name:name,Recording:recording}'
# GuardDuty - comprobar si está activado
aws guardduty list-detectors --query 'DetectorIds'
# Alarmas en eventos clave (login de root, cambios en políticas IAM)
aws cloudwatch describe-alarms --alarm-name-prefix "Security-" \
--query 'MetricAlarms[].{Name:AlarmName,State:StateValue}'
| Punto de control | Estado esperado |
|---|---|
| CloudTrail activo, multi-región | IsLogging: true, Multi-región: true |
| CloudTrail registra en una cuenta separada (log archive) | Bucket en una cuenta distinta |
| AWS Config registrando cambios | Recording: true |
| GuardDuty activado en cada región | DetectorId en cada región |
| Alarma en el login de root | Configurada y activa |
| Alarma en CreateUser/AttachPolicy | Configurada y activa |
Cómo reportar los resultados
Después de ejecutar Prowler, genere un reporte:
# Reporte completo con priorización
prowler aws --severity critical high medium \
--output-formats html csv json-ocsf \
--output-directory ./audit-report-$(date +%Y%m%d)
# Comparar con la auditoría anterior
prowler aws --severity critical high \
--output-formats csv \
| diff previous-audit.csv - > delta-findings.txt
El reporte debería clasificar los hallazgos:
- Críticos - corregir en 24 horas (claves root abiertas, bases de datos públicas)
- Altos - corregir en una semana (MFA ausente, cifrado ausente)
- Medios - planificar para el siguiente sprint (rotación de claves, roles sin uso)
Automatizar auditorías periódicas
Programe la auditoría como un pipeline periódico (por ejemplo, semanal en CI/CD):
# .github/workflows/security-audit.yml
name: Weekly AWS Security Audit
on:
schedule:
- cron: '0 6 * * 1' # lunes 6:00 UTC
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Prowler
run: pip install prowler
- name: Run audit
run: prowler aws --severity critical high --output-formats json-ocsf html
env:
AWS_ACCESS_KEY_ID: $
AWS_SECRET_ACCESS_KEY: $
AWS_DEFAULT_REGION: eu-central-1
- name: Upload report
uses: actions/upload-artifact@v4
with:
name: security-audit-$
path: output/
El rol IAM para la auditoría debería tener la política gestionada SecurityAudit + ViewOnlyAccess, sin permisos de escritura.
¿Ya hizo esta auditoría por su cuenta? Formalícela con un Well-Architected Review.
Una revisión de arquitectura gratuita de 30 minutos cubre seguridad, costo y fiabilidad en un formato estructurado, y hace que sus hallazgos califiquen para el descuento del 10% de AWS sobre la remediación. No se necesita acceso para la conversación inicial.
Próximos pasos
- Corregir de inmediato los hallazgos críticos
- Implementar AWS Config Rules para monitoreo continuo
- Considerar AWS Organizations con SCP (Service Control Policies) como guardrails
- Configurar Security Hub con agregación automática de hallazgos
Si necesita ayuda para ejecutar una auditoría o implementar automatización de seguridad, póngase en contacto.