Archivo de la etiqueta: software

Los programadores y la seguridad informática

En esta ocasión quiero compartir con ustedes una pequeña experiencia que me sucedió en uno de los muchos grupos de programadores a los que pertenezco en la red social Facebook, esta anécdota me hizo reflexionar acerca del nivel de cultura de seguridad informática que tenemos en México y al final me hizo terminar escribiendo este post a manera de auto crítica constructiva para la misma comunidad de desarrolladores.

Son muchos y muy variados los grupos de programación que uno encuentra Facebook: desarrolladores web, desarrolladores iOS / Android, desarrolladores C#, desarrolladores de videojuegos y todo lo que uno se imagine; esta funcionalidad de Facebook (los grupos) ha pasado a sustituir los antiguos foros de discusión (como smf o phpbb) para la generación millennial ya que de alguna forma es mucho mas cómodo tener todo integrado en la misma plataforma social, pero ese no es el tema de discusión aquí.

La Anécdota

Lo que verdaderamente me llamo la atención fue hace unos días cuando un miembro del grupo hizo una consulta acerca de cómo podía realizar una validación de correo electrónico en un sistema que estaba desarrollando, no me llamo la atención la duda, pues todos los días hay gente que pregunta y mucha otra que le responde, lo que me llamo la atención fue la respuesta que le dio una persona del grupo y sobre todo la convicción con la que escribió la misma.

La imagen esta censurada por que la idea no es quemar a nadie sino más bien sacar algo bueno de todo esto.

La imagen esta censurada por que la idea no es quemar a nadie sino más bien sacar algo bueno de todo esto.

En cuanto termine de leer su respuesta no pude esperar para unirme a su conversación y explicarle por qué su solución era incorrecta desde el punto de vista de seguridad, lo bueno fue que no lo tomo mal y se interesó bastante en el tema.

La solución del comentario de Facebook va más o menos así

mail_fail

¿Pueden ver dónde está el problema de su solución?

La solución iba bien hasta el momento en donde decide regresar el token aleatorio al navegador del usuario y realizar ahí la validación. Explicando un poco más acerca de por qué este esquema de solución era malo le mostré un escenario en donde un atacante podría crear miles de cuentas saltando su sistema de verificación.

Haciendo un pequeño ejercicio de reflexión le propuse lo siguiente:

Partimos de la siguiente premisa: el objetivo del sistema de activación por correo es validar una identidad (así como detener posibles ataques automatizados que te creen cuentas falsas y te llenen la base de datos de usuarios ficticios), para lograr esto se utiliza el concepto de “secreto”, un secreto es un token que debe ser compartido solamente con el usuario mediante el método que él especifico (el correo electrónico), enviando ese token al correo que se supone tiene acceso y es el único medio en el que pueda recibir ese secreto nos aseguramos que la cuenta que el usuario especifico existe y es válida, por lo tanto su identidad ha sido avalada por un proveedor de correo.

Ahora, en el escenario que nos plantean de realizar toda la validación del lado del cliente el problema es que realmente no estas validando nada, si el servidor le está regresando al navegador mediante Ajax el token que se supone el usuario debe escribir ¿Cuál es el punto pedirle revisar su correo? Fácilmente se podría crear un bot que registrara cuentas y las activara de forma masiva, es por eso que no es una buena solución.

source-code-583537_1280

La solución óptima seria (o al menos como se usa en la industria de software hoy en día):

Al momento de crear el usuario en la base de datos debemos manejar un campo para representar el estado actual de su cuenta (activada o desactivada), y cuando el usuario reciba el token por correo este lo introduce en un formulario y es enviado para su comparación del lado del servidor (el token generado también debimos haberlo almacenado de alguna forma en el servidor) y dependiendo de si es válido o no activamos su cuenta.

Lo que me interesaba al final es dejarles en claro que todo el código y los datos (por ejemplo funciones de validación en JavaScript) que enviemos al navegador pueden ser modificados por el usuario, y por lo tanto jamás debemos confiar en esa información.

Bueno aquí termina la anécdota, satisfecho de saber que al menos ese programador siguiendo mis recomendaciones seria capas de lanzar ese componente de forma segura a producción me puse a pensar en todos los demás desarrolladores que tienen dudas pero por X o Y motivo no preguntan y siguen produciendo mas y mas código vulnerable que al final contribuye a llenar las bases de datos sobre hackeos de sitios como https://haveibeenpwned.com o http://www.zone-h.org/

