Delanover

Blog sobre Informática y Seguridad

Siento todo este tiempo sin escribir, he estado ocupado con temas de la universidad hasta este dia. Pero bueno, intenté despedirme durante un tiempo con una entrada especial como la de Vodafone.

Aunque no haya publicado nada desde entonces, tengo en mente varias entradas, así que volver a estar asiduo (o eso espero).

Empezaré la entrada lanzando una pregunta. ¿Estamos preparados para perder nuestro smartphone? Todos sabemos que la respuesta es no. En ese caso la mayoria de la gente perdería desde contactos hasta fotos. Pero vamos a intentar que este no sea nuestro caso.

Paso 1: la nube puede ser nuestra amiga.

Desde hace tiempo, he dejado de agregar contactos al móvil de forma tradicional, es decir, desde el propio teléfono añadir el contacto. Desde ahora, uso mi cuenta de GMail para agregar ahí a los contactos y posteriormente, actualizar los de mi teléfono teniéndolo sincronizado a dicha cuenta.

Ventajas:
Como principal ventaja, está si perdemos el teléfono, los contactos los seguimos teniendo en nuestra cuenta. Igualmente añado, que podemos añadir contactos desde el teléfono a la cuenta de GMail.
Control de tus contactos desde el ordenador, clasificación, puedes ponerles imágenes, y todo lo que puedes hacer desde tu teléfono, pero más cómodo incluso.

Paso 2: copia de seguridad de todos nuestros archivos

El objetivo original de esta entrada era mayormente este paso, ya que era el entretenido realmente, pero ya que estoy, he añadido el paso anterior ya que también me parece interesante.

Lo primero que haremos será bajarnos una aplicación para Android (gratuita): FTPDroid (también existe la versión de pago).

Esta aplicación nos permitirá convertir nuestro teléfono en un servidor FTP en donde nos conectaremos desde el ordenador y haremos copias de seguridad. Si, para hacer copias de seguridad solo necesitamos un cable y copiar-pegar, pero eso no es entretenido, se busca una manera más entretenida.

Configuración:


Añadimos un usuario y contraseña, y por defecto, la ruta en la cual accederemos será la de la tarjeta. Podriamos hacer una copia de seguridad de todo el teléfono, pero a mi personalmente me interesa la tarjeta, ya que es ahí en donde solemos meter canciones, recibir archivos, guardar ficheros, fotografias, grabaciones, etc. En este ultimo caso, cambiariamos la ruta que está, por / aunque algunos archivos no nos dejan copiarlos (supongo que teniendo el teléfono rooteado si que te dejará).

En la parte de opciones, desactivamos “Enable anonymous” para que solamente podamos acceder al teléfono a través del nombre de usuario y contraseña previamente establecido (por si acaso).

Una vez configurado esto, ya podemos acceder a nuestro teléfono desde el navegador. Si la IP local de nuestro teléfono fuese 192.168.1.100, accederiamos de la siguiente manera: ftp://192.168.1.100:2121

Comando lft
Ahora, desde la consola realizaremos la copia de ficheros, pero en lugar de usar el comando ftp como todos hemos pensado, usaremos lftp.

A diferencia de ftp, lftp permite realizar algunas más cosas, pero nos centraremos en una sola, y es en la función “mirror”.

Usaremos esta función para hacer copia de seguridad de nuestra tarjeta. Desde la consola, nos situamos en la carpeta en donde queremos llevar la copia de seguridad y seguimos los siguientes pasos:

sftp 192.168.1.100 -p 2121

Tras conectarnos establecemos el nombre de usuario y contraseña

user Usuario Contraseña

Usamos la función mirror, estableciendo que queremos copiar desde la ruta / (Nota: se copia recursivamente por defecto) (Nota 2: recordemos que / equivale a /mnt/sdcard ya que es lo que hemos configurado en nuestro teléfono).

mirror /

Este proceso nos puede llevar largos minutos, dependiendo de lo que tengamos en el teléfono claro. Ahora viene lo realmente beneficioso e interesante. Al cabo del tiempo habremos sacado nuevas fotos y tendremos nuevos archivos. ¿Tendremos que copiarlos todos de nuevo? No. ¿Hay alguna función que nos permita copiar solo los nuevos? En efecto. Además, esto también nos es útil por si hemos tenido algún problema al hacer la primera copia, como una desconexión a internet o algo.

mirror / -n

Nos queda hacer un último paso. Al realizar esto, igual tenemos problemas con los permisos. Yo mismo he tenido problemas haciéndolo en Windows, ya que no me dejaba accceder a nada de lo que habia copiado.

Para ello, realizamos un cambio de permisos. Si no nos queremo complicar y estamos en Windows, nos vamos a la carpeta donde hemos hecho la copia y hacemos un chmod recursivo:

