Categories
.NET ASP.NET

Instalación del SP1 de Visual Studio 2005

La instalación del SP1 -beta- para Visual Studio 2005 fue realmente un martirio, a continuación una pequeña crónica:

Primero, para poder descargar el SP, tuve que volver a usar -necesariamente- Internet Explorer e instalar un componente ActiveX para la transferencia de archivos, la velocidad de descarga oscilaba en 25 Kb/s, por lo cual tuve que esperar aproximadamente 4 horas para descargar los 371.88 MB del parche principal - me pregunto porque no usan BitTorrent para distribuir este tipo de cosas.

Una vez descargado el SP, tuve esperar unos 5 minutos para que el instalador solamente me pregunte si quiero instalar el parche o no... finalmente, una hora después terminó la instalación y con esto, la actividad de mi procesador volvió a la normalidad.

Unas cuantas imágenes de la actividad que tuvo mi procesador durante la instalación:

No sé si realmente habrá sido problema de mi máquina, o es que talvez no han solucionado completamente los problemas que describían hace tiempo con el tamaño del parche.

Categories
.NET ASP.NET

Visual Studio 2005 Service Pack 1 Beta

Ya está disponible para la descarga la beta del Service Pack 1 para las versiones en inglés y español del Visual Studio 2005, el tamaño del parche principal es de 371.88 MB

Los parches son los siguientes:

Para descargar este Service Pack, es necesario que se suscriban en la siguiente dirección.

Categories
PHP Quiz Seguridad

Quiz sobre validación de datos en PHP

El código mostrado a continuación, es una versión reducida de una falla de seguridad presente en una aplicación algo conocida.

Indiquen la falla, lo que se puede hacer con ésta, una forma de explotarlo y la solución que plantean al mismo:

php:

// demo.php
<?php

include './db.php';

error_reporting(0);

$tb_url    = $_POST['url'];
$title     = $_POST['title'];
$excerpt   = $_POST['excerpt'];

if (empty($title) || empty($tb_url) || empty($excerpt)) {
        die ('Invalid values');
}

$titlehtmlspecialchars( strip_tags( $title ) );
$title = (strlen($title) > 150) ? substr($title, 0, 150) . '...' : $title;
$excerpt = strip_tags($excerpt);
$excerpt = (strlen($excerpt) > 200) ? substr($excerpt, 0, 200) . '...' : $excerpt;

$contents=@file_get_contents($tb_url);
if(!$contents) {       
        die('The provided URL does not seem to work.');
}

$query = "INSERT INTO tabla (url, title, excerpt) VALUES ('%s', '%s', '%s')";

$db->query
        (
                sprintf (
                        $query,
                        $db->escape($tb_url),
                        $db->escape($title),
                        $db->escape($excerpt)
                        )
        );

?>

php:

// show.php
<!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>
                <title>Bug</title>
        </head>
        <body>

                <ul>
                <?php

                include './db.php';
                $items = $db->get_results('SELECT url, title, excerpt FROM tabla');

                foreach ($items as $tb) :
                        echo '<li><a href="'.$tb->url.'" title="'.$tb->excerpt.'">'.$tb->title.'</a></li>';               
                endforeach;

                ?>
                </ul>

        </body>
</html>

Para el acceso a datos se usa la clase ez_sql, el método escape en mi versión, contiene lo siguiente:

php:

function escape($string) {
        if (get_magic_quotes_gpc())
                $string = stripslashes($string);
        return mysql_real_escape_string( $string, $this->dbh );
}
Categories
Varios

¿Compuntoes?

Gracias al post que publicó Braulio sobre compuntoes, recién me entero que es un nuevo concurso de posicionamiento, que al parecer ha generado bastante controversia.

Al intentar indagar un poco más en Technorati -que rara vez lo uso- para ver los últimos comentarios sobre el fucking término compuntoes, llego al sitio de uno de los participantes, quien, por el título y el contenido de su última entrada, está realmente descontento por el supuesto tercer lugar que ocupa este blog en la siguiente búsqueda. Lo curioso de esto, es que tiene una linda definición de este blog:

El tercer puesto es un blog cualquiera ahí, salido de las nada con 34 lectores en el feed.

No entiendo porque se preocupa por un blog cualquiera con tan pocos lectores... 😛

En fin, suerte a todos participantes de este concurso.

Categories
.NET

Implementación de un pequeño Servidor Web

