He leído: Dissecting SQL Server Execution Plans de Grant Fritchey

Descárgalo Los libros gratuitos proliferan como hongos tras día de lluvia por la red. Pero la categoría de los libros gratuitos que merece la pena leer y ya no digo imprimir creo que se cuenta con los dedos de las manos. Suelo descargar todo libro gratuito del que tengo noticia si la temática me interesa. Muchos pululan durante meses por mi escritorio, victimas de cortas visitas en los que los ojeo (¿será ojear correcto tratandose de libros electrónicos? ). Rara vez alguno me resulta del interés suficiente como para que no desaparezca en las profundidades de la papelera de reciclaje tras unos cuantos meses, cuando llego al convencimiento, una vez más, que gratuito no quiere decir interesante. Sin embargo, a pesar de las continuas decepciones sigo manteniendo una media de media decena de libros electrónicos en mi escritorio. El motivo no es otro que a veces, raras veces, se descubre una joya, un libro realmente interesante, uno que incluso merece el honor de abandonar el triste PDF y pasar a ser un libro, uno de verdad, impreso en papel, y que ocupa un lugar en la mesilla de noche en lugar de en el escritorio. Hacia mucho que esto no ocurria, desde que descubrí el ya mítico Scrum and XP from the Trenches.

Pero a vuelto a ocurrir. Se trata de Dissecting SQL Server Excution Plans de Grant Fritchey, obra definitiva a la hora de entender los planes de ejecución de SQL Server, saber como trabajar con ellos, leerlos e interpretarlos hasta el más mínimo detalles. Todos los que tenemos interés por la optimización sabemos de la importancia de los planes de ejecución a la hora de analizar por qué una consulta se está comiendo el procesador de nuestro servidor de SQL Server o cualquier otro problema de rendimiento. Pero la verdad es que la cantidad de operadores que pueden aparecer en un plan de ejecución es muy alta y la información que Microsoft nos proporciona sobre los mismos en los libros en pantalla de SQL Server es cuando menos escasa. Pues bien, mi amigo Pablo Alvarez Doval, esta de suerte, tras leer a fondo este libro, no va a recibir más llamadas mias preguntándole cual es la diferencia entre un Nested Loop y un Hash Match y cual es ‘menos malo’ y por qué aparece uno u otro… Gracias a este libro ahora conozco todo los secretos que un plan de ejecución esconde.

Además, no tiene despercio la parte de introducción sobre que ocurre desde que el servidor recibe una consulta hasta que devuelve los datos, proceso que ya conocía pero que está estupendamente explicado en el libro. Resumiendo, aquellos que no tengáis en vuestro movil el teléfono de Doval, estáis tardando en descargar el libro y deborarlo.

P.D.: Txukito, este post está dedicado a tí. Este libro te vendrá muy bien en tu nueva andadura. Te desearía suerte, pero no te hace falta.

Protegerse de las inyecciones SQL por URL

Stop Nos contaba el otro día el vecino de blog Gustavo Velez como su sitio, que corre sobre Sharepoint, ha sido atacado. Todos los que gestionamos algún tipo de comunidad online sabemos que Internet se ha convertido en un lugar peligroso donde un motón de delicuentes, amparándose en el anonimato, se dedican a hacer la vida imposible a todo aquel que quiere contar algo al mundo. Desde que gestiono Geeks.ms la cantidad de maldades que el sitio ha sufrido han sido incontables y de todo tipo. Todas con un mismo afán: colar spam en el sitio o lograr colar spam a los usuarios del sitio publicando URLs maliciosas en el mismo. Sin duda el spam es un lacra y una enorme amenaza para Internet. El ataque que ha sufrido el sitio de Gustavo también tenia ese mismo fin.

Uno de los ataques más frecuentes en los últimos tiempos es una variación de las clásicas inyecciones de SQL: la inyección de SQL por URL. Se trata en esencia de pasar en la URL una cadena SQL para tratar de que el sistema atacado la ejecute. La principal protección frente a este tipo de situaciones es un buen diseño de la aplicación, protegerse de cross site scripting, de los ataques de inyección en general, y de los de SQL en particular y utilizar un enfoque de continua defensa cuando se desarrollan soluciones. Por ejemplo, utilizar consultas parametrízadas siempre nos evitará un motón de quebraderos de cabeza relacionados con las inyecciones de SQL (sean por URL o no y sea la aplicación Web o de escritorio). El problema es que en una aplicación basta cometer un solo error para que sea comprometida. Como todos los desarrolladores cometemos errores (los desarrolladores, pese a lo que algunos piensen, tamibén somos humanos) la conclusión es que toda aplicación es probable que contenga errores explotables por terceros para hacer el mal. En resumen, aunque es sumamente importante, solo el ser cuidadoso en lo referente a la seguridad durante el desarrollo a menudo no es suficiente.

