Cómo prevenir vulnerabilidad decubierta en ASP.NET‏?

Update: ya está disponible el parche lanzado por la gente de Microsoft que soluciona este problema. Descargar de aquí.

Debido a la vulnerabilidad descubierta en estos días para todos los sitios desarrollados bajo ASP.NET (en todas sus versiones), adjunto una serie de recomendaciones que dió Scott Guthrie para prevenirse de posibles ataques.

Los pasos a seguir son:

– Si estamos utilizando ASP.NET 1.0, 1.1, 2.0 o 3.5 entonces deberemos crear u actualizar en el archivo web.config la sección <customErrors> y de esta se redireccionaran todos los errores a una única página. Para esto debemos modificar o agregar la siguiente sección en nuestro archivo de configuración:

Configuración web.config

Configuración web.config

– Si estamos trabajando con la versión ASP.NET 3.5 SP1 o 4.0 deberemos configurar nuestro web.config de la siguiente manera:

Configuración web.config

Configuración web.config

En ambos casos se da por supuesto que deberemos tener creada nuestra página de error.

– Finalmente en el evento Page_Load() (para sitios WebForm) o en la acción del controlador (para sitios MVC) de la página de error deberíamos agregar un pequeño retraso de tiempo aleatorio (esto permite “confundir” aún más sobre los errores ocurridos):

Configurando retraso de carga

Configurando retraso de carga

Nota: el método RandomDelay() del ejemplo MVC debería hacer algo similar a lo que ocurre dentro del método Page_Load() del ejemplo de WebForm.

Como podemos ver además no tenemos secciones <error> dentro del elemento <customerrors>, esto nos permite ocultar la información del porqué se produjo el error al atacante.

Para ver en detalle el problema podemos ingresar aquí. Dentro del link encontraremos para descargar un pequeña aplicación para nuestros servidores web que se encarga de encontrar aquellas aplicaciones que tienen deshabilitada la sección customerrors o en caso de que estén habilitadas tienen definidos errores personalizados.

Fluent Interface en C#

Para quienes no conocen acerca de Fluent Interface les recomiendo este gran artículo escrito por los responsables de este estilo de programación: Eric Evans y Martin Fowler.

Básicamente la idea de esto es permitir escribir código de una manera más fluida y más comprensible de leer.

Para entender este concepto vayamos directamente al código. Supongamos que tenemos definida una clase que para representar e-mails:

public class Email
{
    public SmtpClient Client { get; set; }
    public string From { get; set; }
    public string To { get; set; }
    public string Subject { get; set; }
    public string Body { get; set; }

    public void Send()
    {
        // Enviar correo...
    }
}

Para crear una nueva instancia de Email lo que generalmente haríamos es lo siguiente:

SmtpClient client = new SmtpClient("host", 1);

Email email = new Email();
email.Client = client;
email.From = "from@sebys.com.ar";
email.To = "to@sebys.com.ar";
email.Subject = "Envio email";
email.Body = "Este es el contenido del e-mail";

email.Send();

Ahora bien, los que nos ofrece esta nueva técnica es poder inicializar un e-mail de la siguiente forma:

SmtpClient client = new SmtpClient("host", 1);

IEmail fluentEmail = new IEmail()
                         .Client(client)
                         .From("from@sebys.com.ar")
                         .To("to@sebys.com.ar")
                         .Subject("Envio email")
                         .Body("Este es el contenido del e-mail")
                         .Send();

Lo que hicimos acá es exponer todo el comportamiento que realmente nos interesa de la clase Email dentro de la clase IEmail. Para esto lo primero que debemos hacer es crear esta nueva clase y definir una propiedad privada del tipo Email y luego encapsular todo el comportamiento deseado:

public class IEmail
{
    private Email _email;

    public IEmail()
    {
        this.IEmail();
    }

    public IEmail IEmail()
    {
        this._email = new Email();
        return this;
    }

    public IEmail Client(SmtpClient client)
    {
        this._email.Client = client;
        return this;
    }

    public IEmail From(string from)
    {
        this._email.From = from;
        return this;
    }

    public IEmail To(string to)
    {
        this._email.To = to;
        return this;
    }

    public IEmail Subject(string subject)
    {
        this._email.Subject = subject;
        return this;
    }

    public IEmail Body(string body)
    {
        this._email.Body = body;
        return this;
    }

    public IEmail Send()
    {
        this._email.Send();
        return this;
    }
}

El secreto está en que cada uno de los métodos devuelve una instancia del objeto creado, por lo tanto podemos ir invocando nuevos métodos sin necesidad de hacer una nueva línea.

Esta es una forma de utilizar Fluent Interface, otra es hacerlo directamente en la clase EMail, también podemos crear una interfaz con los métodos que nos interesan de Email y las clases que implementen dicha interfaz sean nuestras “Fluent Interface“.