Mi opinión

Como muchos sabrán, actualmente soy consultor de seguridad informática, sin embargo tengo una formación de desarrollador de software, antes de dedicarme a la seguridad y durante la universidad cree muchísimas plataformas web y aplicaciones móviles (y lo sigo haciendo de vez en cuando como FreeLancer xd), estoy convencido de que al realizar una prueba de penetración en algún sistema o aplicación, en el 95% de los casos los hackeos se hubieran evitado si el software hubiera sido diseñado con la seguridad en mente.

Desarrollar software seguro no es una tarea sencilla, nadie nunca lo dijo, pero las empresas de desarrollo y pequeñas agencias tienen la manera de mitigar este problema.

Capacitación del personal

En mi opinión por cada equipo de desarrolladores debería de haber por lo menos una persona con nociones básicas de seguridad, “Nociones básicas” es un término muy relativo, es por eso que las empresas (lideres técnicos, Project managers, IT managers, etc.) deberían voltear a ver estándares y buenas prácticas de seguridad en el desarrollo de software y no solo eso, integrarlas en su ciclo de desarrollo.

Hay un documento que me gusta recomendar bastante.

OWASP Top 10: los diez riesgos más críticos en aplicaciones web

Este documento explica las diez vulnerabilidades más populares en las aplicaciones web hoy en día, así como su riesgo, impacto y mitigación.

owasp

Ya sea que trabajes para una empresa o seas un desarrollador FreeLancer, te aseguro que si desarrollas tu software tomando como referencia los 10 puntos de OWASP tu aplicación sera lo suficientemente robusta para que no venga cualquier lammer / hackerucho de tercera y vulnere tu sistema usando sus herramientas automatizadas.

Como decía mas arriba, producir software seguro es compromiso de todos, las metodologías de desarrollo ágil como SCRUM son buenas y funcionan, pero muchas veces el personal que las lleva acabo deja de lado el tiempo requerido para hacer un buen diseño de software (con la seguridad en mente, programación defensiva, etc.) o lo minimiza

Aunque lo ideal sería tener un departamento de seguridad que apoyara al departamento de desarrollo durante todo el ciclo de vida del proyecto.

Después de todo, ¿cuánto te cuesta contratar un arquitecto de seguridad? ¿Cuánto te costaría recuperarte de un hackeo (hablando de información, dinero y prestigio de la empresa)?

Juego 4 en raya hecho en C++

Revisando entre mis curiosidades me encontré un código que hice hace varios años (de la prepa creo), se trata del juego 4 en línea o 4 en raya hecho en C++, he decidido subirlo al blog ya que no me gustaría que se perdiera en el final de los tiempos xD.

Pueden descargar el código fuente aca:

Juego 4 en raya hecho en C++

#include <iostream>

using namespace std;

const int n=6;
const int m=8;

bool sobranEspaciosLibres(int tablero[n][m])
{
    for(int i = 0; i < 6; i++)
    {
        for(int j = 0; j < 8; j++)
        {
            if(tablero[i][j] == 0)
            {
                //Sobran espacios donde colocar fechas
                //cout<<"Hay espacios"<<endl;
                return true;
            }
        }
    }

    //No sobran mas espacios donde colocar fichas, juego empatado
    cout<<"No hay mas espacios: empate"<<endl;
    return false;
}

void ImprimirTablero(int tablero[n][m])
{
    for(int i = 0; i < 6; i++)
    {
        for(int j = 0; j < 8; j++)
        {
            if(tablero[i][j] == 1)
            {
                cout<<" O ";
            }
            else if(tablero[i][j] == 2)
            {
                cout<<" X ";
            }
            else
            {
                cout<<" . ";
            }

        }
        cout<<endl;
    }
}

int ColocarFichaEn(int tablero[n][m], int columna)
{
    for(int i = 0; i < 6; i++)
    {
        if(!(i+1 > 5))
        {
            if(tablero[i][columna] == 0 && tablero[i+1][columna] != 0 )
            {
                return i;
            }
        }
        else
        {
            //Alcanzo la base del tablero
            if(tablero[i][columna] == 0)
            {
                return i;
            }
        }
    }

    return -1;
}

