Disponible ASP.NET MVC 4 Roadmap

ASP.NET MVC

ASP.NET MVC

En el día de hoy me he encontrado con una gran noticia, y es que están por comenzar a trabajar en una nueva versión de ASP.NET MVC.

Ya podemos acceder al documento con la planificación del trabajo de ASP.NET MVC 4, el cual no es definitivo, pero nos da pautas de las nuevas características que va a ofrecer esta versión.

Uno de los objetivos es generar una de las mejores plataformas de desarrollo de aplicaciones web modernas (rich web apps) y multi-plataforma (ya veremos que varias de las características estan relacionadas a los dispositivos mobiles o tablets, como también a HTML 5).

Algunas de las características que ofrecería son:

  • Recipes (Extensible Task-Based Tooling): en ASP.NET MVC 4 un Recipe es básicamente una caja de dialogo entregada vía Nuget para implementar ciertas carateristicas automaticamente, como por ejemplo: Ajax grid, autentificación mediante OAuth o claims utilizando Windows Identity Framework (WIF) entre otros. La idea es que uno también pueda escribir sus propios Recipe y reutilizarlos en otras aplicaciones.
  • Mobile Support: en los nuevos proyectos web tendremos plantillas CSS optimizadas para la visualización de nuestro sitio en dispositivos móbiles y tablets. También podremos crear “Mobile Applications” las cuales trabajaran con jQueryMobile para aplicaciones que estan orientadas a dispositivos mobiles unicamente.
  • Razor Helpers Support: la idea es continuar utilizando el viewengine Razor y mejorar la forma de escribir Helpers para las web pages.

Pueden ver en detalle estas característicamente y muchas otras más desde aquí.

Anuncios

Evitando JavaScript Injection en ASP.NET MVC

Hace unos días revisando un informe de sobre seguridad web, un ítem me llamo la atención porque es una de esas cosas que a uno se olvida de tenerlas en cuenta al momento de desarrollar un sitio. El mismo hablaba sobre los ataques de inyección de JavaScript.

Este tipo de ataque se denomina Cross-site scripting o de manera abreviada XSS:

XSS, del inglés Cross-site scripting es un tipo de inseguridad informática o agujero de seguridad basado en la explotación de vulnerabilidades del sistema de validación de HTML incrustado.

La idea de este post es ver de que forma podemos prevenir este tipo de ataques en aplicaciones ASP.NET MVC partiendo desde dos ópticas diferentes.

Antes que nada vamos a ver un poco mas en profundidad de que se trata JavaScript Injection y como se llevan a cabo este tipo de ataques. Para darnos una mejor idea supongamos que desde nuestro sitio web tenemos una caja de texto en la cual un usuario carga contenido y luego el mismo se visualiza en la página. Esta situación podría estar dejando abierta la posibilidad de un ataque de inyección de Javascript. Cómo es posible esto?… vamos a verlo con un simple ejemplo.

Lo primero sera crear una aplicación web tipo Twitter pero muy simplificada, en la cual vamos a permitir este tipo de ataques. Vamos a crear un controlador al cual vamos a llamar TweetController y a definir la siguiente entidad que formará parte del modelo de nuestra app y que se llamaremos Tweet:

1: public class Tweet
2: {
3:     public int TweetID { get ; set ; }
4:
5:    public string Usuario { get ; set ; }
6:
7:     public string Mensaje { get ; set ; }
8: }

Al momento de codificar la vista, la visualización de los items estará armada de la forma estandar:

1: <div class="tweetSection">
2:  <% foreach (var item in Model) {  %> 
3:     <span class="tweetUser">  <%= item.Usuario %></span>
4:    <br />
5:      <%= item.Mensaje  %> 
6:     <br />
7:     <br />
8:  <%   }  %>
9: </div>

Básicamente nuestra app esta conformada por un formulario donde se ingresa un nombre de usuario y un mensaje, el cual al momento de hacer el submit se grabara en una DB (para esto utilizaremos la librería EF) y luego se visualizara en la misma pantalla:

Interfaz de la aplicación

Interfaz de la aplicación

De la forma en que “dibujamos” el formulario, hemos dejado desprotegido nuestro sitio a los ataques de este tipo. Imaginemos que el usuario escribe un simple script de Javascript en nuestra caja de texto, por ejemplo, la ejecución de un mensaje de alerta informándonos que hemos sido atacados:

Cargando un script JS en el formulario

Cargando un script JS en el formulario

Una vez que “tweeteamos” nuestro contenido y volvemos a cargar la vista (que incluye la visualización del contenido de cada uno de los tweets) se estará ejecutando nuestro script:

Ataque de Javascript Injection

Ataque de Javascript Injection

Uno puede pensar que este tipo de ataques son inofensivos, sin embargo un hacker podría utilizar la inyección de JavaScript para realizar un ataque Cross-Site Scripting (XSS) robando información confidencial del usuario y enviando la misma a otro sitio web (dos ejemplos clásicos serían robar información de las cookies del navegador del usuario o información que se carga en un formulario que previamente a sido victima de Javascript Injection).

Cómo podemos evitar este ataque? Tenemos dos alternativas, la primera es utilizar el helper HTML.Encode el cual se encargara de renderizar el contenido de forma tal que no se ejecuten scripts que alguien pudo ingresar:

1: <div class="tweetSection">
2:  <% foreach (var item in Model) {  %> 
3:     <span class="tweetUser">  <%= item.Usuario %></span>
4:     <br />
5:      <%= Html.Encode(item.Mensaje)  %> 
6:     <br />
7:     <br />
8:  <%   }  %>

