ASP.NET 4.0: Nueva sintaxis declarativa para evitar XSS

code_snipLos que ya tenemos una cierta edad y hemos trabajado (y mucho) con ASP Clásico estamos acostumbrados a ver la sintaxis <%= %> en las páginas Web. Este tipo de expresiones se limitan a mostrar lo que vaya dentro de ellas en el lugar indicado en la página.


Por ejemplo, si escribimos:



<%= Request.Url.ToString() %>


Obtendremos la URL de la página actual. Se puede usar cualquier tipo de expresión dentro de estas etiquetas (llamadas a funciones, condicionales, bucles…) y veremos en la página el resultado.


Este tipo de sintaxis siempre fue denostada por generar mucho código espagueti, el cual es típico de otros lenguajes como PHP. Está soportado por ASP.NET Web Forms, aunque prácticamente apenas se utiliza pues hay muchas opciones mejores.


Sin embargo vuelve a estar más de moda que nunca debido a ASP.NET MVC. En MVC se utilizan mucho en las vistas ya que permiten mostrar de manera directa y sencilla los valores de las propiedades del modelo. Y la verdad es que convierten en algo muy sencillo la generación de interfaces enlazados a datos.


Problemas de seguridad


El principal problema de este tipo de sintaxis es que muestra el resultado de la expresión que contienen las etiquetas directamente en el HTML de la página y sin codificar.


Por ello, si las usamos para mostrar contenidos generados por los usuarios (introducidos previamente, por ejemplo, en un formulario), podemos obtener código HTML + JavaScript malicioso que nos puede generar vulnerabilidades de Cross-Site-Scripting (XSS).


La solución más sencilla tradicionalmente ha pasado por codificar como HTML el contenido a mostrar antes de insertarlo dentro del HTML de la página, así:



<%= HttpUtility.HtmlEncode(«<script>alert(‘hola’);</script>») %>


Al aplicar el método HtmlEncode a la cadena anterior obtenemos en la página la misma cadena pero codificada como caracteres HTML (es decir, por ejemplo, el «<» se transforma en un «&lt;», el «>» en un «&gt;», etc…). De esta manera lo que obtenemos es una cadena de texto inocua insertada dentro de la página y visible dentro de ésta, que no tendrá efecto alguno sobre el comportamiento de la misma. Si no hubiésemos tenido la precaución de haber codificado la cadena dentro de la expresión lo que hubiésemos obtenido es una bonita ventana de advertencia saludándonos, ya que el texto del script formaría parte natural del a página y sería interpretado por el navegador.


La nueva sintaxis en ASP.NET 4.0


En ASP.NET 4.0 se introduce una nueva forma de conseguir lo anterior que consiste en utilizar esta sintaxis alternativa:



<%: %>


Es decir, se utiliza el símbolo de dos puntos en lugar del igual.


Esta expresión tiene la ventaja de que todo el contenido que se insertará en la página se codificará como HTML automáticamente antes de ser insertado. Así, por ejemplo, si tenemos un formulario con un campo «Comentario», y el usuario incluye un Script o algún código malicioso dentro de él, escribiendo (en C#) lo siguiente:



<%: Request[«Comentario»] %>


nos aseguraremos de que la entrada del usuario es inofensiva.


¿Y  qué pasa si quiero que no estén codificadas?


Bueno, siempre nos queda la sintaxis tradicional, pero aún así se nos proporciona una forma de conseguirlo usando la nueva sintaxis también. Se trata de devolver las cadenas de texto finales dentro de una clase HtmlString. Por ejemplo así:



<%: new HtmlString(Request[«Comentario»]) %>


Esta clase indica que la cadena que contiene no debe ser codificada como HTML, pues ya es HTML o una cadena codificada como tal, por lo que obtendremos tal cual el contenido de la cadena sin modificar.


En resumen


Es recomendable que utilicemos esta sintaxis en lugar de la anterior, heredada de ASP 3.0 clásico), sobre todo los programadores de ASP.NET MVC 2. Además es muy fácil adaptar vistas existentes puesto que basta con hacer una búsqueda y sustitución de «<%=»  por «<%:» para tener todas las vistas actualizadas.


No te preocupes si realizas el cambio y ya te preocupabas de codificar como HTML algunos campos antes de insertarlos: la etiqueta está preparada para reconocer que una cadena ya se encuentra codificada y no volver a codificarla por segunda vez, lo cual podría ser desastroso.


¡Espero que te sea útil!

Creación de manejadores de peticiones asíncronos: El contador de Meneame.net