chmod -R 777 /

Algo más acerca de LFTP

Dentro de las opciones que nos ofrece el comando mirror, podemos hacer un reverse mirror, que viene siendo lo mismo pero al revés, es decir, en vez de bajarnos del servidor un arbol con sus descendientes, lo subimos.

mirror / -R

En general, lftp es más potente que ftp. Una diferencia con respecto el comando ftp es que con lftp podemos combinar comandos locales de la consola y comandos propios de lftp. Por ejemplo, desde una sola línea podriamos comprimir el directorio actual (local), subirlo al servidor, y luego borrarlo del directorio local:

!(tar -cvvf target.tar * && gzip target.tar) && put target.tar.gz && !(rm target.tar.gz)

Como podemos ver, el símbolo de exclamación nos permite ejecutar en el sitio local.
Otra diferencia es que con lftp podemos trabajar fácilmente con el grep. Imaginemos que queremos todos los ficheros que no sean carpetas de nuestr servidor:

ls | grep '^[^d]'

lftp además de soportar transferencias ftp como hemos estado viendo, también soporta http y sus respectivas versiones encriptadas (ftps y https).

Por último, también interesante, es que lftp puede ejecutar scripts mediante el comando -f de la siguiente manera. Suponiendo que tenemos un archivo llamado script con el siguiente contenido:

connect 192.168.1.100 -p 2121
user Usuario Contraseña
ls

Al ejecutar lftp -f script se ejecuta todo el contenido del script, nos devuelve el ls del directorio remoto y volvemos a tener la consola operativa.

Un saludo, lipman

Parte 1 del Post.

Tras meses sin hacer nada los de Vodafone.es, el pasado jueves dia 8 publiqué un Proof of Concept de la inseguridad que esta página proveia, hasta el punto de poder entrar en cualquier cuenta a partir únicamente del número de teléfono de la “víctima”.

En este momento (dia 14 de diciembre), unos 6 días después de la publicación, he vuelto a entrar a Vodafone.es y me he dado cuenta de que han mejorado la seguridad: en lugar de tener que pasar una puerta delgada de madera, tenemos que pasar a través de dos.

El principal fallo residía en la obtención de una nueva contraseña, dándole a “recordar contraseña”. Esto es lo que habia antes de ser “arreglado”:

Ahora:

Como podemos ver no ha cambiado mucho, podemos elegir de poner nuestro teléfono, y es realmente lo mismo. Donde si notamos el cambio es en la segunda parte. Antes:

Ahora:

La primera parte (lo de la pregunta secreta) aparece una vez la hemos establecido (la primera vez que realicé la prueba no aparecia, y al finalizarla, me pedia que la introdujese). Lo que si que aparece ya fijo es lo demás.
Por un lado, necesitamos la identificación (vease, DNI y demás) y por otro, podemos elegir entre: introducir la entidad en donde tenemos domiciliada nuestra factura, o introducir los 4 últimos dígitos de nuestra cuenta (hmm interesante esto último…).

Aquí ya va mi primer comentario y el resultado de más pruebas realizadas:

  • Necesitamos el DNI (cosa relativamente fácil de conseguir, vease ingeniería social. Además, es obvio que si esto se le hace a alguien, es porque se le conoce).
  • Se puede volver a usar fuerza bruta. Si señores, se puede volver a usar fuerza bruta. Sigue sin haber ningún tipo de expiración por cantidad de veces, captcha, o cualquier tipo de arreglo.

Tras esto, nos vamos al paso 3. El paso 3 anteriormente era el siguiente:

Ahora es este:

¿Diferencia? ninguna. ¿Se puede volver a usar fuerza bruta? Si, se puede.

Conclusión hasta el momento: Han hecho el sistema algo más seguro, siendo necesario ahora el DNI de la víctima. Como dije anteriormente, no lo han arreglado, simplemente han puesto una traba más, que tampoco es nada del otro mundo.

Problema añadido: Si nos fijamos en el paso dos (el antes y el después), a partir de ahora hay que meter los 4 últimos dígitos del número de cuenta. ¿Qué quiere decir esto? Que ya no habrá diferencia entre “titular” y “usuario”, y si logramos entrar, veremos todos los datos sin ningún tipo de impedimento (aunque el que habia antes tampoco es que lo fuera demasiado).

Otras mejoras de seguridad

Con respecto al tema de la fuerza bruta, se han puesto al dia en lo que es el login principal. Solamente nos deja meter un cierto número de intentos, 5 para ser exactos. Y aquí si que realmente no se puede bruteforcear. Sin embargo, repito, el fallo principal no está en el login, sino en la parte de recuperar la password, por lo que todavia queda por arreglar.

