Delanover

Blog sobre Informática y Seguridad

Artículos publicados por 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;
}
 
?>

No es una novedad, y existe desde hace mucho tiempo, pero siempre he querido hacer un post dedicado a esto, y dedicado a los que tenemos cuentas largas e incómodas de dar al público para cosas serias, y además de eso, usar varias y diferentes cuentas, incluso la de la universidad.

Alias en Hotmail

Voy a empezar por hablar de los alias en Hotmail.com. Desde hace bastantes años, llevo usando una cuenta de correo en hotmail que combina el ser bastante larga, con el ser bastante lol.

Todo esto ocasiona algunos problemas en el dia a dia: a la hora de registrarse en sitios teclear una dirección tan larga cansa más, a la hora de rellenar formularios impresos en papel con tu correo incluso ha llegado a no caberme el correo electrónico en el espacio de papel permitido. También he aprendido que cuando das tu dirección de correo en persona o por teléfono, es más tedioso, incluso puede algunos caracteres se puedan confundir (guiones con guiones bajos por ejemplo), y multitud de ejemplos.

Crearnos un alias en Hotmail nos permite asociar una nueva dirección para poder ver los mensajes que se reciben en esta en nuestro correo normal. De la misma manera, podemos escribir mensajes desde nuestro correo normal, poniendo de remitente el alias. ¿Qué ventajas obtenemos con esto? En mi caso, al tener un correo largo, me puedo crear un alias más corto para poder registrarme en sitios, y que los correos de registro me lleguen directamente a otra carpeta, separada de la principal. Vamos a probar a configurarlo:

Le damos a “Crear un alias de Hotmail”, y elegimos nuestro nuevo alias.

Tras esto, seleccionamos si queremos crear una nueva carpeta para que ahí se redigiran los correos llegados, y ya está. Un momento, porqué no me funciona?? Claro, a Hotmail se le olvidó decirnos que nos lo tienen que activar. Tardan unas horas (a mi me tardaron unas 10 o así) en activarlo, y cuando lo hacen, te mandan un correo del estilo.

Sincronizar diferentes cuentas de correo en GMail

También soy de las personas que tienen varios correos y los usan, por lo que la sincronización con GMail me ha venido bastante bien.

Para empezar vamos a crear las etiquetas, cuyo nombre (en mi caso) serán el nombre de cada correo, para así tener un orden sencillito.

Posteriormente, vamos a “Configuración del correo”, y nos vamos a “Cuentas e Importación”, y en la parte de “Comprobar correo mediante POP3″, le damos a “Añadir cuenta de correo electrónico”

Ahí ya ponemos finalmente el correo, la contraseña, y seleccionamos los checkboxes de “Usar SSL” y “Etiquetar los mensajes entrantes”, a lo que seleccionaremos la etiqueta que creamos anteriormente.

Ahora bien, ya lo tenemos configurado, solo un par de aclaraciones.

  • Podemos poner cualquier correo, yo tengo dos de hotmail y uno de mi universidad.
  • Es un proceso que requiere actualización no inmediata, osea que puede que tarde en verse reflejado los correos. Igualmente, se le puede dar a “Comprobar correo electrónico” para ver si tenemos algo nuevo.
  • Cuando eliminamos un correo importado a nuestro GMail, se elimina en la cuenta. Si queremos que se mantenga, seleccionaremos el primer checkbox de la configuración.

Otro post más acerca de Twitter.. debe ser que estoy tan enganchado que no puedo pensar en otra cosa. Esta vez, quisiera hablar de los identificadores a la vez que averiguamos el contenido de un tweet (que, a pesar de lo que pueda parecer, no es poco precisamente).

Los identificadores numéricos nos permiten poner un orden a nuestra base de datos usándolos como Primary Key, sin embargo el usuario normal no necesita conocerlos para nada, así que no es un dato explícito tal y como lo sería nuestro nick en un foro por ejemplo.

Primero de todo, vamos a obtener el ID de un tweet, que es un procedimiento (si se puede llamar así) bastante sencillo, y para ello, hay que poner el ratón sobre el indicador del tiempo de cúando se envió el tweet.

Ahora sencillamente, mediante cualquier herramienta con la que podamos usar cURL (ya sea desde la consola de Linux o desde el Cygwin con Windows, o con PHP..) o incluso poniendo la URL en nuestro navegador (que nos pedirá de descargar un archivo .json el cual podremos abrir con cualquier editor de texto) hacemos una petición a al siguiente enlace: http://api.twitter.com/1/statuses/show.json?id=XXXXXXXXXXXXXX en donde XXXX.. es la ID del tweet.