logo_menameMeneame.net es una Web recopiladora de enlaces en la que los usuarios publican enlaces que creen de interés, y el resto de los usuarios votan o critican en función de lo sus intereses. La teoría es que, de este modo, los enlaces más interesantes subirán hacia las primeras posiciones de su categoría en virtud de este proceso de «crowdsourcing». La práctica es que no siempre es así (prueba a posicionar un enlace técnico, por ejemplo). Pero no obstante la web es muy interesante para encontrar enlaces y noticias de interés general dentro de temáticas más o menos prosaicas. A cada voto que recibe una URL se le denomina «meneo».


El caso es que, al menos oficialmente, no existe ningún botón de información sobre cuántos «meneos» tiene una determinada URL, al estilo de los que tiene Facebook o Twitter. Los únicos desarrollos que integran este botón para poder poner dicha información en tu blog o web pertenecen a sitios de valoración social, estilo ShareIt y compañía, por lo que si quieres tener un botón de meneame en tu Web tendrías que instalar uno de estos plugins.


Recientemente uno de los posts en mi otro blog no-técnico fue meneado por alguien allí y recibí una cantidad de tráfico bestial, lo cual llamó mi atención sobre este sitio y  me pregunté si existiría algún tipo de botón de este estilo. Al no encontrarlo busqué también a ver si existía algún tipo de API que permitiera averiguar esta información, pero oficialmente tampoco la tienen. Sin embargo caí en este antiguo post del fundador fundador del sitio, Ricardo Galli, que aunque tiene más de 4 años y el blog está abandonado resulta que todavía sirve. Si bien la función, como puedes observar es muy simple, resulta muy sencilla de usar.


Así que me pareció un ejercicio interesante escribir un manejador para ASP.NET al que le pudieras pasar cualquier URL y te devolviera un gráfico con la información sobre los meneos que tiene en Meneame.net, algo así:


BotonMeneame_Ej


Es un ejercicio interesante porque entre otras cosas el manejador no puede estar hecho de cualquier manera ya que, si quieres hacerlo de manera profesional, debería de permitir:



1.- Ser asíncrono para no ocupar hilos de IIS cuando lo llamas de las página principal de un blog que tiene muchos botones como este. La razón principal es que, además, la llamada a la API de Meneame para obtener la información puede ser lenta o incluso no responder si el servidor está caído o tiene problemas de conectividad, por lo que es más importante todavía que el uso del botón no te pueda llegar a mermar la escalabilidad de tu propio servidor. Por ello lo he implementado como un IHttpAsyncHandler.


2.- Hacer caché de los resultados para cada URL. En páginas con muchas visitas podría afectar negativamente al rendimiento de Meneame el estar llamando a la API  continuamente, por lo que a este manejador le he incorporado también caché de los resultados de manera que el número de meneos de cada URL individual se almacena en caché durante un minuto. De este modo durante un minuto el botón siempre devuelve el mismo valor para una URL dada, siendo muy rápido y además evitando que se sobrecarguen los servidores de Meneame.


3.- Seguridad de acceso. Si hubiera hecho el manejador de cualquier manera, al colocarlo en tu dominio cualquiera podría hacer uso de él para generar su propio botón de Meneame, lo cual podría llevar a consumir muchos recursos en tu servidor y afectar a lo que tengas albergado en él. Por ello he creado un pequeño sistema que restringe el uso del botón a los dominios que tú decidas. Existe la posibilidad de restringirlo sólo al dominio actual en el que está albergado (opción por defecto), especificar una lista de dominios y subdominios a los que permitir el acceso o bien dejarlo abierto para que cualquiera lo pueda usar (opción no recomendada). Basta tocar una constante al principio del código para cambiar este comportamiento.


4.- Fácil de adaptar y personalizar sin que sea necesario recompilar nada. Con sólo tocar el código en el servidor, automáticamente tienes un comportamiento diferente para el botón. Es posible modificar el gráfico que se genera, el tipo de letra, su tamaño, su posición y su color. Así, si quieres cambiar el gráfico generado para hacer, por ejemplo, uno más grande y con los números debajo, lo único que tienes que hacer es cambiar el archivo meneame.png que acompaña al manejador poniendo el gráfico que tú quieras. Luego, en el .ASHX, cambias con el bloc de notas o cualquier otro editor unas cuantas constantes que están al principio del código y, ¡Listo!, tienes un botón completamente diferente.


Como ves tiene bastantes más cosas de las que pudiera parecer a simple vista y estudiar el código te puede resultar interesante para aprender. Lo he dejado completamente comentado y explicado, por lo que nadie con conocimientos básicos de C# y ASP.NET debería tener problema para seguirlo.


Como utilizar este manejador para añadirlo a tu página o blog


Descárgate el manejador desde este ZIP (5,25 KB). Descomprímelo en cualquier carpeta de tu servidor en la que tengas ya una aplicación ASP.NET funcionando (tu blog o portal).


El ZIP contiene 3 archivos:



· meneame.png: Es el gráfico de base utilizado para generar el contador. Si quieres puedes cambiarlo por cualquier otro, pero tendrás que cambiar entonces las constantes del código que controlan el tamaño, tipo de letra y posicionamiento del texto generado sobre él.


· MeneameHandler.ashx: este es el manejador en cuestión, y el que se encarga de generar el gráfico para cada URL. Se le debe pasar la dirección a comprobar en un parámetro llamado»url», por ejemplo así:


    MeneameHandler.ashx?URL=http://frikipedia.isdifferent.org/


· default.htm: es un simple archivo de pruebas para poder verificar que el manejador funciona bien. Genera tres botones de ejemplo y nos permite comprobar que todo está correcto. Lo puedes eliminar si quieres. Sólo son necesarios los dos anteriores.


Una vez copiado y habiendo comprobado que todo está correcto, para poder colocar un botón de Meneame en tu web lo único que tienes que hacer es llamar al .ashx anterior y pasarle la URL de cada post o página que quieras comprobar. Además la deberías rodear de un enlace que permita a los usuarios pulsar en el botón para votar por el contenido en Meneame. En una página ASPX normal podrías escribir simplemente esto:



<a target=_blank href=»http://www.meneame.net/submit.php?url=<%= Request.Url.ToString() %>» ><img border=0 src=»ContadorMeneame/MeneameHandler.ashx?URL=<%= Request.Url.ToString() %>« alt=»Meneame!» /></a>


De este modo se colocará la URL a la página actual como argumento tanto del enlace como del botón contador.


OJO: si esto se quiere usar con cada post de un blog no valdría el código anterior en rojo para obtener la URL ya que, por ejemplo, en la página principal del blog mostraría la misma URL para todos los botones. En ese caso habría que obtener la URL actual del post usando la API concreta que utilice el blog. Por ejemplo en el sistema de blogs DasBlog la expresión correcta sería <%permalink%>. En el caso de BlogEngine.net la expresión correcta sería: <%=Post.AbsoluteLink.ToString() %>. En ambos casos habría que tocar la plantilla correspondiente del tema actual del blog. En otros blogs será de forma diferente.


Por supuesto es posible colocar el manejador en cualquier otro dominio y hacer uso de él desde otros sitios distintos. Como he comentado, además, permite restringir los dominios que tendrán derecho a usarlo, así que es interesante incluso para compartir código si tenemos varios sitios web o blogs en los que utilizarlo.


Cómo incorporarlo a BlogEngine.NET


BlogEngine.net es uno de los sistemas de blogging más potentes para .NET. para mi la única carencia grave que tiene es que no permite tener más de un blog al mismo tiempo, pero por lo demás es casi perfecto. Y digo casi porque precisamente una de las cosas que no me gustan nada es el sistema de reescritura de URLs que trae incorporado. Está escrito de manera bastante chapucera y, por ejemplo, cuando detecta cualquier URL que lleva la cadena «.aspx» la trata como si fuera un post o página propios y reescribe la URL para redirigir hasta ella.


El efecto práctico de esto es que si ponemos el botón anterior en un blog creado con BlogEngine.net no funcionará porque cada vez que llamemos al manejador con la URL de un post, como lleva .aspx lo detectará y en lugar de devolver el gráfico nos redirigirá al post en cuestión 🙁


Para solucionarlo tenemos dos opciones fundamentales:



1.- Tocar el código fuente de BlogEngine.net y cambiar el módulo de redirección (ubicado en BlogEngine.CoreWebHttpModulesUrlRewrite.cs). La verdad es que es realmente fácil cambiar el código para que funcione como es debido, pero tiene la pega de que tenemos que volver a desplegar la .DLL resultante en el servidor. Los de BlogEngine.net suelen sacar la última versión sin código fuente (es decir, está disponible el código fuente de la revisión inmediatamente anterior a la última) por lo que si estamos usando la última no nos valdrá de nada recompilar pues no funcionará. Siempre podemos usar la penúltima sin problemas, en cuyo caso sí que es válida esta solución.


2.- Colgar el botón en otro dominio cualquiera bajo nuestro control y usarlo desde allí en el blog. Cambiamos la constante de dominios permitidos para protegerlo y listo. Esto es lo más fácil y directo, pero tendremos que tener otro lugar en dónde colgarlo.


En resumen


En el código que puedes descargar tienes un botón contador de meneos totalmente funcional. Aunque no te interesa usar este botón en tu sitio se trata de un código muy interesante para aprender a crear manejadores asíncronos con ASP.NET.


¡Espero que te resulte útil!

Solución al mensaje "Error genérico de GDI+" en aplicaciones Web que generan gráficos

Este fin de semana he estado trabajando en una pequeña aplicación que en breve colgaré con código fuente para todo el mundo y que me dio el error que os comento en el título del post.


