Tip: Detectar el estado de la red con .NET

Detectar el estado de la red con .NET usando la clase System.Net.NetworkInformation.NetworkChange

Una forma sencilla de detectar el estado de las interfaces de red:

csharp:
using System;
using System.Net.NetworkInformation;

namespace Examples.Net.AddressChanges
{
    public class NetworkingExample
    {
        public static void Main()
        {
            NetworkChange.NetworkAddressChanged += new
                NetworkAddressChangedEventHandler(AddressChangedCallback);
            NetworkChange.NetworkAvailabilityChanged += new
                NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged);
            Console.ReadLine();
        }

        static void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
        {
            Console.WriteLine(e.IsAvailable);
        }
        static void AddressChangedCallback(object sender, EventArgs e)
        {
            NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface adapter in adapters)
            {
                Console.WriteLine("   {0} is {1}", adapter.Name, adapter.OperationalStatus);
            }
        }
    }
}

Tomé el ejemplo de la documentación por si algún día necesito hacer algo parecido. 😀

Edición #12 de Architechture Journal

Edición número 12 de Architechture Journal, esta edición trae artículos sobre Web2.0, Cross-Domain Communication, Software Delivery Platforms, ADO.NET Entity Framework, etc.

Para los interesados, ya está disponible la edición número 12 (EN) de esta interesante revista denominada The Architecture Journal. Los temas para este número son:

  • Web 2.0 in the Enterprise
  • Eficient Software Delivery through Service Delivery Platforms
  • Secure Cross-Domain Communication in the Browser
  • An Application-Oriented Model for Relational Data
  • Architechture Journal Profile: Pat Helland
  • Data Confidence Over the Web
  • Managed Add-Ins: Advanced Versioning and Reliable Hosting

El artículo "Secure Cross-Domain Communication in the Browser" es una lectura interesante para desarrollares web, porque muestra una alternativa para saltar las restricciones de seguridad impuestas por los navegadores (cross-domain policy) y realizar la comunicación en 2 vías entre diferentes dominios usando elementos iframe. En el artículo se afirma que este método es seguro, sin embargo tengo dudas acerca de esa afirmación :).

Si desean los contenidos de esta revista en español, al parecer van a tener que esperar un poco más porque la última traducción disponible es de la edición #11.

Proteger la descarga de archivos en ASP.NET 2

Protección de la descarga de archivos en ASP.NET 2, usando una página intermedia que se encarga de validar al usuario y entregar los contenidos.

En la anterior entrega (Protección de archivos con ASP.NET 2 y IIS 6), vimos que a partir de IIS 6, es posible proteger archivos que no son procesados directamente por ASP.NET; si bien es cierto que este método es fácil de implementar, tiene el inconveniente que en hostings compartidos es difícil o imposible hacer eso ya que generalmente no se tiene acceso a la configuración de IIS.

Otra forma de proteger la descarga de archivos de usuarios anónimos, es crear una página intermedia que antes de entregar los contenidos de éstos, realice las validaciones pertinentes al usuario que hace la petición. Para evitar que los usuarios descarguen directamente los recursos protegidos (por si conocen la ruta) es mejor que éstos estén ubicados en lugares no accesibles directamente desde el navegador (Ejemplo: App_Data o el directorio padre de la aplicación).

El siguiente ejemplo, ilustra de manera básica como proteger los archivos que están ubicados en App_Data\Protected:.

asp:
<%@ Page AutoEventWireup="true" CodeFile="Default.aspx.cs" EnableViewState="false"
    Inherits="_Default" Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Download</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="messageLabel" runat="server"></asp:Label>
        <asp:Repeater ID="filesRepeater" runat="server">
            <HeaderTemplate>
                <ul>
            </HeaderTemplate>
            <ItemTemplate>
                    <li><a href='?file=<%# HttpUtility.UrlEncode(Container.DataItem.ToString()) %>'><%# Container.DataItem %></a></li>
            </ItemTemplate>
            <FooterTemplate>
                </ul>
            </FooterTemplate>
        </asp:Repeater>
    </div>
    </form>
</body>
</html>
csharp:
using System;
using System.IO;
using System.Web;

public partial class _Default : System.Web.UI.Page
{
    readonly static string basePath = HttpContext.Current.Server.MapPath("~/App_Data/Protected");

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!string.IsNullOrEmpty(Request.Params["file"]))
        {
            DownloadFile(Request.Params["file"]);
        }
        LoadFiles();
    }
    void LoadFiles()
    {
        string[] files = Directory.GetFiles(basePath);
        for (int i = 0; i < files.Length; i++)
        {
            files[i] = Path.GetFileName(files[i]);
        }
        filesRepeater.DataSource = files;
        filesRepeater.DataBind();
    }
    void DownloadFile(string file)
    {
        /*
         * Usar autenticación de formularios sobre esta página
         * o realizar algún otro proceso de validación del usuario
         */


        file = Request.MapPath(file, "~/App_Data/Protected", false);

        // Sólo descargar si el archivo está dentro de App_Data/Protected
        if (!file.StartsWith(basePath) || !File.Exists(file))
        {
            messageLabel.Text = "El archivo no existe";
            return;
        }
        Response.Clear();       
        Response.ContentType = "application/octet-stream";
        Response.AppendHeader("Content-Disposition", "attachment; filename=" + Path.GetFileName(file));
        Response.TransmitFile(file);
        Response.End();
    }
}

Al implementar este tipo de cosas, hay que validar bien el archivo a descargar, puesto que por un descuido, podemos hacer que el código de nuestra aplicación esté disponible a todo el mundo. 🙂

Cecil: Examina y modifica ensamblados .NET al vuelo

Uso de Mono Cecil para la modificación (agregar, modificar y quitar código) de ensamblados .NET.

