Minimizando el impacto del SQL injection con IIS7 y LogParser

Hola

Antes de nada, hay que dejar claro que la unica manera efectiva de evitar este tipo de ataques es mediante un desarrollo adecuado de la aplicación web. Sin embargo, al margen del buen hacer de los desarrolladores, el administrador puede y debe también llevar a cabo tareas preventivas y de detección de este tipo de ataques, y configurar el sistema para minimizar su impacto lo más posible.

El principio de defensa en profundidad establece que se debe securizar de manera independiente cada una de las capas de la torre OSI, implementando las contramedidas adecuadas en cada caso. El SQL Injection, como otros ataques similares, sucede a nivel de aplicación y es ahí donde debe ser evitado. Sin embargo, una interpretación libre de ese mismo principio introduce el concepto de "sana desconfianza constructiva" entre los responsables de securizar cada una de las capas. Dicho de otra manera, no debemos contar con la efectividad de las contramedidas que serán implementadas en los niveles superior o inferior, y establecer también en el nuestro todas las que estén en nuestra mano como si la seguridad de todo el sistema dependiera única y exclusivamente de la securización de nuestra capa. Trabajando de esta manera aumenta la probabilidad de tener simultáneamente unos firewalls bien configurados, hosts con el SO y los servicios fortificados, bases de datos bien diseñadas desde el punto de vista de la seguridad, y desarrollos web seguros.

Lo que vamos a utilizar es la funcionalidad de Request Filtering de IIS7 (equivalente a URLScan en IIS6) junto con la herramienta LogParser 2.2. La idea es ser capaces de identificar cuales son las longitudes máximas de URL y consultas que un site/aplicación va a utilizar de manera legítima, y evitar que el servidor web sirva nada que supere esas longitudes. Esto tiene además como efecto colateral que en los casos en que eso suceda, se producirán errores http específicos, que podremos trazar y que se pueden utilizar como un método de detección de intentos de intrusión.

Lo que propongo aquí es una metodología de trabajo sencilla, que luego cada cual puede complicar o refinar lo que quiera. Parto de la base de que existen tres entornos completamente diferentes:

  • El entorno de producción, que es donde viven los servicios y aplicaciones que están dando servicio a clientes internos y/o externos.
  • El entorno de preproducción, donde se prueban los cambios que se van a hacer en el entorno de producción. Debe ser un reflejo exacto del entorno de producción, para que las pruebas que se realicen tengan sentido y podamos aplicarlos con tranquilidad al entorno de producción.
  • El entorno de pruebas/desarrollo, donde los programadores trabajan durante el proceso de creación y depuración de la aplicación web, y los administradores ponen a prueba nuevos servicios, aplicaciones y configuraciones del sistema. Generalmente es un entorno más relajado en cuanto a sus restricciones, donde se busca más la funcionalidad que la seguridad, el rendimiento y la estabilidad.

Una vez se ha terminado el desarrollo de la aplicación, se pasa al entorno de preproducción donde se realizará toda la batería de pruebas necesarias para comprobar que cada una de sus características funcionarán correctamente en el entorno de producción. Para el caso que nos ocupa, es importante que dichas pruebas funcionales contemplen la totalidad de las consultas que la aplicación puede llegar a hacer a las bases de datos. La idea es utilizar posteriormente los logs de IIS en busca de los datos que necesitamos para configurar el servidor web de manera que no sirva URLs o consultas de mayor longitud.

Insisto en que esta metodología no es la panacea universal, y esa es la razón por la que titulo el post "minimizando" y no "evitando".

Request Filtering

En la versión de IIS7 incluida en la RTM de Windows Server 2008, la configuración del Request Filtering se lleva a cabo directamente sobre el fichero web.config a nivel de site, aplicación, o carpeta, ya que no existe interfaz gráfica para hacerlo (la sintaxis esta documentada aqui). Por fortuna, al instalar el IIS7 Administration Pack Technical Preview esta carencia se resuelve y podemos configurar cómodamente con el IIS Manager las extensiones de ficheros que no serviremos, los verbos HTTP permitidos, las secuencias de URL denegadas, los segmentos ocultos y las longitudes de determinadas cabeceras.

Request Filtering - IIS Manager Resquest Filtering 

En nuestro caso estamos interesados en encontrar los valores adecuados para la "Maximum URL lenght" y Maximum query string", aunque es muy posible que queramos afinar también el resto de opciones. Para evitar este tipo de ataques, es frecuente encontrar diccionarios de palabras en la lista de secuencias de URL denegadas, que contemplan la mayor parte de los comandos SQL que se suelen utilizar para construir las sentencias de las consultas.