Aunque todo lo que utilicé era compatible con .NET 2.0, la desarrollé en mi equipo con Visual Studio 2010 y .NET 4.0, donde todo funcionaba a la perfección. Al subirla al servidor donde iba a estar albergada, de repente, me daba el error «Error genérico de GDI+» o -en inglés- «A generic error occurred in GDI+», sin más explicaciones, y con unas referencias muy raras a Remoting.


Mi código original generaba una imagen que posteriormente se devolvía al navegador en formato PNG. El código que estaba utilizando era similar al siguiente:


Bitmap img = new Bitmap(sRutaImagenPatron);
Graphics g = Graphics.FromImage(img);
Font f = new Font(fuente, tamanio, FontStyle.Bold);
Brush b = colorLetra;
g.DrawString(string.Format(«{0:n0}», iDato), f, b, posX_Letra, posY_Letra);


context.Response.ContentType = «image/png»;
img.Save(context.Response.OutputStream, ImageFormat.Png);


Las primeras líneas, antes de la que está en negrita al final, se encargan de generar el gráfico sobreponiendo un texto a partir de un gráfico inicial que tengo en disco. La línea importante es la última, que se encarga de guardar el gráfico resultante al flujo de salida de la petición actual, de modo que lo reciba el usuario en su navegador.


El motivo de que se produzca este error es que en las versiones anteriores de .NET el Stream de respuesta de ASP.NET no permite moverse adelante y atrás por él, es decir, lo que escribes ese añade al final y nada más. El caso es que el formato PNG para poder escribirse correctamente necesita moverse a lo largo del stream, y por eso rompe el código anterior al intentar escribir directamente en la salida de la respuesta actual (Response).


La solución que funciona siempre: generar el gráfico en un stream en memoria que siempre permiten el movimiento en todas direcciones, y luego enviar el resultado de una vez al Response. En código C# esto es así:


using (MemoryStream stream = new MemoryStream())
{
    img.Save(stream, ImageFormat.Png);
    stream.WriteTo(context.Response.OutputStream);
}


Si sustituimos la última línea anterior con este fragmento obtendremos el mismo resultado (la imagen enviada al cliente) pero sin que se produzca el error anterior, ya que el stream en memoria se puede mover adelante y atrás sin problema.


¡Espero que te resulte útil!

La manera correcta de actualizar contadores de rendimiento personalizados

fuel-gaugeEsta es una pregunta interesante que ha surgido en el curso de fundamentos de la plataforma .NET que tutelo on-line en campusMVP. Se trata de una pregunta sencilla pero con una sutileza interesante respecto a la creación de contadores de rendimiento para Windows desde .NET.

Cuando creamos un contador personalizado en .NET incrementamos o disminuimos su valor para actualizar la medición que queremos reflejar en el contador de rendimiento del sistema. Algunos ejemplos de contadores que podemos crear son: uno que indique el número de usuarios actualmente autenticados en nuestra aplicación Web, uno que indique el número de compras realizadas en una tienda on-line, el promedio de consultas lanzadas contra un almacén de datos, etc, etc…

Tienen mucha utilidad ya que nos permiten monitorizar con las herramientas propias de Windows el desempeño de nuestras aplicaciones, tanto en tiempo real como haciendo trazas para un análisis posterior.

El caso es que todos ellos implican generalmente el incremento y decremento de un valor almacenado en el contador.

Tenemos dos formas de actualizar el valor contenido en un contador:

  • Usando la propiedad RawValue del mismo, que contiene dicho valor y podemos leer y escribir.
  • Aumentando o disminuyendo su valor mediante los métodos Increment, Decrement o IncrementBy.

La pregunta es ¿Qué diferencia hay entre usar estos métodos o directamente el valor? Es más, ¿para qué tener esos métodos si podemos acceder al valor directamente?

RawValue accede directamente al valor del contador. Lo puedes usar para leer o escribir el valor en cualquier momento, aunque se suele usar para inicializarlo únicamente.

Si utilizas Increment, Decrement y demás métodos te estás asegurando de que te va a funcionar bien en escenarios con múltiples hilos accediendo al contador, mientras que si usas directamente RawValue para escribir el valor esto no es así.

Es decir, si escribes:

contador.Increment();

te aseguras de que aunque varios programas a la vez (o varias instancias de tu programa) incrementan el contador, el incremento se hace correctamente (es Thread-safe).

Sin embargo,si hubieras hecho esto:

contador.RawValue++;

podrías tener problemas si hay concurrencia, y los valores no serían correctos.

Esto es especialmente importante tenerlo en cuenta si vas a estar utilizando contadores personalizados en una aplicación Web, en la que puede haber gran simultaneidad en las actualizaciones del contador.

Por otro lado, si estamos seguros de que no va a haber concurrencia, usar RawValue es hasta 5 veces más rápido que usar los métodos.

¡Espero que te sea útil!