La buena noticia, es que contamos con una segunda táctica de defensa, que siempre debe ser adicional al buen diseño: la posibilidad una vez desplegada la aplicación asegurarla mediante otros sistemas adicionales. Los firewalls, los filtros antispam y los sitemas de detección de intrusiones son el ejemplo más conocido de estos sistemas adicionales de protección. Pero en el caso que nos ocupa, ninguno de estos tres sitemas nos serviran de ayuda. Esto me llevo a pensar ¿qué podríamos hacer para evitar las peticiones maliciosas que intentan ataques SQL por URL?.

La conclusión es evidente: si logramos detener esas peticiones maliciosas ‘en la puerta’, no pasará nada aunque nuestra aplicación sea vulnerable. Contaremos con una defensa adicional. Lo importante es que los ‘juanquers’ tienden a atacar aquellos sitios menos protegidos. Si un ‘juanquer’ ataca un sitio y ve que tiene ciertas protecciones recibe un mensaje claro: este sitio está administrado por alguien que va a tratar de ponerte las cosas dificiles. Por lo tanto el ‘juanquer’ moverá sus efuerzos a otro sitio. Muchos de estos ataques son llevados a cabo por bots automatizados, que comprueban si sus esfuerzos son productivos o no y si no lo son simplemente sacan el sitio de sus listas de sitios a explotar.

Bueno, ya tenemos nuestras táctica de defensa: evitar que ciertas peticiones, que contienen ciertos elementos en la URL que delatan su mala intención, alcancen la aplicación. Esta técnica, que se puede implementar de diferentes maneras y con diferentes utilidades se conoce como ‘URL sanitizing’ o validación de URLs. La idea es filtrar ciertas peticiones tan pronto alcanzan nuestro servidor Web y rechazarlas. En un entorno IIS contamos con varias opciones:

UrlScan 3.0 o Request Filtering: UrlScan es un filtro ISAPI que pemite restringir el tipo de URLs que nuestro servidor va a procesar. Bloqueando ciertos tipos de peticiones HTTP por URL vamos a poder para ciertos tipos de ataques que utilizan la URL como vector. UrlScan no solo aplica para los ataques de inyección de SQL por URL, sino también para inyecciones de otro tipo o inyecciones que usen cabeceras. Podéis descargar UrlScan gratuitamente, tanto para servidores de 32 como de 64 bits. Además el equipo de IIS ha publicado una configuración de UrlScan diseñada para evitar los ataques de inyección de SQL, entre muchas otras. Es importante destacar que se debe usar la versión 3.0 de UrlScan (actualmente en beta), pues versiones anteriores no analizaban lo que se pasaba en el query string, solo analizaban la URL. Se puede usar esta herramienta con IIS 5, 6 y 7, si bien es cierto que en IIS 7 la funcionalidad de UrlScan se ha incluido en un módulo llamado Request Filtering con el que podemos usar denyUrlSequence para especificar que elemento nos son permitidos en las URLs.

IIS 6 SQL Injection Sanitation ISAPI: Es un proyecto que podemos encontrar en Codeplex y que consiste en un filtro ISAPI especialmente dedicado a frenar ataques de inyección por SQL. En principio creo que la opción mas interesante es UrlScan, pero este proyecto nos proporciona el código fuente y es sin duda interesante para ante situaciones de ataques específicos saber como desarrollar una ‘antidoto’ especifico para la solución. Además este ISAPI es más simple de desplegar y configurar que UrlScan, aunque también es mucho menos flexible y potente.

Espero que estas dos utlidades os resulten útiles.

Bugleanos… o la historia de un bug que no lo es

bool Desde que apareció el primer bug de la historia, los desarrolladores los venimos sufriendo con frecuencia. Siempre que nos enfrentamos a un comportamiento anómalo, pasamos por varias fases. En una primera fase asumimos que hemos cometido un error, depuramos y le damos vueltas a asunto hasta que, varias madiciones depués, pasamos a la siguiente fase. No puede ser mi fallo, el error tiene que estar en las librerías que estoy utilizando. Y pasamos a buscar un ‘workarround’… Total no nos queda otro remedio. A menudo es más dificil conseguir que el autor de la librería corrija el bug que simplemente asumir que sea o no nuestro bug, nosotros lo estamos sufriendo y a nosotros nos compete corregirlo.


De todos modos siempre conviene recordar que ‘el printf no está roto’, máxima mencionada en el excelente The pragmatic programmer, que nos recuerda que, es más probable que el error sea debido a nuestro desconocimiento o a nuestro código que a la librería que estamos utilizando. Sobre todo si es una librería de tan amplísimo uso con el Framework de .Net.


También es cierto a que a veces ocurre que los diseñadores de la librería han tenido que tomar decisiones de diseño que contradicen lo que suponemos lógico desde nuestro puesto de vista, lo que nos puede llevar a proclamar al mundo equivocadamente que hemos encontrado un bug, uno que lleva seis años sin corregirse, uno que se podría corregir con una simple línea de código… como hace poco clamaba mi vecino de blog en Geeks.ms, Rafael Ontivero. Quizás también se deba a que nuestro ego como desarrolladores crece mucho cuando encontramos un bug en una pieza de software que sabemos que ha sido escrita por excelentes ingenieros y desarrolladores… no se puede negar que es tentador el quejarse y el darle ‘bombo’ a la situación… pero siempre conviene recordar que: ‘el printf no esta roto’… (aunque también es cierto que algunas implementaciones del runtime de C, han sufrido un printf roto).