Formato de los logs de IIS

Por defecto IIS7 guarda sus logs en formato W3C, y podemos elegir qué información queremos almacenar en ellos:

W3C Logging

Los campos del log que nos interesan a nosotros son el URI Stem (cs-uri-stem) y el URI Query (cs-uri-query) del log de IIS que corresponda a la fecha en la que se han realizado las pruebas funcionales de la aplicación.

LogParser 2.2

Como dice en su sitio de descarga, esta es una herramienta muy potente que da acceso universal a datos almacenados en ficheros de texto con diferentes formados (CSV, XML, Logs) y a fuentes de datos del sistema operativo como los logs de eventos, el registro, el sistema de archivos o el directorio activo. Lo curioso es que accedemos a ellos como si estuviésemos haciendo consultas a una base de datos, independientemente de cual sea su origen, y podemos presentar los resultados de diferentes maneras. Lógicamente, utilizarla no es precisamente trivial. De hecho en el IIS7 Administration Pack Technical Preview se ha incluido una nueva funcionalidad, "IIS Logs", basada en algunas de las cosas que se suele hacer con esta herramienta.

LogParser se suele utilizar en ocasiones como herramienta de análisis forense en IIS. En este artículo de Securityfocus se explica cómo hacerlo, y de hecho basta retocar un poco alguna de las consultas que aparecen citadas en él para obtener la información que andamos buscando:

Para sacar la máxima longitud de URL, asi como el número de veces en los que cada URL se ha solicitado:

logparser "SELECT cs-uri-stem, Count(*) As Total, STRLEN(cs-uri-stem) as Longitud FROM C:\inetpub\logs\LogFiles\W3SVC2\u_ex080403.log GROUP BY cs-uri-stem ORDER BY Longitud DESC" -rtp:100

y para la máxima longitud de query, asi como el número de veces que se ha realizado cada consulta:

logparser "SELECT cs-uri-query, Count(*) As Total, STRLEN(cs-uri-query) as Longitud FROM C:\inetpub\logs\LogFiles\W3SVC2\u_ex080403.log GROUP BY cs-uri-query ORDER BY Longitud DESC" -rtp:100

Lo único que hay que variar en los comandos es el path al log que nos interesa. Un ejemplo de los resultados que se obtienen son los siguientes (he utilizado un site con Mediawiki al que he hecho un par de consultas rápidas)

cs-uri-stem

cs-uri-query 

Según esto los datos que tendríamos que utilizar serían 50 para la URL y 84 para la query (no pongáis esto para mediawiki, que os la cargáis seguro), con lo que el fichero web.config quedaría, al margen de las otras opciones de filtrado que queramos introducir:

<configuration>
<system.webServer>
  <security>
   <requestFiltering>

       <requestLimits
       maxAllowedContentLength="30000000"
       maxUrl="30"
       maxQueryString="25"
       />

   </requestFiltering>
  </security>
</system.webServer>
</configuration>

Comprobando si el filtrado esta sirviéndonos o no

Como decía más arriba, el filtrado nos va a dejar errores HTTP personalizados, en particular el 404.14 para las URLs y el 404.15 para las consultas (ver la tabla del final del ya citado How to Use Request Filtering). Nuevamente podemos usar LogParser para buscar en todos los logs ocurrencias de dichos errores y poderlos analizar con detalle para ver si son intentos de ataque o falsos positivos:

logparser "SELECT sc-status, sc-substatus, cs-uri-stem, cs-uri-query, Count(*) As Total FROM C:\inetpub\logs\LogFiles\W3SVC2\u_ex*.log WHERE sc-status='404' and (sc-substatus='14' or sc-substatus='15') GROUP BY sc-status, sc-substatus, cs-uri-stem, cs-uri-query ORDER BY sc-substatus DESC" -rtp:100

Seguramente hay otros muchos métodos, herramientas, etc. pero esto lo usé para preparar una demo de seguridad en IIS7, y al menos quería dejarlo documentado.

Muchas gracias a Maligno por haber inspirado este post con sus comillas y sus asteriscos, y a Nacho Alonso por echarme una mano con las queries SQL, como ha hecho siempre con otras muchas cosas (este tipo es de los que si que saben, y mucho, y además lo saben contar).

Saludos

David Cervigón

Technorati tags: SQL Injection, LogParser, IIS, Securityfocus, Nacho Alonso