Por otra parte, el buscador lo han cambiado (al fin) ya que sufría más de un XSS en distintos argumentos, en el que insistí mucho. Buscador viejo:

Buscador nuevo:

El tema de las Cookies

La verdad es que en el otro post lo mencioné muy por encima porque tampoco queria entrar al tema, ya que no era tan importante como el problema principal. De todos modos, estoy contento de que por lo visto, algún tipo de efecto ha tenido que haber tras hacer la publicación anterior, ya que como dije, en meses no lo habian arreglado, y de repente, 6 dias después de la publicación (justo antes de publicarla volví a comprobar si habian hecho algo nuevo y nada..) me encuentro con que han hecho algo, poco, pero algo.

Principalmente, una de las partes que más me sorprenden de Vodafone, es que guarda la contraseña y el usuario (y el usuario es ni más ni menos que el número de teléfono), en una cookie, de la siguiente forma.

Todo el mundo sabe (o debería) que nunca jamás se debe guardar en una cookie los credenciales, aunque estén encriptados. En el caso de robar una cookie de alguien, podemos obtener su teléfono (punto de ataque) y su contraseña, que aunque esté encriptada, no es difícil de mostrar tras esos asteriscos.

Fallos XSS con los que podriamos robar cookies:
Viejos
Uno
Dos

Todavia persistentes
[Uno] [Enlace]
[Filtro interesante (WAF)] [Filtro Bypasseado] [Imagen] (En varios argumentos de la URL)

Otros:
[Este lo han intentado arreglar de alguna forma.. pero la página nunca termina de cargar]

Animo a que pongais más si los encontrais.

Un saludo, lipman

Nota: han arreglado algunas cosillas, aunque todavia sigue quedando este fallo. Parte 2 del Post.

“Esto” está descubierto y reportado desde hace más de medio año… He intercambiado mails y conversaciones telefónicas con Vodafone y con la propia policia (GDT). Tenia un post explicándolo todo detalladamente además de un PDF que mandé a ambas partes, pero visto que no lo arreglan nunca, no lo voy a publicar. Lo que haré será un mini resumen, y se acabó, ya que quiero olvidarme de este tema completamente.

Antes de nada os hago un spoiler: no es nada del otro mundo. Solo es una muestra de cómo una absurda tonteria, nos permite hacer cosas que no deberiamos. Es más, esto indica que este descuido es realmente grave, ya que cualquiera puede explotarlo.

Empezaré con el debate respecto al título elegido de esta entrada. Ojalá hubiera podido poner “Bug en Vodafone.es…” o “Fallo de seguridad/Vulnerabilidad..”. En fin, múltiples son los adjetivos para ello. Pero no, pongo descuido por no poner incompetencia, ya que guardar en una cookie el nombre de usuario (teléfono) y la contraseña (encripada, pero eso da igual) no es un fallo de programación, no es un bug, no es una vulnerabilidad… es ser un incompetente. Menciono también que tiene XSSs varios, sin ir más lejos, creo recordar que el propio buscador tenía.

Como dije anteriormente, voy a ser breve, y no voy a dar detalles. Solo decir esto: no seas gilipollas.

Como dice el título, este descuido nos permite meternos en la cuenta de usuario a partir únicamente de su número de teléfono. Y si no tiene cuenta, también nos lo permite porque le podemos registrar nosotros mismos.
Uno de los orígenes de este problema, es que si le damos a “olvidar contraseña”, podemos poner el número de teléfono objetivo y nuestra dirección de correo. Nos mandan una clave numerica de 4 digitos al movil para que la introduzcamos y establezcamos una nueva contraseña. Pues bien, podemos hacer fuerza bruta tranquilamente que al final, daremos con esa clave que no puede ser otra que alguna entre 0000 y 9999. Una forma para hacer fuerza bruta sin ser un 5uP3RH4X0R es usar el iMacros para Firefox, haciendo:

SET !LOOP 1000
URL GOTO=http://canalonline.vodafone.es/cpar/do/alta/changePassword?uuid=XXXXXXXX&claveAntigua={{!loop}}&claveNueva=1234&rePassword=1234

(Esta iría desde 1000 hasta 9999, y estableceria como nueva contraseña 1234).
Así que nada, después de esto ya podemos meternos en la cuenta. Pero no podemos acceder a todos los datos, que pena. No podemos porque tenemos que ser titular, y para eso, tenemos que validarnos. ¿Como? Pues hay varias formas. Una de ellas es introduciendo los 4 últimos dígitos de nuestra cuenta bancaria asociada.

¿Otra vez 4 números? Esto me suena de antes… Exacto. iMacros de nuevo. Y claro, si aquí tampoco ponemos nada que nos impida un bruteforce como un captcha o una expiración de la sesión, pues igualmente podemos petarlo. Y efectivamente, se puede.

