Archivo de 4 junio 2008

La semana pasada era atacado un sitio Web alojado por nosotros y, para colmo, realizado también por nuestro equipo. El ataque era trivial, como siempre, mediante inyección SQL (SQL-injection) y había seguido los procedimientos habituales.

Para quien no esté familiarizado, describo a continuación la técnica, bien explicada y masivamente difundida (demasiado, a buen seguro) por Chema Alonso:

Generalidades

Los ataques de inyección SQL se realiza mediante el envío de una sentencia SQL hacia un parámetro o campo de formulario que va a ser leído por una aplicación web para su procesamiento. En otras palabras, los atacantes intentarán completar una instrucción SQL especialmente “maligna” cuando ofrezcamos en una página web un formulario o un parámetro dentro del encabezado (del tipo, por ejemplo, http://midominio.com/listado.asp?id=23).

Esto es empleado, generalmente y menos mal, para cambiar datos en las bases de datos que almacenan la información que se presenta en la web. Y digo “menos mal” porque también podría ser utilizado para borrar una tabla, conseguir un usuario de la base de datos, etc.

Usualmente el fin consiste en cambiar de cara (defacement) de la web para colocar otro texto o imágenes identificando al hacker o con un mensaje alusivo. Estos delincuentes “menores” (ha habido ataques hace muy poco de este tipo que han limpiado webs tan concurridas como la Jazztel, Izquierda Unida y otras; han sido pillados -lee la crónica de Chema Al talego o a por talegos-) parece que pretenden ser los primeros en el top de Zone-h o cosas por estilo, no les da para mucho más. El problema es que los que están detrás sufrimos y mucho.

Técnica

La técnica no es muy complicada y suele ser parecida a la siguiente:

  1. Lo primero es buscar una víctima, pero para eso qué mejor que Google, para eso está. Introducimos una cadena que pueda representar una vulnerabilidad (por ejemplo una búsquda del tipo “inurl:listado.asp?id” y a ver que nos dice el buscador (para comprender mejor esto recomiendo el libro “Hacking Google” de Johnny Long
  2. Una vez localizada una posible víctima, se suele probar a ver si es vulnerable. Las pruebas suelen hacerse intentando romper una cadena y ver lo que canta.
  3. La técnica se basa en romper la sentencia SQL que haya programado el desarrollador y anexar otra sentencia maliciosa.
    Imaginemos que presentamos un formulario para buscar un nombre que presenta un campo llamado “apellido”. El valor introducido por el usuario lo tratamos por una página que tendrá una sentencia del tipo "SELECT * FROM usuario WHERE usr_apellido='" & apellido & "' ".
    Si un hacker nos introduce “algo de SQL” en el campo “apellido” puede hacer romper la sentencia SQL y realizar otras acciones. En este ejemplo, se podría introducir algo similar a:
    Apellido: kk' or 1=1 --
    Con esto la sentencia quedaría:
    "SELECT * FROM usuario WHERE usr_apellido='kk' or 1=1 -- ' "
    Observad que esa condición (con el “or 1=1”) se cumple siempre y, por tanto, devolverá algún registro (seguramente el primero aunque no exista el apellido “kk”, ideal para romper formularios de validación). El doble guión medio es usado para que el resto de la sentencia se entienda como comentario (según MS SQL Server, en otros SQL es parecido) y no produzca errores.

  4. Siguiendo así, seguramente probarán distintos valores para conocer nombres de campo, tablas, usuarios, etc. En esto les ayuda nuestro generoso sistema que le va diciendo dónde está el error, con su nombre de campo, tabla, etc. En el ejemplo del ataque sufrimos la semana pasada, el hacker incluso hizo:
    www.miweb.com/listado.asp?id=Convert(int,(select+user));--
    en la URL y nuestro sistema, amable de verdad, le contestó:
    Error de sintaxis al convertir el valor nvarchar 'usuario_de_la_bd' para una columna de tipo de datos int.
  5. Siguiendo así, al final realizará una sentencia:
    UPDATE tabla SET campo='Hacked by SuperHackilistico'
    y todos los valores tendrán esa cadena, que a buen seguro se lucirá flamante en la página de inicio de nuestra web.

El problema

El problema está en el desarrollo, no en el sistema que alberga la web ni en el de base de datos. Hace tiempo la gente ni se planteaba hacer cosas así, por lo que se programaba sin seguridad de ese tipo, pero hoy en día es muy frecuente este tipo de ataques.

En concreto, el día 28 del mes pasado, recibía un mensaje de Jorge Chinea del INTECO-CERT advirtiendo lo siguiente:

Estimados colaboradores,

En los últimos días se han detectado ataques masivos contra sitios web con el objetivo de manipular su funcionalidad y contenido. Una vez comprometidas, las paginas Web manipuladas redirigirán a sus visitantes a sitios web maliciosos expresamente diseñados para descargar e instalar todo tipo de códigos maliciosos en el ordenador que podrán permitir al atacante su control.

Desde INTECO-CERT se alertó en anteriores ocasiones la existencia de este tipo de ataques para comprometer los sitios web. Se trata de ataques de tipo inyección SQL, aprovechando una vulnerabilidad en el Internet Information Server (IIS), provocada por una errónea programación del código ASP (Active Server Pages).

Estos ataques masivos están apoyados en herramientas automáticas con las que logran infectar gran número de sitios web en poco tiempo. El número total de páginas comprometidas a día de hoy ronda los 1’5 millones, aunque muchas de ellas ya han sido o están siendo corregidas.

Recomendamos a todos los webmasters que tengan sus páginas ASP alojadas en servidores IIS comprobar, lo antes posible, si sus páginas web han podido verse afectadas. Un síntoma claro de la infección puede ser la existencia de código javascript externo desconocido y que apunte a alguno de los dominios indicados en el siguiente listado (y que iremos actualizando):

Listado de dominios maliciosos

De cara a los usuarios finales, para evitar infecciones, aconsejamos seguir las recomendaciones básicas que siempre se deben adoptar ante incidentes de seguridad:

* Utilizar software de seguridad como antivirus, cortafuegos, antiespias, etc.
* Tener actualizadas todas las aplicaciones de nuestro sistema, sobre todo sistema operativo y navegador, con los últimos parches de seguridad.
* Utilizar por defecto cuentas limitadas de usuario -no de administrador- con lo que limitaremos en gran medida los efectos de una posible infección.

Usuarios con conocimientos técnicos más avanzados pueden optar por deshabilitar el javascript en el navegador de manera temporal o instalar alguna extensión, como NoScript, que permita tener un control más exhaustivo sobre la ejecución de secuencias de comandos.

Es evidente que los desarrolladores deben prestar más atención en el código y poner filtros que anulen algunos caracteres y sentencias peligrosas.

En nuestro caso, ahora lo hacemos de forma usual, pero es cierto que siempre quedan desarrollos antiguos no actualizados que pueden ser vulnerables.

Contramedidas

Ya que conocemos el problema, solo nos falta ponerle solución. Esta se encuentra “simplemente” en filtrar lo que nos venga a páginas que admiten parámetros (ya sea por GET o por POST). Y digo “simplemente” porque hay que completar código y eso a veces da más que pereza.

El mismo Jorge Chinea planteaba la cuestión de la forma siguiente:

Con respecto a los ataques masivos contra sitios Web de los últimos días hemos estado viendo diferentes soluciones:

1.- La solución definitiva, que sería revisar todas las paginas asp verificando la entrada de datos para que no permitan inyecciones de SQL.
2.- El parche para las inyecciones que modifican datos: Usar un usuario para las consultas genéricas de la base de datos con permisos de solo lectura en las tablas y otro para la administración de la web, añadir/modificar contenidos… Con esto ya no se podrían modificar datos en la web

Pero me parece mucho más elegante otra solución que se planteó en el mismo foro (denominado RESCATA -Red Nacional de Sensores Antivirus- en la que colaboro) ofrecida por Juan Cascón de Vocento-ABC y que incluyo a continuación:

Function ControlSQLInjection(texto)
  ' Autor: Juan Cascón:  xxx@abc.es
  on error resume next
    Dim res
    res = LCase(texto)
    res = Replace(res, "[", "[[" & Chr(0))
    res = Replace(res, "]", "[]]")
    res = Replace(res, "< ", "")
    res = Replace(res, ">", "")
    res = Replace(res, "script", "")
    res = Replace(res,"select","")
    res = Replace(res,"table","")
    res = Replace(res,"create","")
    res = Replace(res,"insert","")
    res = Replace(res,"update","")
    res = Replace(res,"delete","")
    res = Replace(res,"drop","")
    res = Replace(res,"exec","")
    res = Replace(res,"declare","")
    res = Replace(res,"alter","")
    res = Replace(res,"union","")
    res = Replace(res,"null","")
    res = Replace(res,"schema","")
    res = Replace(res,"execute","")
    res = Replace(res,"-","")
    res = Replace(res,";","")
    res = Replace(res,"""","")
    res = Replace(res, "[[" & Chr(0), "[[]")
    res = Replace(res, "'", "''")
    res = Replace(res, "%", "[%]")
    res = Replace(res, "_", "[_]")
    res = Replace(res, "#", "[#]")
    res = Replace(res, CHR(13), "")
    res = Replace(res, CHR(10), "")
    res = Replace(res, CHR(0), "")
    res = Replace(res, "=", "")
    res = Replace(res, "&", "")
    res = Replace(res, "$", "")
    res = Replace(res, "@", "")
    res = Replace(res, "(", "")
    res = Replace(res, ")", "")
    res = Replace(res, "\", "")
    res = Replace(res, ",", "")
    res = Replace(res, "\'", "")
    res = Replace(res, "+", "")
    ControlSQLInjection = res
End function

Invocando a esta función en cada recepción de datos de un formulario o enlace, podemos considerar que estamos protegidos frente a este tipo de amenazas.

Etiquetas: , , , , , ,

Comments No Hay Comentarios »