// DevOps

Un servidor nuevo — no es una hoja en blanco. Es una puerta sin cerrar.

Publicado el 28.05.2026

Hace unos días analicé el hackeo de un servidor de producción. No teórico — real, con un minero de Monero, un agente C2 y una puerta trasera. El ataque fue completamente automático. Nadie perseguía concretamente ese servidor — simplemente un bot escanea continuamente todo Internet, prueba en bases de datos abiertas con contraseñas por defecto y hace lo suyo.

Desde que el servidor apareció en la red hasta el primer ataque pasaron menos de seis horas. Hasta el compromiso exitoso — menos de un día.

Tres condiciones que lo permitieron: PostgreSQL estaba expuesto, la contraseña era postgres, el firewall no estaba activado. Eso fue todo. No se necesitó nada más.


Por qué esto ocurre incluso con gente experta

Hay cierta psicología alrededor de un servidor nuevo. Acabas de levantarlo, todo funciona, la aplicación responde — y pasas a la siguiente tarea. La seguridad parece algo que se puede configurar después. Después — cuando haya tiempo. Después — antes de producción. Después — tras el lanzamiento.

Ese después nunca llega. O llega, pero ya en forma de top mostrando /tmp/mysql con 400% de CPU.

Un servidor nuevo en Internet no es una hoja en blanco. Es una puerta sin cerrar en una casa que ya está en una calle concurrida. Los escáneres lo encuentran en cuestión de horas, no días.


Lo que realmente ocurrió

El atacante encontró el puerto 5432 abierto en Internet. Lanzó un brute force. La contraseña postgres — eso ni siquiera es brute force, es la primera línea de cualquier diccionario. Obtuvo acceso a PostgreSQL con privilegios de superusuario.

Después entra en juego una función legítima de PostgreSQL — COPY FROM PROGRAM. Permite al superusuario ejecutar comandos arbitrarios de shell directamente desde una consulta SQL. El atacante le pasó a través de ella un script bash en base64, que descargó y ejecutó un dropper.

Pero lo más ingenioso fue la mecánica de persistencia. Se añadieron a la base event triggers — disparadores que se activan en cada operación DDL (CREATE TABLE, ALTER, DROP…). En cada uno de esos eventos recreaban silenciosamente una rol de superusuario con una contraseña conocida por el atacante. Es decir, incluso si el administrador lo hubiera notado y eliminado la rol maliciosa — la siguiente migración o un CREATE INDEX la habría restaurado automáticamente.

Elegante y realmente desagradable.


Tres reglas que bloquean el 99% de estos ataques

No escribo intencionadamente «diez reglas» ni «checklist completo». No porque lo demás no importe — sino porque precisamente estas tres reglas cierran la mayoría de los ataques automatizados que ocurren en la naturaleza.

Las bases de datos no deben ser accesibles desde Internet. PostgreSQL, MySQL, Redis, MongoDB — ninguna está diseñada para acceso directo desde fuera. En docker-compose.yml la línea "5432:5432" para la base de datos — casi siempre es un error. La aplicación se conectará a la base dentro de la red de Docker por nombre de host. Desde fuera ese puerto no le sirve a nadie, salvo a los atacantes.

Si necesita acceso para desarrollo — enlácelo solo a localhost:

ports:
  - "127.0.0.1:5432:5432"

Para producción — quite ports por completo.

Las contraseñas por defecto no son contraseñas. postgres, password, root, admin — esas son las primeras líneas de cualquier diccionario para brute force. Un escáner las probará en segundos, no en horas. Genere la contraseña al desplegar:

POSTGRES_PASSWORD=$(openssl rand -base64 32)

O use gestión de secretos: HashiCorp Vault, AWS Secrets Manager, Doppler. Lo importante — nunca commitee contraseñas en el repositorio y no deje valores por defecto en .env.

El firewall debe estar activado desde el primer minuto. No antes del lanzamiento. No después de la configuración. Desde el primer minuto tras crear el servidor. El modelo correcto — denegar todo por defecto, abrir solo lo necesario:

ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw enable

Después de esto abra puertos concretos según necesidad. No al revés.


Sobre el monitoreo que conviene añadir

Las tres reglas anteriores son para prevención. Pero si también quiere ver lo que ocurre, añada en PostgreSQL un logging mínimo. Por defecto no registra ni conexiones exitosas ni comandos DDL. Eso significa que no tiene visibilidad de lo que ocurre con la base.

En postgresql.conf:

log_connections = on
log_disconnections = on
log_statement = 'ddl'

Y un simple cron-script para comprobar anomalías:

#!/bin/bash
SUPERUSERS=$(psql -U postgres -t -c "SELECT count(*) FROM pg_user WHERE usesuper = true AND usename != 'postgres';")
if [ "$SUPERUSERS" -gt 0 ]; then
    echo "ALERTA: detectados superusuarios no autorizados" | mail -s "Alerta de seguridad" admin@example.com
fi

Eso ya es suficiente para notar algo sospechoso antes de que lo note top.


Por qué esto importa más de lo que parece

Según Shodan, hay más de 800 000 instancias de PostgreSQL abiertas en Internet. Una parte significativa — con contraseñas por defecto o débiles. Nadie las está hackeando manualmente — son escáneres totalmente automatizados, funcionando 24/7. No eligen víctimas por el tamaño del negocio ni por el valor de los datos. Simplemente siguen la lista de puertos abiertos.

Su servidor no es una excepción. Ya está en esa lista. La pregunta es solo si en la puerta hay un candado.

Protegerse de esto no requiere tecnologías complejas, herramientas caras ni una profunda experticia en seguridad. Requiere tres cosas que se pueden hacer en diez minutos al entrar por primera vez en el servidor. Simplemente no las deje para después.

// Reviews

Reseñas relacionadas

Llegué con una solicitud costosa para la configuración de un servidor VPS, pero durante la consulta Mikhail propuso una solución mucho más sencilla y económica. Al final ahorré dinero y tiempo. Mikhail — un verdadero experto que trabaja por el resultado del cliente, no por la factura. ¡Lo recomiendo!

Llegué con una solicitud costosa para la configuración de un servidor VPS, pero durante la consulta Mikhail propuso una solución mucho más simple y económica. Al final ahorré presupuesto y tiempo. Mikhail es un …

kfhzasorin

Configuración de VPS, configuración del servidor

12.05.2026 · ★ 5/5

Hubo varios problemas, tanto en la parte técnica como en la comprensión general. Mijaíl respondió rápido a la solicitud, ayudó a aclarar las cosas y resolvió los problemas técnicos; por ello, muchas gracias. Estoy satisfecho con el resultado.

Hubo varios problemas relacionados tanto con la parte técnica como con la comprensión en general. Mijaíl respondió rápidamente a la solicitud, ayudó a aclarar las cosas y resolvió los problemas técnicos, por lo que le …

abazawolf

Configuración de VPS, configuración del servidor

18.02.2026 · ★ 5/5

// Contact

¿Necesitas ayuda?

Escríbeme y te ayudaré a resolver el problema

Enviar solicitud
Escribir y recibir una respuesta rápida