Datos comprometidos (entre otros tantos): DNI, nombre, dirección postal, factura electrónica (con mas telefonos claro, que a su vez igual tambien son de Vodafone), códigos PIN y PUK (ideal por si robamos un teléfono verdad?)…

Yo flipo con las empresas. Pero sobretodo con su pasotismo a la hora de no arreglar nada, ni contactar conmigo siquiera. En fin…

Conclusiones:
-Se puede bruteforcear todo vodafone.es sin problemas
-Se puede robar una cookie con datos como la contraseña y usuario para suplantarse (ya que presenta varios XSS).
-Poned un puto captcha! de una vez.
-Insisto en que la gravedad de este asunto es que es demasiado fácil realizar esto, no hay que ser un experto ni tener conocimientos de nada.
-Seria curioso saber cuantas leyes se pasan por el forro los de Vodafone, como la de las auditorias (a saber si las hacen siquiera, o si les hacen caso), sin contar con las que hacen mención a que hay que proteger bien los datos.

Dato adicional: Vodafone no es la única compañia de telecomunicaciones cuya identidad de sus usuarios se basa en algo tan simple. Aunque lo de guardar en la cookie las password, todavia me sigue costando creerlo. Ahí lo dejo caer…

Retweetealo!
Mi Twitter

INDICE
0.-Resumen
1.-Introducción
2.-Buscando un algoritmo
3.-Implementando nuestro sistema en WordPress
3.1.-Añadiendo posts a nuestra base de datos
3.1.1.-Analizando la tabla de wp_posts
3.1.2.-Nuestra consulta
3.1.3.-La tabla wp_postmeta
3.2.-Implementando la seguridad en nuestra aplicación
3.3.-Conclusión y funcionamiento final
4.-Códigos finales completos

0.-Resumen

En este post intentaré explicar un método casero para poder escribir en nuestro respectivo blog de WordPress desde cualquier lugar sin tener que preocuparnos en que nos estén analizando el tráfico. Ideal por si estamos en una red que no es la nuestra, como en casa de algún conocido o en un hotel.

1.-Introducción

Una de las responsabilidades que tenemos/tienen los bloggers es de mantener actualizado nuestro blog que tanto queremos, incluso si nos encontramos en otros lugares. Sin embargo, no todos disponemos de 3G y algunos tenemos que ir mendigando WiFi por los hoteles, o en casa de un pariente. Yo, con lo paranoico que soy que incluso uso la versión encriptada de Google, siempre trato de intentar comprometer lo menos posible mis datos.

Si no tenemos puesto SSL en nuestro blog de WordPress, y nos logueamos en una red que puedan tener monitorizada, fácilmente nos sacan nuestro user y pass, por lo que tendremos que buscar una alternativa para loguearnos que sea más segura que nuestra propia cuenta.

2.-Buscando un algoritmo

Una idea que se me ha ocurrido para esto, es identificarnos con un hash que varíe, de forma que si es obtenido por algún tercero, no le sirva para nada. Lo más fácil de recordar que varíe, es el tiempo, así que podriamos usar un algoritmo basado en:

  • Caracteres alfanuméricos.
  • Caracteres especiales.
  • Caracteres que varien automáticamente (en función del tiempo).
  • Caracteres que varien de forma controlada.
  • Mayúsculas y minúsculas.

Un ejemplo podria ser en base al siguiente:
///XXlipmanYY///
En donde XX es el dia del mes, y YY la hora. He elegido este par de números debido a que varian lo suficientemente rápido como para que no se reutilicen, y lo suficientemente lento como para controlarlos. Además de esto, usaremos un truco para añadir un caracter aleatorio fácil de recordar. Dependiendo del dia de la semana (lunes, martes…) teclearemos una tecla debajo de los números, dependiendo del dia que sea. Por ejemplo, cuando sea lunes, pulsamos la Q, cuando sea martes la W… (notese que seria en mayúsculas).

Ejemplo completo:
Lunes 20 a las 8AM: ///20Qlipman8///
Martes 21 a las 15PM: ///21lWipman15///
Viernes 24 a las 2AM: ///24lipmTan2///

Notese que las letras mayúsculas “aleatorias” las vamos alternando en las posiciones entre la palabra “lipman”. Para que quede bien, necesitamos palabras de 6 caracteres.
De aquí también podemos descatar lo imprescindible que es que una contraseña no empiece por números o por letras cercanas a los extremos del alfabeto, para que sea todavia más improbable que un brute force nos descubra la contraseña.

3.-Implementando nuestro sistema en WordPress