El siguiente código, originalmente publicado por Eric Carter, muestra la implementación de un pequeño "Servidor Web" con C#, para hacerlo funcionar necesitarán del .NET Framework 2.0 (podría correr en versiones anteriores haciendo ligeras modificaciones al código).

csharp:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using System.Collections.Specialized;

namespace http
{
    public class FakeWebServer
    {
        private const string URL_REPLACE = "{URL}";
        private static readonly Regex urlRegex = new Regex(@"^(GET|POST) /(.*?) (HTTP[^\s]+)",
                                        RegexOptions.Compiled | RegexOptions.IgnoreCase);

        // Almacena las URLs verdaderas y falsas
        public static readonly Dictionary<string, string> FakeUrls;

        static FakeWebServer()
        {
            FakeUrls = new Dictionary<string, string>();
        }

        private TcpListener listener;
        string contents;

        public FakeWebServer(int port, string responseContents)
        {
            this.contents = responseContents;

            // 'Escuchar' en cualquier dirección
            listener = new TcpListener(IPAddress.Any, port);
            listener.Start();

            Thread t = new Thread(delegate()
            {
                AcceptClients();
            });
            t.Start();
        }
        public void AcceptClients()
        {
            while (true)
            {
                using (TcpClient client = listener.AcceptTcpClient())
                {
                    if (client.Connected) // Nuevo cliente
                    {
                        // Leer los datos enviados
                        NetworkStream stream = client.GetStream();
                        byte[] data = new byte[1024];

                        stream.Read(data, 0, data.Length);

                        string request = Encoding.UTF8.GetString(data);

                        // Sólo tomar en cuenta los datos presentes en el QueryString

                        // Obtener la versión del protocolo y la URL del 'Request'
                        MatchCollection matches = urlRegex.Matches(request);

                        string qs = matches[0].Groups[2].Value.TrimStart('?');
                        NameValueCollection paramArray = HttpUtility.ParseQueryString(qs);

                        foreach (string key in paramArray.AllKeys)
                        {
                            if (FakeUrls.TryGetValue(paramArray[key], out qs))
                                break;
                        }                       
                       
                        System.Diagnostics.Debug.WriteLine("Query String: " + matches[0].Groups[2].Value);

                        // Reemplazar las URLs
                        if (!string.IsNullOrEmpty(qs) && !string.IsNullOrEmpty(contents))
                            contents = contents.Replace(URL_REPLACE, qs);

                        // Enviar las cabeceras necesarias y el contenido
                        SendHeaders(matches[0].Groups[3].Value, null, contents.Length, "200 OK", client);
                        SendToBrowser(Encoding.UTF8.GetBytes(contents), client);
                    }
                }
            }
        }

        public void SendHeaders(string httpVersion, string mimeHeader, int totalBytes, string statusCode, TcpClient tcpClient)
        {
            StringBuilder responseBuilder = new StringBuilder();

            if (string.IsNullOrEmpty(mimeHeader))
                mimeHeader = "text/html";

            responseBuilder.Append(httpVersion);
            responseBuilder.Append(' ');
            responseBuilder.AppendLine(statusCode);
            responseBuilder.AppendLine("Server: Fake Web Server");
            responseBuilder.Append("Content-Type: ");
            responseBuilder.AppendLine(mimeHeader);
            responseBuilder.AppendLine("Accept-Ranges: bytes");
            responseBuilder.Append("Content-Length: ");
            responseBuilder.AppendLine(totalBytes.ToString());
            responseBuilder.AppendLine("");

            Byte[] bSendData = Encoding.UTF8.GetBytes(responseBuilder.ToString());
            SendToBrowser(bSendData, tcpClient);

            System.Diagnostics.Debug.WriteLine("Total Bytes : " + totalBytes.ToString());
        }

        public void SendToBrowser(Byte[] data, TcpClient tcpClient)
        {
            if (tcpClient.Connected)
            {
                NetworkStream stream = tcpClient.GetStream();

                stream.Write(data, 0, data.Length);
                stream.Flush();
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("Connection Dropped....");
            }

        }
    }
}

Como habrán podido observar el "Servidor Web", entrega tontamente casi el mismo contenido, sólo reemplaza cada aparición de {URL} en la respuesta en base a los parámetros solicitados.

En una siguiente entrada explicaré la valiosa ayuda que presta ese pedazo de código, en la explotación de otro bug de una aplicación ya algo conocida por este blog.