¿Pero que es lo que llevo a Rafael a pensar que se encontraba ante un bug que hacía que PInvoke no fuese capaz de hacer correctamente el marshalling de los tipos booleanos?: Desconocer la decisión de diseño que en su día se tomo a la hora de en la implementación de P/Invoke mapear ‘booleanos’ de lenguajes nativos como C y C++ a booleanos de .Net.


Nótese que cuando hablo de ‘booleanos’ de C y C++ lo pongo entre comillas. El motivo es que en C no existe un tipo de datos booleano, por lo tanto los desarrolladores de C hemos usado un viejo truco desde hace mucho tiempo: definer BOOL o BOOLEAN como tipos booleanos. Por ejemplo cuando programamos en entornos Windows nos encontramos que en WinDef.h tenemo la siguiente definición de BOOL: typedef int BOOL; y en WinNT.h typedef BYTE BOOLEAN; el resultado final es el que tenemos dos tipos ‘booleanos’ con diferente tamaño. Esto en lo que se refiere a C, por que con la aparición de C++ la situación se embroyo aun un poquito más, puesto que C++ define un tipo boolano nativo… cuyo tamaño depende de como lo haya decidido implementar quien implementa el compilador…


Resumiendo: No hay manera humana de saber el tamaño que un tipo ‘booleano’ tendrá en el mundo nativo. Esto sin duda se convirtio en una paradoja de dificil solución para los desarrolladores que implementarón P/Invoke: ¿A cúal de todos los tipos nativos booleanos mapeamos el tipo booleano de .Net por defecto? La idea es que cuando tenemos una declaración de este estilo:

[DllImport(«dllNativa.dll»)]
extern public static bool FuncionQueDevuelveBool();

Se puede corresponder con una variedad de declaraciones nativas:

extern «C» DLLNATIVA_API bool FuncionQueDevuelveBool(void);
extern «C» DLLNATIVA_API BOOL FuncionQueDevuelveBool(void);

extern «C» DLLNATIVA_API BOOLEAN FuncionQueDevuelveBool(void);

La cuestión es que como ya hemos indicado cada uno de esos posibles tipos booleanos tiene un tamaño diferente. Pues bien cuando los desarrolladores de P/Invoke decidieron a que tipo mapear el tipo bool en las declaraciones con DllImport decidieron mapearlo a un tipo de 4 bytes (generalmente BOOL en C es un tipo de 4 bytes) como podemos ver en la MSDN. ¿Cúal es el motivo de esta decisión? Pues no tengo la certeza pero todo apunta a que el motivo es que las fuciones del API de Windows que devuelven un valor booleano lo hacen usando BOOL que como ya hemos dicho, es un typedef de int y por tanto tiene un tamaño de 4 bytes. Sin embargo el tamaño de System.Boolean es un byte y es el marshalling de tipos de PInvoke el que hace la necesaria conversión, pero siempre asumiendo esos tamaños. Si nuestra función nativa utiliza alguno de los ‘booleanos’ nativos que tienen un tamaño diferente de 4 bytes (bool o BOOLEAN son ambos de un byte), el marshalling por defecto no nos sirve.


La solución es simple. Como bien apuntaba Rafael, podemos usar el atributo MarshalAs para decorar la declaración de nuestra función .Net equivalente a la función nativa especificando así el tipo no manejado que subyace bajo el booleano nativo:

[DllImport(«dllNativa.dll»)]
[return: MarshalAs(UnmanagedType.I1)]
extern public static bool FuncionQueDevuelveBool();

En este caso por ejemplo se indica que el tipo booleano que estamos usando es de un byte (I1 == Integer de un byte).


Decir que usar FxCop hubiese librado al amigo Rafael de sufrir este desagradable ‘no bug’. FxCop incorpora una regla MarkBooleanPInvokeArgumentsWithMarshalAs que nos avisa de que lo más adecuado es especificar explicitamente el tamaño del tipo cuando hacemos marshalling de tipos booleanos en P/Invoke.


Comentar por último que lo aquí expuesto también se aplica al manejo de booleanos con COM Interop pues también se produce el proceso de marshalling.


Con esto queda aclarado el extraño caso de los ‘bugleanos’…

Presentaciones del evento sobre Metodologías ágiles y calidad del software con Team System

Ya están disponibles para descarga la presentaciones que utlizamos Pablo Alvarez Doval y un servidor en el Evento: Team System, metodologías ágiles y calidad del software. El evento fue todo un exito de público (gracias a todos los asistentes) y crítica :).


Podéis decargar las presentaciones Metodologías ágiles y Team System en el mundo real y Calidad del software con Team System.


Espero que os resulten úiles.