Ejecutamos y vemos que ya no se ejecuta nuestro script, ya que todo contenido reconocido como HTML a sido codificado de forma tal que se pueda visualizar como texto:

Utilizando el Helper Html.Encode

Utilizando el Helper Html.Encode

La segunda alternativa es codificar el contenido antes de grabarlo en la base de datos. Para esto podemos hacer uso del método Server.HtmlEncode que nos provee nuestro controlador:

1:             if (ModelState.IsValid)
2:             {
3:                 tweet.Mensaje = Server.HtmlEncode(tweet.Mensaje);
4:                 datos.Tweets.Add(tweet);
5:                 datos.SaveChanges();
6:             }

Utilizando este esquema ya no sería necesario utilizar el helper Html.Encode para visualizar el contenido (aunque no esta demás dejarlo). La desventaja de este enfoque es que los datos que se graban en la base de datos están codificados, lo cual no es del todo prolijo sobre todo si esta información se necesita visualizar en otro tipo de plataformas que no sean web. Observemos a continuación como se guardan los datos sin codificar (registro 2) y codificandolos (registro 3):

Registros de la base de datos

Registros de la base de datos

Para finalizar quería comentarles que utilizando el ViewEngine Razor los datos son “encodeados” automaticamente, sin necesidad de utilizar el helper Html.Encode y previniendonos de este tipo de ataques de entrada.  🙂

Quienes quieren el proyecto del ejemplo pueden descargarlo desde aquí: Projecto MvcJavascriptInjection

ASP.NET MVC 3: nuevo view engine RAZOR

Junto con la nueva versión del framework ASP.NET MVC, se liberó la primera versión de un nuevo view engine llamado Razor y que promete ser muy interesante!

Vayamos directamente al código para entender mejor el tema. Lo primero que debemos hacer es al momento de crear una nueva aplicación web ASP.NET MVC 3, es seleccionar como tipo de view engine a utilizar el nuevo Razor y no al tradicional ASP.NET (ASPX).

Seleccionando el view engine

Seleccionando el view engine

Ahora vamos a crear dos vistas iguales que simplemente muestran una lista de usuarios. La primer vista la haremos con el view engine tradicional de ASP.NET:

<table>
  <% foreach (var item in Model) { %>
  <tr>
    <td><%: item.Id %></td>
    <td><%: item.Name %></td>
  </tr>
  <% } %>
</table>

Como podemos ver nuestras sintaxis de apertura para escribir código es bastante molesta. Pero con Razor nuestro código queda mucho más prolijo gracias a que nuestra sintaxis de apertura es solamente el símbolo @:

<table>
  @foreach (var item in Model) {
  <tr>
    <td>@item.Id</td>
    <td>@item.Name</td>
  </tr>
  }
</table>

Esto nueva sintaxis nos permite generar vistas muchos más limpias y fáciles de leer. Simplemente agregando la @ al iniciar nuestros bloques de código ya es suficiente. Como verán al iniciar el bloque foreach no es necesario indicar el cierre del mismo nuevamente con la @, con solamente agregar la llave de cierre, Razor identifica el final del bloque.

Otra punto interesante es la forma en que definimos nuestras MasterPage. La definición de una MP con Razor sería más o menos de la siguiente manera:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>@View.Title</title>
</head>
<body>
  <div>
    @RenderBody()
  </div>
</body>
</html>

Como podemos observar, el contenido de las vistas que utilicen esta plantilla será reemplazado donde se encuentra el método RenderBody() (mucho más prolijo que los content de ASP.NET, no?). Una vista que utiliza una MP debería hacerlo de la siguiente manera:

@model IEnumerable<MvcTres.Controllers.User>
@{
  View.Title = "Index Usuarios";
  Layout = "~/Views/Shared/_LayoutPage1.cshtml";
}
<table>
@foreach (var item in Model) {
  <tr>
    <td>@item.Id</td>
    <td>@item.Name</td>
  </tr>
}
</table>

Simplemente se crea un bloque donde especificamos cual será la plantilla que vamos a utilizar asignandosela a la propiedad Layout. Además podemos agregar distintas secciones de HTML a nuestras vistas utilizando el método RenderSection(…).

Otra característica interesante es que las páginas no tienen más la extensión aspx, sino que son cshtml o vbhtml, dependiendo del lenguaje seleccionado.

Entre las ventajas encontradas podemos nombrar:

– Reduce al máximo la cantidad de caracteres a escribir en nuestras vistas, lo que permite un código más limpio y simple de leer.
– Es fácil de aprender, ya que permite trabajar con HTML y C# al igual que el motor de ASP.NET.
–  Integra código y HTML como un todo.
– Soporta bloques multi-lineas.

Dos desventajas que note es que por ahora esta versión del view engine no soporta la vista HTML en Visual Studio y tampoco soporta el intellisense (aunque ya prometieron que sí para las próximas versiones!).

Para más info podemos visitar la siguiente entrada del blog de ScottGu’s que contiene muchísima info sobre este motor.

Update: Directiva @model

Razor provee también una nueva directiva llamada @model que nos permite hacer referencia a los modelos de una vista de una forma más limpia y concisa.

Veamos un ejemplo simple: con la directiva @inherits de ASP.NET MVC 3 Previews la forma de hacer la referencia con el modelo de la vista era la siguiente:

@inherits System.Web.Mvc.WebViewPage<IList<Sample.Models.User>>

Pero con la nueva directiva @model podemos definirlo de la siguiente manera:

@model IList<Sample.Model.User>

La sintaxis anterior es conceptualmente igual que antes, sin embargo es muchísimo más fácil de leer y escribir.