Cecil es una librería creada por Jean-Baptiste Evain que permite examinar y modificar los ensamblados .NET de manera sencilla, a su vez estos cambios pueden sobreescribir el original o ser almacenados en un ensamblado nuevo.

Veamos dos ejemplos sencillos que muestran como funciona Cecil:

  1. Convertir una aplicación de consola a una aplicación Windows.- Si compilamos el siguiente código como una aplicación de consola, al ejecutarse mostrará 2 ventanas (una para la consola y otra para el formulario creado):

    csharp:
    // console.cs
    using System;
    using System.Windows.Forms;

    class Program
    {
        static void Main(string[] args)
        {
            Form frm = new Form();
            frm.Height = 100;
            frm.Width = 100;
            frm.ShowDialog();
        }
    }

    Para hacer la conversión usando Cecil, lo único que se tiene que hacer es:

    csharp:
    using Mono.Cecil;
    using Mono.Cecil.Cil;

    class Program
    {
        static void Main(string[] args)
        {
            AssemblyDefinition assembly = AssemblyFactory.GetAssembly("consola.exe");
            assembly.Kind = AssemblyKind.Windows;
            AssemblyFactory.SaveAssembly(assembly, "windows.exe");
        }
    }

    Si ejecutamos windows.exe, esta vez sólo se mostrará el formulario creado.

  2. Cambiar el espacio de nombres y modificadores de acceso: En este ejemplo se va a cambiar el espacio de nombres de las clases y los modificadores de acceso de un ensamblado denominado ClassLibrary1.dll

    csharp:
    namespace ClassLibrary1.Utility
    {
        public enum HashMethod
        {
            MD5,
            SHA1
        }

        internal class Security
        {
            public static string MD5(string password)
            {
                throw new System.Exception("The method or operation is not implemented.");
            }
        }
       
        class Validation
        {
            public static bool IsEmail(string email)
            {
                throw new System.Exception("The method or operation is not implemented.");
            }
            private void IsUrl(string url)
            {
                throw new System.Exception("The method or operation is not implemented.");
            }
            private void IsIp(string ip)
            {
                throw new System.Exception("The method or operation is not implemented.");
            }
        }
    }

    Para hacer realizar los cambios en el ensamblado de arriba:

    csharp:
    using Mono.Cecil;
    using Mono.Cecil.Cil;

    namespace CecilDemo
    {
        class Program
        { 
            static void Main(string[] args)
            {
                string assemblyName = "ClassLibrary1.dll";

                /* Cargar el ensamblado */
                AssemblyDefinition assembly = AssemblyFactory.GetAssembly(assemblyName);

                /* Iterar sobre los tipos del módulo principal */
                foreach (TypeDefinition type in assembly.MainModule.Types)
                {
                    /* Cambiar el espacio de nombres y el
                     * nivel de acceso a todas las clases
                     */

                    if ("<Module>" != type.Name)
                    {
                        type.Namespace = type.Namespace.Replace("ClassLibrary1", "Buayacorp");
                        type.Attributes |= TypeAttributes.Public;                   
                    }
                   
                    /* Hacer que todos los métodos de la clase Validation
                     * sean públicos y miembros de clase (static).
                     */

                    if ("Validation" == type.Name)
                    {
                        foreach (MethodDefinition method in type.Methods)
                        {
                            /* Eliminar el atributo 'private' de cada uno de los métodos */
                            if ((method.Attributes & MethodAttributes.Private) == MethodAttributes.Private)
                            {
                                method.Attributes ^= MethodAttributes.Private;
                            }

                            method.Attributes |= MethodAttributes.Public | MethodAttributes.Static;                       
                        }
                    }
                }
                /* Almacenar el nuevo ensamblado en CustomClassLibrary1.dll */
                AssemblyFactory.SaveAssembly(assembly, "Custom" + assemblyName);
            }
        }
    }

    Si observamos el ensamblado modificado con Reflector, veremos que se realizaron los cambios.

El uso de esta herramienta obviamente va a depender de las necesidades y posibles limitaciones de acceso al código fuente que tengamos, puesto que no sería nada productivo usar Cecil para hacer cosas parecidas a los ejemplos que muestro. 😀

Cuidado con los siguientes plugins para WordPress

Plugins vulnerables a Remote File Inclusion: wordtube, spamx, wp-table, myflash

Luego de una somera revisión del reporte de páginas no encontradas (gracias a AWStats), veo que hay varios intentos de acceso a plugins que no están instalados en este blog: wordtube, spamx, wp-table, myflash. Si se hace una búsqueda de cualquiera de los plugins mencionados (ejemplo), se puede ver que todos tuvieron el mismo problema de inclusión remota de archivos (Remote File Inclusion).

  • /wp-content/plugins/wordtube/wordtube-button.php: exploit
  • /wp-content/plugins/spamx/MTBlackList.Examine.class.php: exploit
  • /wp-content/plugins/wp-table/js/wptable-button.php: exploit
  • /wp-content/plugins/myflash/myflash-button.php: exploit

Actualización: Según gutielua, el plugin democracy también tiene problemas:

Quisiera comentar otro plugin que muestra fallas de seguridad se trata del DEMOCRACY

[/wordpress/wp-content/plugins/democracy/basic.css]

Uno de los administradores del hosting en donde me hospedo me comento que este archivo en especial hizo que se genera mucho trafico en el servidor, lo que provoco que me suspendieran el sitio por varios días.

Si alguien está usando estos plugins, es recomendable que actualice a las últimas versiones de éstos para evitar problemas posteriores.

Una vez más se puede ver que no importa que tan seguro sea el código principal de WordPress, si nosotros instalamos plugins que son desarrollados – a diestra y siniestra – por gente con poco o nulo interés en temas de seguridad.