bool columnaATope(int tablero[n][m], int columna)
{
    if(tablero[0][columna] != 0)
    {
        cout<<"No hay espacio para colocar la ficha ahi"<<endl;
        return true;
    }
    return false;
}

bool ganador(int tablero[n][m], int fila, int columna, int jugador)
{
    //Vertical
    bool encontrado = false;
    int total = 0;

    for(int i = 0; i < n; i++)
    {
        //cout<<"i: "<<i<<endl;
        if(encontrado)
        {
            if(tablero[i][columna] == jugador)
            {
                total++;
            }
            else
            {
                encontrado = false;
                total = 0;
            }
        }
        if(tablero[i][columna] == jugador && !encontrado)
        {
            encontrado = true;
            total++;
        }

        //cout<<"total: "<<total<<endl;
        if(total == 4)
        {
            cout<<"El jugador "<<jugador<<" gana!"<<endl;
            return true;
        }
    }

    //Horizontal
    encontrado = false;
    total = 0;

    for(int i = 0; i < m; i++)
    {
        //cout<<"i: "<<i<<endl;
        if(encontrado)
        {
            if(tablero[fila][i] == jugador)
            {
                total++;
            }
            else
            {
                encontrado = false;
                total = 0;
            }
        }
        if(tablero[fila][i] == jugador && !encontrado)
        {
            encontrado = true;
            total++;
        }

        //cout<<"total: "<<total<<endl;
        if(total == 4)
        {
            cout<<"El jugador "<<jugador<<" gana!"<<endl;
            return true;
        }
    }

    //Diagonal \
    //Obtener Coordenadas donde inicia la diagonal en base a fila - columna
    int nuevaFila = fila;
    int nuevaColumna = columna;
    encontrado = false;
    total = 0;

    //cout<<"Fila: "<<fila<<" Columna: "<<columna<<endl;

    while((nuevaFila != 0 || nuevaColumna != 0))
    {
        nuevaFila--;
        nuevaColumna--;

        //cout<<"nueva Fila: "<<nuevaFila<<" nueva Columna: "<<nuevaColumna<<endl;
        if(nuevaFila == 0 || nuevaColumna == 0)
        break;
    }

    //cout<<"nueva Fila: "<<nuevaFila<<" nueva Columna: "<<nuevaColumna<<endl;

    do
    {
        if(nuevaFila >= n)
        break;

        //cout<<"nueva Fila: "<<nuevaFila<<" nueva Columna: "<<nuevaColumna<<endl;
        if(encontrado)
        {
            if(tablero[nuevaFila][nuevaColumna] == jugador)
            {
                total++;
            }
            else
            {
                encontrado = false;
                total = 0;
            }
        }
        if(tablero[nuevaFila][nuevaColumna] == jugador && !encontrado)
        {
            encontrado = true;
            total++;
        }

        //cout<<"total: "<<total<<endl;
        if(total == 4)
        {
            cout<<"El jugador "<<jugador<<" gana!"<<endl;
            return true;
        }

        nuevaFila++;
        nuevaColumna++;

    }while(nuevaFila < n);



    //Diagonal /
    nuevaFila = fila;
    nuevaColumna = columna;
    encontrado = false;
    total = 0;

    //cout<<"Fila: "<<fila<<" Columna: "<<columna<<endl;

    while((nuevaFila != 0 || nuevaColumna != m))
    {
        nuevaFila--;
        nuevaColumna++;

        //cout<<"nueva Fila: "<<nuevaFila<<" nueva Columna: "<<nuevaColumna<<endl;
        if(nuevaFila == 0 || nuevaColumna == m)
        break;
    }

    //cout<<"nueva Fila: "<<nuevaFila<<" nueva Columna: "<<nuevaColumna<<endl;

    do
    {
        //cout<<"nueva Fila: "<<nuevaFila<<" nueva Columna: "<<nuevaColumna<<endl;
        if(nuevaFila >= n)
        break;

        //cout<<"nueva Fila: "<<nuevaFila<<" nueva Columna: "<<nuevaColumna<<endl;
        if(encontrado)
        {
            if(tablero[nuevaFila][nuevaColumna] == jugador)
            {
                total++;
            }
            else
            {
                encontrado = false;
                total = 0;
            }
        }
        if(tablero[nuevaFila][nuevaColumna] == jugador && !encontrado)
        {
            encontrado = true;
            total++;
        }

        //cout<<"total: "<<total<<endl;
        if(total == 4)
        {
            cout<<"El jugador "<<jugador<<" gana!"<<endl;
            return true;
        }

        nuevaFila++;
        nuevaColumna--;

    }while(nuevaFila < n);

    return false;
}

