// DevOps

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

Publicado el 22.09.2026

Hace unos días investigué el hackeo de un servidor de producción. No teórico — real, con un minero Monero, un agente C2 y un backdoor. El ataque fue completamente automático. Nadie perseguía específicamente ese servidor — simplemente un bot escanea continuamente todo Internet, intenta acceder a 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 es todo. No se necesitó nada más.


Por qué esto ocurre incluso con gente experimentada

Hay una cierta psicología con 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 no 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 llave en una casa que ya está en una calle concurrida. Los escáneres lo encuentran en cuestión de horas, no de días.


Qué pasó realmente

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

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

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

Elegante y realmente desagradable.


Tres reglas que bloquean el 99% de estos ataques

Deliberadamente no escribo “diez reglas” ni “checklist completo”. No porque lo demás no sea importante — sino porque estas tres reglas cierran la mayoría de los ataques automatizados que realmente ocurren en la naturaleza.

Las bases de datos no deben estar accesibles desde Internet. PostgreSQL, MySQL, Redis, MongoDB — ninguna está pensada 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 puede conectarse a la base dentro de la red de Docker por el nombre del host. Desde fuera ese puerto no lo necesita nadie salvo los atacantes.

Si necesitas acceso para desarrollo — enlaza solo a localhost:

yaml
ports:
  - "127.0.0.1:5432:5432"

Para producción — elimina ports por completo.

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

bash
POSTGRES_PASSWORD=$(openssl rand -base64 32)

O usa un gestor de secretos: HashiCorp Vault, AWS Secrets Manager, Doppler. Lo importante — nunca comites contraseñas al repositorio y no dejes 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 — todo denegado por defecto, solo abrir lo necesario:

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

Después abre puertos concretos según necesidad. No al revés.


Sobre el monitoreo que vale la pena añadir

Las tres reglas anteriores son para prevención. Pero si también quieres ver lo que ocurre, añade en PostgreSQL un logging mínimo. Por defecto no registra ni las conexiones exitosas ni las órdenes DDL. Eso significa que no tienes visibilidad de lo que pasa en la base.

En postgresql.conf:

log_connections = on
log_disconnections = on
log_statement = 'ddl'

Y un script cron simple para comprobar anomalías:

bash
#!/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: se han detectado superusuarios no autorizados" | mail -s "Alerta de seguridad" admin@example.com
fi

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


Por qué es más importante de lo que parece

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

Tu servidor no es una excepción. Ya está en esa lista. La pregunta es si la puerta tiene cerrojo.

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

Más detalles sobre cada línea de defensa — en la serie «Protección del servidor Linux»: cortafuegos UFW, Fail2ban, CrowdSec y auditoría con Lynis.

// 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

Respondo en un día laborable (03:00-13:00 GMT)

Или оставьте заявку здесь:

Confirme que no es un bot.

Escribir y recibir una respuesta rápida