Ya tenemos el diseño (respecto a la seguridad) de nuestra aplicación, por lo que queda la parte más entretenida: realizar una aplicación para comunicarnos con WordPress implementando nuestro sistema. Voy a poner solo lo que es esencial: comunicación entre nuestra aplicación y la base de datos para añadir entradas. Por nuestra cuenta podriamos desarrollar más cosas, como una mejor interfaz gráfica, pero esto lo dejaré a parte ya que seguramente dejaré esto como un plugin (ya hablaré más adelante) y haré mejoras en todo.

3.1.-Añadiendo posts a nuestra base de datos

Para nuestra suerte, la base de datos de WordPress (y en general la de cualquier CMS) suele ser sencillita, así que no deberiamos de tener problemas para manejarla.
Lo primero de todo, aprovecharemos el fichero de wp-config.php para conectar a nuestra base de datos. Este fichero es el primero que se genera cuando creamos nuestro sitio en WordPress, y contiene los datos de nuestra base de datos: nombre, usuario, contraseña… Así que le haremos un include.

3.1.1.-Analizando la tabla de wp_posts

Lo interesante de este tipo de situaciones, es analizarlas y aprovecharlas para intentar entender el funcionamiento interior de WordPress, por ello, no me limitaré a hacer, copiar y pegar código simplemente, sino que se intentará explicará todo.

A continuación, vamos a escribir los campos que tendremos que tocar (osease, todos menos los que suelen ir a NULL), explicandolos un poco, sobre todo, los que sean menos obvios.

Nombre Comentario
ID Id (PK) del post
post_author ID del autor
post_date Fecha de escritura
post_date_gmt Fecha de escritura (GMT)
post_content Contenido del post
post_title Titulo
post_status Estado: publicado, borrador..
comment_status Permitir comentarios
ping_status Permitir pingback
post_name Nombre parseado (*)
post_modified Fecha de modificación
post_modified_gmt Fecha de modificación (GMT)
post_parent A quien pertenece (*)
guid URL parseada (*)
menu_order Orden: 0
post_type Indica si es un post
comment_count Contador de comentarios

-Nombre parseado: Se obtiene en función del titulo. Si tenemos el siguiente titulo: “Hola Mundo”, obtendremos: “hola-mundo”. Osease, lo que aparece (si lo tenemos configurado así) de enlace.

-A quien pertenece: Esto solo hace referencia a los borradores y demás. Con respecto a los posts publicados, ni caso.

-URL parseada: Esta seria la URL del post en el caso de tenerlo configurado de manera que se viera la ID en la URL. Un ejemplo, en el caso de delanover, si escribiesemos un post con ID 1234, este campo seria: http://delanover.com/?p=1234

3.1.2.-Nuestra consulta

De momento, llevamos lo siguiente:

//Incluimos los datos de configuración de nuestra base de datos
include('wp-config.php');
 
mysql_connect(DB_HOST, DB_USER, DB_PASSWORD) or die("Error al conectar");
 
//Creamos la consulta
$consulta_principal = "INSERT INTO `wp_posts`(`ID`, `post_author`, `post_date`, `post_date_gmt`,
	`post_content`, `post_title`, `post_status`, `comment_status`, `ping_status`,
	`post_name`,`post_modified`, `post_modified_gmt`,
	`post_parent`, `guid`, `menu_order`, `post_type`, `comment_count`) VALUES
	('$id', 1,$fecha,$fecha_gmt,'$contenido','$titulo','publish','open','open',
	'$titulo_parseado',$fecha,$fecha_gmt,0,'$id_parseada',0,'post',0)";
 
$resultado_principal = mysql_query($consulta_principal);

Como podemos observar en nuestra consulta, hay variables y valores constantes. Me limitaré a contar un poco las variables al igual que la forma de obtenerlas, ya que los valores constantes son un tanto redundantes.

-ID: Es la ID que tendrá nuestro post. Esta ID se consigue obteniendo el valor máximo de todas las IDs que ya hay, incrementando su valor en uno, de la siguiente manera:

SELECT MAX(ID) from `wp_posts`

-Fecha: Es la fecha de creación de nuestra entrada. Tiene un formato específico y estricto que deberemos seguir para que nos funcione correctamente. El formato es el siguiente: AAAA-MM-DD HH:MM:SS
Obtendremos este formato de la siguiente manera:

$fecha = "DATE '" . date("Y-n-j H:i:s",time()) . "'";

Nota: notese que hay que concatenar “DATE ‘” a nuestra fecha, para que a la hora de introducirlo a la BD lo reconozca como tal.

-FechaGMT: Lo mismo que el anterior, incrementando +2 horas. Todo esto de las fechas, depende totalmente de donde nos encontramos.

$fecha_gmt = "DATE '" . date("Y-n-j ",time()) . (date("H",time())+2) . date(":i:s",time()) . "'";

-Contenido y Titulo: Este par de campos, sencillamente son lo que escribimos de titulo y contenido, por lo que no hay que tratar demasiado.