int main()
{
    int matriz[n][m];

    //Preparamos el tablero del juego rellenandolo con 0's
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < m; j++)
        {
            matriz[i][j] = 0;
            //cout<<matriz[i][j]<<" ";
        }
        //cout<<" "<<endl;
    }

    //Logica
    int jugador = 0;
    int ultimo = 0;
    do
    {
        int colocarColumna = -1;
        bool columnaTope = true;

        if(ultimo == 1)
        {
            jugador = 2;
        }
        else
        {
            jugador = 1;
        }

        do
        {
            cout<<"Turno del jugador "<<jugador<<" - Elije un numero del 1 al 8: "; cin>>colocarColumna; cout<<endl;
            colocarColumna--;
            columnaTope = columnaATope(matriz,colocarColumna);
        }
        while((colocarColumna < 0 || colocarColumna > 7) || columnaTope);

        int colocarFila = ColocarFichaEn(matriz,colocarColumna);
        matriz[colocarFila][colocarColumna] = jugador;
        ImprimirTablero(matriz);

        //Revisar si hay un 4 en raya
        if(ganador(matriz,colocarFila,colocarColumna,jugador))
        {
            break;
        }

        ultimo = jugador;
        jugador++;
    }
    while(sobranEspaciosLibres(matriz));

    return 0;
}

PD

No tiene nada de inteligencia artificial ni algoritmos minimax, es el código del juego simplemente, muy sencillo y algo feo también :p.

Siguen los rumores referentes al iPhone 5


Como comentaba en post anteriores, los rumores acerca de las posibles fechas de lanzamiento del iPhone 5, el material con el que estará construido y las nuevas tecnologías que contendrá se hacen cada vez mas fuertes.

Recordemos que la carcaza del iPhone 3 estaba hecha de plástico, después vino el iPhone 4 y 4s el cual manejaba una carcaza hecha de cristal tratado químicamente e incorporaba partes metálicas de acero inoxidable, pues ahora como si fuera una película de ciencia ficción se rumora que el iPhone 5 tendrá una cubierta hecha de liquid Metal (si metal liquido como el terminator xD).

El metal liquido es una aleación que aporta grandes características y ventajas a los dispositivos o aparatos que lo utilizan, el liquid Metal no es nada nuevo, solo que el uso que se le había dado durante las ultimas décadas era mas bien de carácter bélico y para construir material armamentista. En agosto de 2010 apple adquirió los derechos del “Liquid Metal” y poco después comenzó a contratar ingenieros para que adaptaran esa tecnologia a sus productos, es por eso que es valido pensar que el iPhone 5 podría ser mucho mas delgado y resistente que sus antecesores.

salu2

Diplomado Fundamentos HTML5 con Java Script Avanzado


Por parte de Rubén Mugártegui les extiendo la invitación para tomar el Diplomado “Fundamentos de HTML5” que se llevará a cabo en dos partes: la primera (Introducción a HTML5) comienza el 28 de noviembre, y la segunda (HTML5 con Javascript) hasta el próximo año. Algunos puntos a aclarar:

Es un curso en linea de 3 semanas de duración, aproximadamente les tomará una media hora45 minutos al dia de estudio

El curso es respaldado por un instructor certificado y reconocido por Microsoft como Microsoft Valuable Professional (MVP).

Se entregará un diploma con valor curricular, siempre y cuando se concluya 100% el diplomado con las actividades perfectamente completadas.

El costo del diplomado es de $45 dolares, pero se otorgan becas del 100% hay dos opciones:

Buscando a una persona que haya terminado el diplomado de Azure (Jorge Angel Mena) para que los invite, siempre y cuando se comprometan a terminar el diplomado. Los interesados favor de mandar un correo a [email protected]

  • Comprometerte a terminar el diplomado. Si no lo logras, no podrás tomar el curso de HTML5 avanzado. Posterior a tu inscripción recibirás un formato de compromiso de término.
  • Para registrarte al diplomado usa la siguiente liga
    Les recomiendo que vayan descargando WebMatrix