Nos devolverá el siguiente resultado:
{“geo”:null
“coordinates”:null
“retweeted”:false
“in_reply_to_status_id_str”:null
“in_reply_to_user_id_str”:null
“retweet_count”:0
“contributors”:null
“user”:
—{“follow_request_sent”:false
—”verified”:false
—”profile_background_image_url_https”:”https:\/\/si0.twimg.com\/images\/themes\/theme1\/bg.png”
—”profile_link_color”:”0084B4″
—”protected”:false
—”following”:false
—”profile_sidebar_border_color”:”C0DEED”
—”followers_count”:106
—”location”:”Burgos, Espa\u00f1a”
—”name”:”Juan Miguel Lipman”
—”default_profile”:true
—”favourites_count”:10
—”profile_use_background_image”:true
—”utc_offset”:3600
—”url”:”http:\/\/delanover.com”
—”description”:”Otaku. Computer Engineering student. PHP+MySQL Developer. Fedora user. Rammstein lover (as EBM, NDH and Melodic Death Metal music).”
—”listed_count”:6 —”time_zone”:”Madrid”
—”profile_background_color”:”C0DEED”
—”screen_name”:”jmlipman”
—”contributors_enabled”:false
—”notifications”:false
—”profile_background_image_url”:”http:\/\/a0.twimg.com\/images\/themes\/theme1\/bg.png”
—”id_str”:”103288301″
—”show_all_inline_media”:false
—”geo_enabled”:true
—”lang”:”es”
—”created_at”:”Sat Jan 09 14:55:42 +0000 2010″
—”profile_text_color”:”333333″
—”default_profile_image”:false
—”profile_sidebar_fill_color”:”DDEEF6″
—”profile_image_url”:”http:\/\/a1.twimg.com\/profile_images\/1307866230\/MWSnap062_normal.jpg”
—”statuses_count”:9368
—”profile_background_tile”:false
—”friends_count”:84
—”profile_image_url_https”:”https:\/\/si0.twimg.com\/profile_images\/1307866230\/MWSnap062_normal.jpg”
—”id”:103288301
—”is_translator”:false
}
“in_reply_to_user_id”:null
“in_reply_to_status_id”:null
“id_str”:”118319553267761152″
“truncated”:false
“created_at”:”Mon Sep 26 13:42:34 +0000 2011″
“place”:null
“favorited”:false
“source”:”web”
“id”:118319553267761152
“in_reply_to_screen_name”:null
“text”:”Tweet de prueba para un post sobre Twitter en #Delanover”
}

Igual después de ver todo esto entendemos la cantidad de herramientas que hay para twitter que te dicen cosas como de dónde son tus followers o cuanto tiempo de antigüedad tiene la cuenta de twitter.

Para obtener el los datos de un usuario dado una ID (del propio usuario obviamente) simplemente tendriamos que mandar una petición del tipo: http://api.twitter.com/1/users/show.json?id=XXXXXXX.

Y para recorrer el camino inverso, es decir, obtener el nombre de usuario a partir de una ID, simplemente sería cambiar el ID de antes por ‘screen_name=nick’ de forma que quedaria: http://api.twitter.com/1/users/show.json?screen_name=NICK

En general, disponemos de un listado interesante de peticiones que podemos realizar, que como dije es el que usan muchas aplicaciones, justo aquí.

Parte 1
Parte 2

En relación al post acerca de la seguridad de nuestros tweets pudiendo ser atacados por un MitM, he decidido analizar el tráfico de datos generado por cada una de las cuatro aplicaciones que usaban SSL para transmitir los tweets y alguna otra información. La verdad es que me he llevado una sorpresa un tanto desagradable, puesto que no hay ninguna que sea segura en su totalidad.

Las aplicaciones analizadas son: Twitter (Oficial), TweetDeck, Seesmic y HootSuit. Tienen en común estas aplicaciones, que se pueden acceder a ellas y ver los tweets cargados anteriormente, junto con lo que esto conlleva (avatares, biografias…). Esto quiere decir que esta información está guardada dentro del teléfono y cada vez que nos conectamos a Internet se va actualizando y reemplazando. Esto es un tanto obvio la verdad. Lo que también deberia ser obvio, es que para el transporte de estos datos, de Internet al telefono, se hiciese todo mediante el protocolo seguro y no es así.

Por un lado, las cuatro aplicaciones cargan los avatares que posteriormente son guardados en el teléfono sin usar SSL, así que con un MitM podriamos sacar todos los avatares.

La otra falta de seguridad que comparten las cuatro aplicaciones son que, si subimos una imagen desde la aplicación para twittearla junto con nuestro estado, esta imagen también se puede recuperar al realizar un ataque MitM y cualquiera que esté escuchando, podria obtenerla, al contrario que en la versión web de Twitter, que si subimos una imagen, no se puede obtener (en la versión segura claro está).

Twitter (Oficial)

