Recientemente hemos sufrido un ataque informático contra nuestra base de datos SQL Server 2008 R2 expuesta en Internet.
Por casualidad nos pusimos a mirar el log de errores y descubrimos que había más de 2 millones y medio de intentos de inicio de sesión erróneos del usuario sa desde hace más de 2 meses.
El cómo no nos dimos cuenta en todo ese tiempo de que estábamos siendo atacados por fuerza bruta contra el usuario sa daría para otro post, pero ahora lo más importante es intentar incrementar drásticamente la seguridad de nuestro servidor SQL Server en Internet y dejar de buscar culpables… sobre todo porque yo mismo soy el principal culpable!
“Cabe resaltar que este post asume un escenario con un servidor VPS donde se tienen plenos derechos de administración accediendo por escritorio remoto, es decir, no estoy hablando de Windows Azure ni de un hosting compartido”
La medida más efectiva para evitar ataques contra tu servidor SQL Server en Internet es NO exponerlo a Internet. Esto parece de perogrullo, pero a veces no es tan obvio. ¿Por qué expones tu servidor SQL Server en Internet? Normalmente será porque los desarrolladores argumentan que necesitan acceder a la base de datos para consultar datos, realizar cambios, etc. Yo creo que los desarrolladores (entre los que yo me incluyo) deberíamos pensar que un sistema en producción no es nuestra banco de pruebas personal y que si realmente necesitamos acceder a los datos del servidor hay otras herramientas para darnos acceso sin comprometer la seguridad del servidor. Por ejemplo, escritorio remoto, una VPN, etc.
La verdad es que para un sistema SQL Server en producción no se me ocurre ninguna buena razón para exponerlo directamente en Internet.
Antes de ver que medidas tomamos para garantizar la seguridad de nuestro servidor, la pregunta es ¿Cómo me doy cuenta de que estoy siendo atacado? Pues mirando el log de errores de SQL Server. El log de errores de SQL Server lo podemos consultar de 2 formas distintas:
- De forma manual, accediendo a Administración > Registros de SQL Server
- A través de T-SQL, con el comando xp_ReadErrorLog
En cualquiera de los 2 casos podrás ver una información como la siguiente (aquí optamos por el comando xp_ReadErrorLog que es más directo)
xp_ReadErrorLog 0, 1, 'failed'
LogDate | ProcessInfo | Text |
2012-02-23 10:39:25.710 | NULL | Login failed for user 'sa'. Motivo: la contraseña no es válida para el inicio de sesión proporcionado. [CLIENTE: <local machine>] |
Ahora imagina este registro pero multiplicado por 2.5 millones de veces con distintas IP y desde hace 2 meses…y 2.5 GB de log de regalo… ¡terror!
Lo primero es cortar de raíz el acceso al servidor SQL Server desde Internet, y esto es tan sencillo cómo deshabilitar las siguientes reglas del firewall (puede que en tu equipo no se llamen igual, pero básicamente responderán al mismo propósito):
- MS SQL over TCP protocol. Puerto 1433 sobre TCP.
- MS SQL Probe. Puerto 1434 sobre UDP.
En este momento ya estamos seguros porque NO exponemos nuestro servidor SQL Server a Internet, pero ¿Qué pasa si tuviéramos necesidad de hacerlo por algún motivo que ahora mismo se me escapa?
Pues te cuento que según mis investigaciones en google y con la ayuda del sentido común (el menos común de los sentidos por otra parte) las medidas que vamos a tomar son las siguientes:
1. Asegurarnos que todas las claves de los login de SQL Server responden a una política de contraseñas fuerte que impiden poner nombres como “Pepe” o “God”. Esto es porque así los diccionarios de ataques por fuerza bruta no encontrarán nuestra contraseña a la primera de turno y además, cuando empiecen a generar contraseñas de forma aleatoria, les cueste más… Gracias a esto después de 2 meses, nuestro servidor no ha sido hackeado (esta es la única triste medalla que podemos lucir a día de hoy).
A este respecto podemos instruir a SQL Server para garantizar una política de contraseñas e incluso forzar la expiración de los login de SQL Server. Más info aquí. Yo por mi parte no voy a activar esta configuración pero prometo que mi contraseña será de muuuchos caracteres, con números, mayúsculas y minúsculas y algún carácter especial como la arroba o el ampersand.
2. Cambiar el puerto por defecto donde escucha SQL Server. Por defecto, SQL Server atiende al puerto 1433 (puerto bien conocido o como dicen en inglés, well known port). Esto significa que cualquier escáner de puertos que detecte que esté abierto el puerto 1433 automáticamente nos dirá que tenemos a SQL Server a la escucha, luego seremos una victima pidiendo a voces un verdugo.
Una lista completa de estos puertos “bien conocidos” la puedes encontrar en la Wikipedia, que por ejemplo nos dice que los siguientes puertos son “bien conocidos”:
- 1433/tcp Microsoft-SQL-Server
- 1434/tcp Microsoft-SQL-Monitor
- 1434/udp Microsoft-SQL-Monitor
Primero vamos a hacer un ejemplo con los puertos abiertos para ver que información nos da un escáner de puertos on-line como http://www.internautas.org/w-scanonline.php
Con los puertos abiertos (sin haber desactivado las reglas del firewall):
Con los puertos cerrados (habiendo desactivado las reglas del firewall):
Aunque en este post nos estamos centrando en los puertos 1433 TCP (puerto por defecto para SQL Server) y 1434 UDP (puerto por defecto para el servicio SQL Server Browser), hay otros puertos menos habituales pero también relacionados con SQL Server que también podrían estar abiertos. Puedes encontrar más información sobre estos puertos aquí.
Además y aunque no es el propósito de este post, si utilizamos instancias con nombre podríamos estar utilizando puertos dinámicos. Un excelente post que habla sobre ello y lo deja muy claro SQL Server runs on which port? Y otro post más que indica como averiguar que puerto concreto está utilizando SQL Server si estamos utilizando los puertos dinámicos How to Find the Dynamic Port reserved by SQL Server?
En cualquier caso, nosotros no tenemos instancias con nombre y la instancia por defecto utiliza el puerto 1433, así que lo cambiaremos a cualquier otro puerto en el rango 49152-65535 (este es el rango para puertos personalizados que seguro no nos darán problemas mañana con la instalación de otros programas). Imaginemos que lo cambio por ejemplo al puerto 50215. El procedimiento para cambiar el puerto está muy bien explicado aquí.
Después de esto ya sólo nos queda crear una regla en el firewall de Windows, en la que incluso podríamos acotar que direcciones IP podrán conectar (yo por mi parte sólo daré acceso a la IP pública de mi oficina).
3. Deshabilitar la cuenta del usuario sa. Esta medida responde a que es por todos conocidos que cualquier instalación de SQL Server tendrá un usuario sa con privilegios administrativos sobre el servidor. Pero claro está que si deshabilitamos esta cuenta, nuestro atacante no sabrá con que login de SQL Server llevar a cabo su ataque. Lógicamente, antes de deshabilitar la cuenta sa estate seguro de que has creado otro login con los mismos privilegios que el usuario sa o que tienes agregada alguna cuenta de usuario de Windows al role de servidor sysadmin.
Hasta aquí hemos llegado con el propósito de intentar poner las cosas un poco más difíciles a nuestros queridos “amigos de lo ajeno”.
Un saludo!