El temario del diplomado es el siguiente: El usuario…

  • Identificará los principales elementos de la estructura de una página HTML5
  • Conocerá los fundamentos y propósito de las hojas de estilo en cascada (CSS)
  • Identificará los principales elementos de HTML
  • Podrá crear páginas Web incorporando imágenes incluyendo mapas de imágenes
  • Identificará los distintos tipos de listas disponibles en HTML
  • Identificará los usos principales de las Tablas
  • Podrá crear formularios para captura de datos
  • Incorporará código JavaScript en las páginas Web
  • Incorporará características multimedia en las páginas Web
  • Identificará el estado actual de HTML5
  • Conocerá algunas de las herramientas disponibles para crear código HTML
  • Logrará comprender las características más importantes del navegador Internet Explorer 9 y cómo explotar las mismas a través del uso de los estándares de HTML5.
  • Tendrá la oportunidad de brindar riqueza a sus sitios convirtiéndolos en aplicaciones para lograr mayor exposición dentro del escritorio Windows.

Cualquier duda, Habrá una sesión de videoconferencia el Jueves 17 de Noviembre a las 17:00 horas (Centro del Tiempo de México) http://ti-capacitacion.com/ html5/default.htm

Nuevo sistema de seguridad de facebook

Facebook ha revelado detalles extraordinarios acerca de la infraestructura de seguridad que utilizan actualmente para combatir el spam y otros problemas como el phishing, esto va muy relacionado con todas aquellas personas que quieren enterarse como configurar la privacidad en facebook.

Conocido como Sistema inmune de Facebook (FIS por sus siglas en ingles), Facebook Immune System, es un sistema de seguridad defensivo que por el momento parece ser suficiente para combatir el gran problema del Spam. Cifras reveladas por la compañía esta semana indican que por el momento menos del 1% de los usuarios de la red social están experimentando Spam, “Si, aun no es perfecto”, indico un representante de la compañía.

Tomo tan solo 3 años transformar al FIS de un sencillo sistema de seguridad a una compleja herramienta con algoritmos capaz de monitorear cada foto compartida en la red, cada actualización de estado, en efecto cada click hecho por cada uno de los 800 millones de usuarios de Facebook.

En total hay unas 25 billones de actualizaciones de datos de este tipo cada dia, cuando el sistema de seguridad trabaja al 100% es capaz de monitorear unas 650 mil acciones por minuto.

“Es un gran reto”, señalo Jim Larus, un investigador de Microsoft de Redmon, Washington, quien se especializa en el estudio de grandes redes, Larus piensa que la única red que supera a Facebook en tamaño es la Web en si, esto convierte al FIS en unos de los sistemas de seguridad mas grandes jamás creados en por la humanidad.

Para detectar patrones de comportamiento sospechosos se esta utilizando software de inteligencia artificial, el sistema es supervisado por un equipo de 30 personas, la aplicación aprende en tiempo real y es capaz de tomar sus propias decisiones sin la necesidad de la interacción con un humano.

Uno de los ataques mas notables hacia la red social ocurrió en abril de este año, menciono Tao Stein, un ingeniero de facebook que trabajo en el sistema de seguridad. Todo comenzó cuando un usuario creo un código que era introducido en la barra de navegación, el código automaticamente mandaba mensajes de spam por medio del chat de facebook donde invitaba a los usuarios ha entrar a una pagina con instrucciones para copiaran y pegaran el mismo código en su barra de navegación y el gusano se siguiera propagando, “ataques de este tipo pueden generar millones de consultas por minuto”, indico Stein.

Los usuarios son menos susceptibles a sufrir este tipo de ataques, por ejemplo en el correo electrónico, ya que el mensaje proviene de un extraño, pero en facebook es diferente, ya que los mensajes vienen directamente de los amigos del usuario.

Para combatir este problema, FIS genera una firma que es utilizada para diferenciar entre mensajes legítimos y mensajes de spam, esto se basa mas que nada en los links del mensaje, palabras como “gratis” y “ipad” y la dirección IP de la computadora desde donde se envían los mensajes influyen.


..

¿Nos estaremos acercando a la singularidad tecnologica?

Articulo original Inside Facebook’s massive cyber-security system