Como anteriormente dije, se pueden obtener los avatares que se cargan en la aplicación:

Cabe destacar que la recuperación de tweets, privados, menciones, búsquedas, listas, y todo en general, se hace a través de SSL, por lo que no podrán leer lo que escribimos o recibimos.

Sin embargo, como anteriormente también dije, si que podemos recuperar una imagen que subamos a Twitter directamente desde la aplicación, como podemos ver a continuación:

Finalmente, añadir que otro dato que también podemos recuperar con total precisión, es la geolocalización, es decir, la localización que se recupera al usar el propio GPS del teléfono móvil para posteriormente incluirla en los tweets. Como podemos ver, recuperamos las coordenadas que luego las ponemos en GMaps y tan tranquilamente vemos el sitio, aunque ciertamente poco sentido tiene si esto se realiza en un MitM puesto que al realizarlo en un entorno controlado, ya sabemos donde está.

TweetDeck

Al sincronizar todo por primera vez, como con todas las aplicaciones, se transfieren los avatares, incluso podemos ver que llega un paquete cuyo host es: tracking.tweetdeck.com y realiza una petición GET a la siguiente URL: /track/add_account?cl=android&tw=103288301&tz=120&v=2 de la obtenemos el número identificador de la cuenta de twitter (se hablará sobre esto en otra entrada).

Al actualizar la timeline, tweets de perfiles, privados y demás, se realiza todo mediante SSL, aunque cada 15 minutos (configurable) al actualizarse automáticamente, podemos interceptar un paquete sin tampoco demasiada importancia aunque con ciertos datos, cuyo contenido también es una petición GET de URL /track/ping?android-model=MT15i&android-sdk=2.3.3&cl=android&interval=900&tw=103288301&tz=120&v=2&ver=1.0.7.3. Aparecen el identificador, el modelo, versión de Android y el intervalo de tiempo.

Por otro lado, al subir una imagen, podemos recuperarla al igual que con la aplicación anterior, pero no solo eso, sino que también disponemos del link de la subida que se ha generado, como podemos ver:

Otra característica curiosa que tiene TweetDeck es la posibilidad de traducir tweets o biografias, pero esto tampoco pasa por SSL y es totalmente transparente, por lo que podemos ver el mensaje traducido y el original:

Por último, al agregar y desagregar de favoritos, recibimos los identificadores de los tweets que nos sirven para saber qué tweet hemos añadido o no, también en texto plano.

Como podemos ver, tenemos el identificador del tweet 104311621911982080. De esto también se hablará próximamente.

Seesmic

Al sincronizar por primera vez nuestra cuenta de twitter, además de recoger los avatares de los usuarios, podemos obtener nuestra descripción y último tweet. Al subir una imagen, además de poder recuperarla como en las demás aplicaciones, podemos ver el enlace generado junto con nuestro nombre de usuario e identificador.

Por otra parte, en un paquete de datos, vemos que alguna información es guardada en la siguiente ruta de nuestro teléfono: /sdcard/ANdroid/data/com.seesmic/stats.txt

HootSuit

Esta, es la más insegura de las cuatro sin lugar a dudas: cierto es que los tweets y privados que enviamos se hace a través de la capa segura, pero al actualizar de forma automática (cosa que hace cada 300 segundos) o de forma manual, son totalmente visibles los tweets de nuestro timeline, de nuestro usuario, y nuestros privados. Además, al sincronizar por primera vez también aparecen algunas cookies interesantes junto con nuestra descripción.

Y por supuesto, al subir alguna imagen, también la podemos obtener junto con el enlace en donde se ha subido:

Conclusión

Tristemente, no hay ninguna aplicación segura en su totalidad, pero si de alguna manera tuvieramos que ordenarlas por orden de más seguro a inseguro, seria el siguiente:

Twitter (Oficial) > Seesmic > TweetDeck > HootSuit

Resumen:
–>Todos:
-Recuperación de avatares.
-Recuperación de imágenes subidas al enviar tweet.

–>Twitter (Oficial):
-Recuperación de coordenadas al usar el GPS para ubicarnos.

–>TweetDeck
-Enlace de la imagen subida
-Sistema Operativo, versión y modelo del teléfono.
-ID del tweet que faveamos o desfaveamos.
-Nuestro ID identificador de twitter.
-Obtención de los tweets que traducimos (ambos, el original y el traducido).

–>Seesmic
-Enlace de la imagen subida.
-Nuestro ID identificador de twitter.
-Nuestro nombre de usuario de twitter.
-Sistema Operativo, versión y modelo del teléfono.

–>HootSuit
-Obtención de cookies interesantes.
-Enlace de la imagen subida.
-Obtención de los tweets de nuestro timeline, perfil y privados (junto con información de los usuarios).

Un saludo, lipman