-ID parseada: Como comenté anteriormente, no es muy dificil de conseguir, simplemente seria concatenando una constante a la ID:

$id_parseada = "http://delanover.com/test_wordpss/?p=" . $id;

-Titulo parseado: Esta la he dejado para el final ya que es la más largilla de hacer, para la cual he creado una función específica. En principio, al ser el enlace, lo unico que puede contener son letras (quitaré las tildes), numeros, guiones bajos y guiones. Por lo que haré lo siguiente:

$titulo_parseado = parsear_titulo($titulo);
 
function parsear_titulo($titulo){
  //pasamos a minusculas y cambiamos caracteres
  $titulo = strtolower($titulo);
  $titulo = str_replace(" ", "-", $titulo);
  $titulo = str_replace("á", "a", $titulo);
  $titulo = str_replace("é", "e", $titulo);
  $titulo = str_replace("í", "i", $titulo);
  $titulo = str_replace("ó", "o", $titulo);
  $titulo = str_replace("ú", "u", $titulo);
 
  $caracteres_permitidos = array("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "ñ", "o", "p",
  			"q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "1", "2", "3", "4", "5", "6", "7", "8", "9",
  			"0", "_", "-");
 
  //Si nos encontramos con un caracter no permitido (que no salga en el array anterior), lo eliminamos
  for($a=0;$a<strlen($titulo);$a++){
     if(!in_array($titulo[$a], $caracteres_permitidos)){
       $titulo[$a] = "";
       }
  }
 
  return $titulo;
}

3.1.3.-La tabla wp_postmeta

Afortunadamente para nosotros, el tratamiento de esta tabla será todavia más sencillo, y limitaré mi explicación por no tener demasiado que ver con el tema principal.

Explicaré brevemente los detalles dentro del código fuente:

 
//Obtenemos el ID maximo
$consulta_metapost = "SELECT MAX(meta_id) from `wp_postmeta`";
$respuesta_metapost= mysql_query($consulta_metapost);
if($resultado=mysql_fetch_array($respuesta_metapost))
	$_id = $resultado[0]+1;
 
//Introducimos el ID recogido, el ID anterior que teniamos del post, y dos valores constantes
$consulta2 = "INSERT INTO `wp_postmeta`(`meta_id`, `post_id`, `meta_key`,
`meta_value`) VALUES ($_id,$id,'_edit_last',1)";
$resultado_consulta2 = mysql_query($consulta2);
 
$_id++; //Aumentamos el ID ya que vamos a insertar otra fila
//Obtenemos un valor que meteremos, compuesto por el tiempo y el ID del autor
$meta_valor = time() . ":1";
$consulta3 = "INSERT INTO `wp_postmeta`(`meta_id`, `post_id`, `meta_key`,
`meta_value`) VALUES ($_id,$id,'_edit_lock','$meta_valor')";
$resultado_consulta3 = mysql_query($consulta3);

3.2.-Implementando la seguridad en nuestra aplicación

Muy bien, con todo esto ya deberia de funcionarnos el sistema, pero claro, falta lo más importante, implementar la seguridad con ese hash dinámico que generamos.

Lo más sencillo es crear una función que nos devuelva un valor booleano, en función de si el hash introducido es verdadero (entonces se ejecuta) o falso (devolviendo un error).

function comprobar_hash($hash){
$hora = date("H", time())+6; //Obtenemos la hora (la adecuamos en función de la hora del servidor a la hora de nuestro pais)
$dia = date("j", time()); //Obtenemos el dia
 
//Nuestro salt
$cadena = "lipman";
 
//En función del dia, generamos un resultado u otro
switch(date("N", time())){
  case 1:
  $nueva_cadena = "Q" . $cadena[0] . $cadena[1] . $cadena[2] . $cadena[3] . $cadena[4] . $cadena[5];
  break;
  case 2: $nueva_cadena = $cadena[0] . "W" . $cadena[1] . $cadena[2] . $cadena[3] . $cadena[4] . $cadena[5]; break;
  case 3: $nueva_cadena = $cadena[0] . $cadena[1] . "E" . $cadena[2] . $cadena[3] . $cadena[4] . $cadena[5]; break;
  case 4: $nueva_cadena = $cadena[0] . $cadena[1] . $cadena[2] . "R" . $cadena[3] . $cadena[4] . $cadena[5]; break;
  case 5: $nueva_cadena = $cadena[0] . $cadena[1] . $cadena[2] . $cadena[3] . "T" . $cadena[4] . $cadena[5]; break;
  case 6: $nueva_cadena = $cadena[0] . $cadena[1] . $cadena[2] . $cadena[3] . $cadena[4] . "Y" . $cadena[5]; break;
  case 7: $nueva_cadena = $cadena[0] . $cadena[1] . $cadena[2] . $cadena[3] . $cadena[4] . $cadena[5] . "U"; break;
  default:
  	$nueva_cadena = "error";
 
}
 
//Obtenemos la cadena formada y la pasamos a MD5
$resultado = "///" . $dia . $nueva_cadena . $hora . "///";
$resultado = md5($resultado);
 
//Finalmente comprobamos si coincide con el hash pasado por parámetro
if($resultado==$hash)
	$final = "Verdadero";
else
	$final = "Falso";
 
return $final;
}

