Categories
.NET ASP.NET Internet Explorer Web Windows Forms

Capturar una página Web de manera sencilla

Por si alguien necesita una funcionalidad parecida a lo que ofrecen sitios como WebSnapr o Snap, a continuación pongo la manera de capturar una página web como imagen.

csharp:

string url = "http://www.buayacorp.com/";
using (WebBrowser navegador = new WebBrowser())
{
    // Tamaño del navegador
    navegador.Size = new Size(1024, 768);
    // Deshabilitar la barra de scroll
    navegador.ScrollBarsEnabled = false;

    // Cargar la página
    navegador.Navigate(url);

    // Esperar a que cargue completamente la página
    while (navegador.ReadyState != WebBrowserReadyState.Complete)
    {
        Application.DoEvents();
    }
    // Tamaño de la imagen a capturar
    Rectangle tamaño = new Rectangle(0, 0, 1024, 768);
    Bitmap bitmap = new Bitmap(tamaño.Width, tamaño.Height);

    // Guardar la imagen de la página con el tamaño especificado
    navegador.DrawToBitmap(bitmap, tamaño);

    // Convertir y guardar la imagen como jpg
    Bitmap thumbnail = new Bitmap(tamaño.Width, tamaño.Height);
    Graphics gfx = Graphics.FromImage(thumbnail);
    gfx.DrawImage(bitmap, tamaño, tamaño, GraphicsUnit.Pixel);

    thumbnail.Save(@"E:\demos\demo.jpg", ImageFormat.Jpeg);
}

Esa porción de código hace una captura de 1024x728 pixeles, si se quiere capturar la página completa sólo es necesario jugar con los valores de navegador.Document.Body.ClientRectangle.

Por otro lado, como seguramente saben la clase WebControl usa internamente los controles de Internet Explorer disponibles en la máquina donde se ejecuta la aplicación, así que si un sitio se ve mal con este navegador, la imagen capturada también tendrá este pequeño problema.

Categories
.NET ASP.NET Desarrollo de Software Utilidades Web Windows Forms

Reflector 5.0

Al parecer ayer se liberó una nueva versión de Reflector, una herramienta muy útil que permite explorar, analizar, ver, etc. los ensamblados de .NET.

Entre las novedades que trae esta versión, están:

  • Soporte para LINQ y el .NET Framework 3. 5
  • Existe un nuevo protocolo "code://" que hace que Reflector cargue el tipo especificado, por ejemplo code://System.Web/System.Web.HttpResponse/TransmitFile(String) debería ubicarlos en el método TransmitFile de la clase HttpResponse.
  • Existe la posibilidad de registrar una extensión (Reflector.exe /register) para que cada vez que se haga click derecho sobre un ensamblado compatible con .NET, aparezca una opción "Browse with .NET Reflector" en el menú contextual.

Para sacarle más provecho a esta herramienta, se pueden agregar plugins de acuerdo a las necesidades que tenga uno.

Categories
.NET ASP.NET Desarrollo de Software Web

Response.TransmitFile, nueva forma para enviar archivos al cliente en ASP.NET 2

Existen algunos escenarios donde hay la necesidad de que antes de autorizar la descarga de un archivo desde nuestra aplicación, debamos realizar algún tipo de proceso. En estos casos lo que básicamente hacía es lo siguiente:

csharp:

// Algun tipo de validación o proceso
// ...
string file = Request.Params["file"];
if (!string.IsNullOrEmpty(file))
{
    file = Path.Combine(Server.MapPath("downloads"), Path.GetFileName(file));

    Response.Clear();
    Response.ContentType = "application/octect-stream";
    Response.AddHeader("Content–Disposition", "attachment; filename=foo.xyz");
    Response.WriteFile(file);
    Response.End();
}

Categories
Menéame Seguridad Web XSS

Menéame y las cookies HttpOnly

Este último fin de semana finalmente fue incluido un parche para que la cookie donde se almacena las credenciales del usuario, sea marcada con la propiedad HttpOnly

Se hizo esta sugerencia gracias a un bug (XSS) -sobre el que comentaré dentro de unos días- que afectaba principalmente a todas las versiones de Internet Explorer, funcionaba porque este navegador hace posible la ejecución de javascript desde CSS.

Si bien es cierto que esta nueva característica incluida en menéame no evita del todo el robo de cookies, por lo menos limitará un poco más el número de vectores de ataques XSS.

Categories
Seguridad Web WordPress XSS

Nueva vulnerabilidad de WordPress

Héctor comentaba sobre la liberación de una nueva versión de wordpress que corregía un bug presente en las ramas 2.0 y 2.1 de este CMS.

Este error se presenta en la función wp_nonce_ays (archivo wp-includes/functions.php), porque la variable $action no está correctamente validada y en algunos casos, ésta puede ser modificada por el cliente. Por ejemplo http://vulnerable.com/wp-admin/plugins.php?action=activate&plugin=<script>alert(/XSS/)<script> es un posible vector de ataque.

php:

function wp_nonce_ays($action) {
        global $pagenow, $menu, $submenu, $parent_file, $submenu_file;

        $adminurl = get_option('siteurl') . '/wp-admin';
        if ( wp_get_referer() )
                $adminurl = wp_get_referer();

        $title = __('WordPress Confirmation');
        // Remove extra layer of slashes.
        $_POST   = stripslashes_deep($_POST  );
        if ( $_POST ) {
                $q = http_build_query($_POST);
                $q = explode( ini_get('arg_separator.output'), $q);
                $html .= "\t<form method='post' action='$pagenow'>\n";
                foreach ( (array) $q as $a ) {
                        $v = substr(strstr($a, '='), 1);
                        $k = substr($a, 0, -(strlen($v)+1));
                        $html .= "\t\t<input type='hidden' name='" . attribute_escape(urldecode($k)) . "' value='" . attribute_escape(urldecode($v)) . "' />\n";
                }
                $html .= "\t\t<input type='hidden' name='_wpnonce' value='" . wp_create_nonce($action) . "' />\n";
X              $html .= "\t\t<div id='message' class='confirm fade'>\n\t\t<p>" . wp_explain_nonce($action) . "</p>\n\t\t<p><a href='$adminurl'>" . __('No') . "</a> <input type='submit' value='" . __('Yes') . "' /></p>\n\t\t</div>\n\t</form>\n";
        } else {
X              $html .= "\t<div id='message' class='confirm fade'>\n\t<p>" . wp_explain_nonce($action) . "</p>\n\t<p><a href='$adminurl'>" . __('No') . "</a> <a href='" . add_query_arg( '_wpnonce', wp_create_nonce($action), $_SERVER['REQUEST_URI'] ) . "'>" . __('Yes') . "</a></p>\n\t</div>\n";
        }
        $html .= "</body>\n</html>";
        wp_die($html, $title);
}

Para corregir este fallo, simplemente hay que aplicar la función wp_specialchars sobre la salida de wp_explain_nonce en las línes marcadas con X:

php:

wp_specialchars(wp_explain_nonce($action));

Aprovechando este suceso, finalmente actualicé el blog a la versión 2.1 de WordPress e instalé el plugin wp-cache; si notan algún error, les estaré muy agradecido si me lo hacen saber.