3.3.-Conclusión y funcionamiento final

Nos falta diseñar la página de “login” en la que tendriamos que recoger el titulo de la entrada, el contenido, y el hash en MD5. Este hash en MD5 recordemos que es nuestra contraseña aleatoria pasada a MD5. Un apunte respecto a esto: imaginemos que nos están esnifando la red y tal. Vale, usamos este sistema y todos felices, pero si a la hora de crear nuestro hash MD5 (para que posteriormente lo valide) usamos una herramienta externa en una página web, nos esnifan esto, y no tiene mucho sentido.

Para ello, recomiendo que tengais un programa o algo, ya que desde la consola de Windows, a diferencia de la Linux, no se puede obtener el MD5 de una cadena. Si no, si teneis un servidor web instalado, lo haceis desde ahí usando la función de PHP “md5″.

4.-Códigos finales completos

crear.html

<html>
 
 
<form action="create.php" method="POST">
Metemos el hash
<input type="text" name="hash"><br><br>
 
Titulo
<input type="text" name="titulo"><br><br>
 
Contenido<br>
<textarea name="contenido">
 
</textarea>
<input type="submit" name="Aceptar">
</form>
 
</html>

create.php

<?
 
//Recuperamos el hash
$hash = $_POST['hash'];
 
 
$postear = comprobar_hash($hash);
 
 
if($postear=="Verdadero")
{	//Incluimos las variables para conectarnos a la base de datos
	include('wp-config.php');
 
	//Recogemos el contenido y titulo del post
	$titulo = $_POST['titulo'];
	$contenido = $_POST['contenido'];
 
	mysql_connect(DB_HOST, DB_USER, DB_PASSWORD) or die("Error al conectar");
 
	//Obtenemos el ID que del nuevo post
	$consulta = "SELECT MAX(ID) from `wp_posts`";
	$respuesta= mysql_query($consulta);
	if($resultado=mysql_fetch_array($respuesta))
		$id = $resultado[0]+1;
 
 
	//Obtenemos las fechas
	$fecha = "DATE '" . date("Y-n-j H:i:s",time()) . "'";
	$fecha_gmt = "DATE '" . date("Y-n-j ",time()) . (date("H",time())+2) . date(":i:s",time()) . "'";
 
	//Parseamos el titulo
	$titulo_parseado = parsear_titulo($titulo);
	$id_parseada = "http://delanover.com/test_wordpss/?p=" . $id;
 
 
	//Realizamos la consulta principal
	$consulta_principal = "INSERT INTO `wp_posts`(`ID`, `post_author`, `post_date`, `post_date_gmt`,
	`post_content`, `post_title`, `post_status`, `comment_status`, `ping_status`,
	`post_name`,`post_modified`, `post_modified_gmt`,
	`post_parent`, `guid`, `menu_order`, `post_type`, `comment_count`) VALUES
	('$id', 1,$fecha,$fecha_gmt,'$contenido','$titulo','publish','open','open',
	'$titulo_parseado',$fecha,$fecha_gmt,0,'$id_parseada',0,'post',0)";
	$resultado_principal = mysql_query($consulta_principal);
 
	//=====PARTE DOS======\\
	//Obtenemos el ID de la otra tabla
	$consulta_metapost = "SELECT MAX(meta_id) from `wp_postmeta`";
	$respuesta_metapost= mysql_query($consulta_metapost);
	if($resultado=mysql_fetch_array($respuesta_metapost))
		$_id = $resultado[0]+1;
 
	//Realizamos las dos consultas
	$consulta2 = "INSERT INTO `wp_postmeta`(`meta_id`, `post_id`, `meta_key`,
	`meta_value`) VALUES ($_id,$id,'_edit_last',1)";
	$resultado_consulta2 = mysql_query($consulta2);
 
	$_id++;
	$meta_valor = time() . ":1";
	$consulta3 = "INSERT INTO `wp_postmeta`(`meta_id`, `post_id`, `meta_key`,
	`meta_value`) VALUES ($_id,$id,'_edit_lock','$meta_valor')";
	$resultado_consulta3 = mysql_query($consulta3);
 
	//Si todo va bien, que muestre el mensaje
	if($resultado_principal && $resultado_consulta2 && $resultado_consulta3)
		echo "Se ha realizado todo correctamente";
	else
		echo "Ha ocurrido algún error";
 
	mysql_close();
}
else
	echo "<br>error<br>";
 
 
function parsear_titulo($titulo){
  //Pasamos a minusculas y quitamos las tildes
  $titulo = strtolower($titulo);
  $titulo = str_replace(" ", "-", $titulo);
  $titulo = str_replace("á", "a", $titulo);
  $titulo = str_replace("é", "e", $titulo);
  $titulo = str_replace("í", "i", $titulo);
  $titulo = str_replace("ó", "o", $titulo);
  $titulo = str_replace("ú", "u", $titulo);
 
  $caracteres_permitidos = array("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "ñ", "o", "p",
  			"q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "1", "2", "3", "4", "5", "6", "7", "8", "9",
  			"0", "_", "-");
 
  //Si encontramos un caracter que no está en el array de permitidos, lo eliminamos
  for($a=0;$a<strlen($titulo);$a++){
     if(!in_array($titulo[$a], $caracteres_permitidos)){
       $titulo[$a] = "";
       }
  }
 
  return $titulo;
}
 
 
function comprobar_hash($hash){
  //Obtenemos la hora (la adecuamos en función de la hora del servidor a la hora de nuestro pais)
  $hora = date("H", time())+6; 
  $dia = date("j", time()); //Obtenemos el dia
 
  $cadena = "lipman";
 
  switch(date("N", time())){
    case 1: $nueva_cadena = "Q" . $cadena[0] . $cadena[1] . $cadena[2] . $cadena[3] . $cadena[4] . $cadena[5]; break;
    case 2: $nueva_cadena = $cadena[0] . "W" . $cadena[1] . $cadena[2] . $cadena[3] . $cadena[4] . $cadena[5]; break;
    case 3: $nueva_cadena = $cadena[0] . $cadena[1] . "E" . $cadena[2] . $cadena[3] . $cadena[4] . $cadena[5]; break;
    case 4: $nueva_cadena = $cadena[0] . $cadena[1] . $cadena[2] . "R" . $cadena[3] . $cadena[4] . $cadena[5]; break;
    case 5: $nueva_cadena = $cadena[0] . $cadena[1] . $cadena[2] . $cadena[3] . "T" . $cadena[4] . $cadena[5]; break;
    case 6: $nueva_cadena = $cadena[0] . $cadena[1] . $cadena[2] . $cadena[3] . $cadena[4] . "Y" . $cadena[5]; break;
    case 7: $nueva_cadena = $cadena[0] . $cadena[1] . $cadena[2] . $cadena[3] . $cadena[4] . $cadena[5] . "U"; break;
    default:
  	$nueva_cadena = "error";
 
  }
 
  //RESULTADO: ///XXlipmanYY///
  $resultado = "///" . $dia . $nueva_cadena . $hora . "///";
  $resultado = md5($resultado);
 
  //Si coincide el resultado generado y el hash pasado como parámetro, es verdadero
  if($resultado==$hash)
	$final = "Verdadero";
  else
	$final = "Falso";
 
  return $final;
}
 
?>
Este es mi primer artículo en delanover.com quisiera antes que nada presentarme y decirles que estaré publicando artículos y noticias sobre las temáticas del blog y espero sea de su agrado.

Hasta hace muy poco, escuchar Google Dart era como el viento de una colina… nadie le prestaba atención, y no es para menos. ¿Un lenguaje de programación de Google? ¿En qué estaban pensando? Estas y otras muchas preguntas llegaron en función del aumento de rumores respecto al mismo, pero a estas alturas, todo ha cambiado…

…ya que Google Dart, presentado durante el pasado mes de octubre, está empezando a ganar una interesante popularidad en el sector de los lenguajes de programación. Tanto es así, que muchos comienzan a verlo como una hipotética alternativa a Javascript.

Dart se postula exactamente como eso. Una opción más que Javascript como un lenguaje para navegadores web, más actualizadomoderno e interactivo que un más que veterano Javascript.
¿Realmente tiene posibilidades de llegar a su altura? Con la llegada del próximo año 2012, Google comenzará a darle un protagonismo mucho mayor a Dart, incluyendo un compilador y una máquina virtual para su navegador, Chrome. Pero yendo más allá, la noticia más interesante que podemos decir de este lenguaje es que de cara a las listas, está ganando popularidad a ritmos insospechados.

El aumento de popularidad es muy posible que se deba a por supuesto, la influencia de Google en todo Internet. Si de verdad los de Mountain View tienen grandes expectativas para Dart, muchos programadores web no tardarán en tomar sus apuntes, y comenzar a pensar en la posibilidad de tomar parte con Dart en lugar de Javascript. Aunque para esto, falta mucho, mucho tiempo…