25.7.11

Corregir "warning" del timezone en PHP 5.3

Si actualizaron PHP en su servidor y ven millones de errores del timezone como este:

PHP Warning: mktime(): It is not safe to rely on the system's timezone settings. You 
are *required* to use the date.timezone setting or the date_default_timezone_set() function.
In case you used any of those methods and you are still getting this warning, you most likely
misspelled the timezone identifier. We selected 'America/Buenos_Aires' for 'EDT/-3.0/DST'
instead in page.php on line 1

Van a tener que configurar el parametro date.timezone en el archivo php.ini que este usando su servidor web (en mi caso esta en /etc/php.ini) y agregarle la zona correspondiente.

;;;;;;;;;;;;;;;;;;;
; Module Settings ;
;;;;;;;;;;;;;;;;;;;

[Date]
; Defines the default timezone used by the date functions
; http://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone
date.timezone = America/Buenos_Aires

Si no saben en donde esta el archivo php.ini que tienen que modificar, pueden crear un archivo PHP con este codigo:

<?php phpinfo(); ?>

Y acceder a dicho archivo desde el navegador. Ahi van a encontrar la ruta al archivo php.ini del cual necesitan modificar el timezone.

19.7.11

Enumerando usuarios de WordPress

Cuando empeze desarrollar y probar wpbf me di cuenta que necesitaba nombres de usuario válidos para realizar los ataques de fuerza bruta. En un principio buscaba en el contenido del blog links que hacian referencia a las páginas de autor hasta que di con el advisory de Veronica Valeros (TALSOFT-2011-0526) que permite automatizar la enumeración de usuarios a traves de una redicción (segun el advisory, esta presente en versiones de WordPress 2.6, 3.1, 3.1.1, 3.1.3 y 3.2-beta2).

Los usuarios enumerados pueden ser verificados/validados (para filtrar falsos positivos) desde el formulario de ingreso de usuarios (wp-login.php) cuyo mensaje de error diferencia entre usuarios válidos e inválidos.

Redirección

Esta técnica funciona en muchas instalaciones de WordPress (actualizadas o no). Para saber si un blog es vulnerable basta con ingresar a la siguiente página en el blog:

http://www.miblog.com.ar/?author=2

En caso de que exista un usuario cuyo ID sea "2", la redirección nos revela el nombre de usuario "pepito":

http://www.miblog.com.ar/author/pepito/

La idea general es ir incrementando el IDs de usuario hasta obtener todos los usuarios. Algo importante es no detenerse cuando no encontremos un usuario, ya que es común que algunos usuarios hayan sido eliminados y exista un "vacio" en la secuencia de IDs de usuarios.

Pagina del autor

Pero, ¿qué pasa cuando no se hace la redirección? Como bien dice el advisory, versiones recientes de WordPress solucionan el problema de la redirección pero el nombre de usuario sigue presente en las paginas de autor de cada usuario. En esta pagina se deberían listar todos los posts de un autor en particular, y si bien el template puede estar modificado para no incluir un link al autor (href="/author/pepito/") la etiqueta "title" suele comenzar con el nombre de usuario.

<title>pepito | Titulo de mi blog</title>

En muy pocos casos cambia la posición del nombre de usuario pero, en caso de que cambie, se podria comparar el contenido del titulo de varias paginas de autor y encontrar cuales son las palabras que se repiten en la mayoría de los casos. Las palabras que cambian representarian los nombres de los autores.

Otros métodos

Nos queda buscar en el contenido del blog referencias a la pagina de autor en las firmas de los posts. Acá dependemos del tema/template elegido por el administrador del blog y hay una gran posibilidad que no encontremos todos los usuarios (como, por ejemplo, un usuario que no escribió un post en ese blog). Un link a una página de autor seria algo así:

<a title="View all posts by admin" href="http://www.miblog.com.ar/?author=1" class="url fn n">admin</a>

¿En que versiones funciona esto?

Se suponía que la versión 3.1.3 solucionaba el problema del redirect, pero en mis pruebas tengo resultados dispares. En algunos blogs cuya versión es la misma, para uno funciona el redirect y para el otro no (en ambos casos, la enumeración es exitosa).

Estas son las versiones que pude probar:

WordPress 2.6.1 : redirect
WordPress 2.7 : author-title
WordPress 2.7.1 : author-title
WordPress 2.8.4 : author-title
WordPress 2.9.2 : author-title
WordPress 3.0.2 : author-title
WordPress 3.0.3 : author-title
WordPress 3.0.4 : redirect
WordPress 3.1.2 : author-title
WordPress 3.1.3 : redirect
WordPress 3.2 : redirect
WordPress 3.2.1 : redirect / author-title

Si quieren hacer pruebas enumerando usuarios de su blog automaticamente, pueden utilizar wpbf o el plugin wordpress_enumerate_users.py del framework de explotacion web w3af.

1.7.11

BruteForce en WordPress con wpbf

Una de las aplicaciones web que mas se esta usando para armar sitios es WordPress. Como muchas otras aplicaciones web, su instalacion por defecto, es vulnerable a ataques de fuerza bruta.


Auditando contraseñas debiles

Utilizando un password "fuerte" (largo, que incluya numeros, letras y no se predecible), sumado a la latencia de la red (no pudiendo probar tantos passwords por segundo) hacemos que un ataque de fuerza bruta sea impractico. Pero la experiencia nos demuestra que muchos usuarios no suelen preocuparse mucho por la complejidad de sus contraseñas, mas bien piensan "quien va a intentar "hackear" a mi blog?". Lo cierto es que este tipo de ataques pueden automatizarse y quiza a nadie le interese "hackear" tu blog especificamente, pero si puede interesarle a alguien tener un espacio en un hosting en donde alojar scripts (malware, botnets, etc) o contenido (imagenes, musica, peliculas, etc) sin tu permiso.

Habiendo dejado en claro que para un ataque practico sea practico debemos buscar passwords cortas y predecibles, podemos utilizar la herramienta wpbf (WordPress BruteForce) con un diccionario chiquito y su opcion por defecto de utilizar keywords del blog como contraseñas.


La herramienta

El wpbf esta desarrollado en Python bajo licencia GPL y su codigo es accesible a traves del repositorio en GitHub de wpbf. Entre sus caracteristicas principales podemos destacar:

  • Soporte para threads (hilos) que hacen mas rapida las pruebas con diccionarios grandes

  • Utilizacion de palabras clave del sitio en la lista contraseñas

  • Enumeracion y deteccion de usuarios

  • Soporte para proxy HTTP

  • Utilizacion de la libreria logging de Python permitiendo registro avanzado y configurable

Una vez descargada, la descomprimimos en un directorio y ya podemos comenzar a utilizarla: no tiene dependencias mas que la libreria estandar de Python e incluye un pequeño diccionario de pruebas.

Vamos un ejemplo sobre un blog de prueba ejecutando el script sin ninguna opcion:


$ ./wpbf.py http://localhost/wordpress/
2011-07-01 18:33:03,757 - wpbf - INFO - Target URL: http://localhost/wordpress/wp-login.php
2011-07-01 18:33:03,759 - wpbf - INFO - Checking URL & username...
2011-07-01 18:33:08,139 - wpbf - INFO - Load into queue additional words using keywords from blog...
2011-07-01 18:33:08,802 - wpbf - INFO - Bruteforcing...
3 words left
2011-07-01 18:33:21,012 - wpbf - INFO - Password 'qawsed' found for username 'admin' on http://localhost/wordpress/wp-login.php

Despues de verificar la existencia del formulario de login (default: wp-login.php) y la validez del nombre de usuario (default: admin, puede cambiarse utilizando la opcion -u) se buscan palabras clave para agregar al diccionario y el script lanza threads para iniciar las pruebas. Un detalle de actividad del script puede verse en el archivo "wpbf.log" y en caso de encontrar una contraseña valida se guardara en el log y se mostrara en pantalla.


Solo la mitad del trabajo

Para este ataque necesitamos dos datos: usuario y contraseña. Debido a ciertos aspectos de WordPress podemos enumerar usuarios y comprobar que esos usuarios sean validos. La enumeracion de usuarios se puede hacer mediante la deteccion de redirecciones de la query "?author=" incrementando un entero que corresponderia al ID de usuario (ver TALSOFT-2011-0526) o mediante el analisis de la "Author's archive page" del blog. La herramienta wpbf incorpora estas dos tecnicas para buscar automaticamente un usuario valido antes de comenzar el ataque.


$ ./wpbf.py -eu http://localhost/wordpress/
2011-07-01 19:16:02,092 - wpbf - INFO - Target URL: http://localhost/wordpress/wp-login.php
2011-07-01 19:16:02,093 - wpbf - INFO - Enumerating users...
2011-07-01 19:16:03,615 - wpbf - INFO - Usernames: admin, caco, test


Un video demostrativo

En este video se muestra un ataque como el mencionado anteriormente y enumeracion de usuarios en varios blogs elegidos al azar. Hay que verlo en pantalla completa y la calidad del video deja mucho que desear... pero bueno, aqui esta:




Mitigando el ataque

Para el bruteforce existen dos plugins llamados: User Locker y Login LockDown, no probe ninguno de los dos pero si hacen bien lo que dicen hacer deberia alcanzar para evitar el ataque por fuerza bruta.

Respecto a validar que un usuario sea correcto o no, habria que modificar los mensajes de error del formulario de ingreso al administrador de WordPress unificando los mensajes de contraseña invalida con los de usuario invalido (ver post de EthicalHack3r con una propuesta de patch).

Evitar la enumeracion de usuarios por redireccion ya funciona en las ultimas versiones de WordPress, pero queda pendiente de solucion la extraccion de datos del usuario desde la pagina de archivo del usuario. Nuevamente, habria que modificar el codigo de WordPress y eliminar esta funcionalidad o evitar exponer el nombre de usuario en este tipo paginas.

24.5.11

Como cambiar/resetear el password de administrador en Django

Otra vez me olvide la contraseña del administrador de un sitio que hace meses no trabajo y necesito cambiarla por una nueva. Parados en el directorio en donde tenemos nuestra aplicacion vamos a iniciar una 'shell' y hacer uso del modelo de usuarios:


caco@particula:~/dev/subs$ ./manage.py shell
Python 2.6.6 (r266:84292, Sep 15 2010, 15:52:39)
Type "copyright", "credits" or "license" for more information.

>>> from django.contrib.auth.models import User
>>> usuarios = User.objects.all()
>>> usuarios
[<User: caco>]
>>> usuarios[0].set_password('nuev0passwowd')
>>> usuarios[0].save()


Resumiendo: instanciamos el modelo User, traemos todos los usuarios, seteamos un nuevo password para el primer usuario ([0]) y guardamos en la base de datos la informacion sobre este usuario.

23.5.11

Seguimiento del servicio gratuito de SMS Online y la Aplicacion SMS Online de Personal

Un poquito cansado de que no funcione el servicio de Personal para enviar SMS gratuitos por internet decidi investigar un poco y escribir al respecto notificando a Personal via Twitter cuando el servicio no funcionaba, por que y como detectar cuando esto pasaba.

El problema esta de tu lado

De todas las respuestas de Personal (de 9 personas diferentes que manejan su cuenta de Twitter) ninguna se hacia cargo del problema. Las soluciones que me brindaban tenian que ver con mi navegador, cosas como borrar el historial o las cookies. La mas graciosa fue "Intenta actualizar la pagina reiteradas veces": obvio, si tienen un problema de disponibilidad en algun momento que no este saturado el servicio me va a tocar pero la idea es no tener que pasar por eso (sobre todo como cliente de una compañia de comunicaciones).

Ante este tipo de respuestas, empeze a enviar la entrada en mi blog sobre el analisis del problema y comenzaron a responderme que iban a revisar el problema y al parecer lo hicieron.

Aqui no paso nada

En estos momentos, la pagina de personal para enviar mensajes por internet dejo de mostrar el error de SQL que mostraba cuando no funcionaba PERO el sitio sigue sin ser capaz de generar el CAPTCHA para enviar los mensajes desde la web.



Quiza un error no visible haga creer al usuario promedio que es su culpa, o culpa "del internet", que el sitio no funcione pero a mi me gusta investigar y estos dias tengo mucho tiempo libre!

La aplicacion online

En una de las respuestas de Personal me recomiendan utilizar la "Aplicacion SMS Online", asi que la descargue e instale en una de mis maquinas virtuales. Lamentablemnete la aplicacion no funciono y la solucion que me dio Personal fue reinstalar, el mambo de las cookies y demas.

Nuevamente, me pongo a ver en detalle que es lo que no funciona. Haciendo pasar la aplicacion de Personal por un proxy veo que la aplicacion pide la siguiente URL:

http://www.personal.com.ar/smsonline/aplicacion/config/PersonalSMSOnline.txt

Que desde la aplicacion respondia con un error pero desde el navegador respondia:

Personal SMS Online
1.1.1
1.1.2
\nHay una nueva versión de\nAplicación Personal SMS Online


Haciendo un par de pruebas, pude hacer arrancar la aplicacion eliminando el User-agent de la peticion a esa URL. Una vez pasado este paso, la aplicacion funcionaba de manera "normal". Me alegre mucho, pero la alegria me duro poco y fue muy desmoralizante ver que la aplicacion de escritorio que te bajas de personal no es nada mas ni nada menos que un parser de la web de donde se envian los mensajes (para los no-tecnicos, usa la misma web sacando los datos que necesita para funcionar). Osea que si la web no anda, tampoco anda la aplicacion online.

Estamos en la misma, es casi imposible usar el servicio de las 21.00hs a 24.00hs y en las soluciones que plantean no se reconoce el problema real. Tampoco creo que los tecnicos de una empresa como Personal no sepan lo que pasa, pero como me comento otro usuario del servicio: "no van a arreglar algo que no les representa ganancias" y pareceria que tiene toda la razon.

Quiza alguien lea esto y piense que estoy "atacando" a Personal, pero la verdad es que estoy laburandoles gratis a ver si de alguna vez por todas este servicio (que un monton de gente usa y hasta escuche casos que fue crucial para elegir una compania de celular) funcione perfecto.

6.5.11

Pesima disponibilidad del servicio SMS Online de Personal para enviar mensajes por la web

Me gusta que en Personal se pueden mandar mensajes gratis desde la web a otro Personal; pero casi siempre tengo problemas para utilizar este servicio por errores en la carga completa de esta pagina.

El error visible


El error en concreto es de conexion con una base de datos MySQL:

Can't connect to local MySQL server through socket '/tmp/mysql.sock' (11)

Cada vez que aparece este error en la pagina, no se muestra el CAPTCHA y hace imposible completar el formulario correctamente para enviar un SMS desde la web. Probablemente el CAPTCHA se guarde en una base de datos MySQL y se verifique al suscribirse el formulario.



Interaccion con Personal

Cuando comente en Twitter un vez el problema y respondieron "Hubo tareas de mantenimiento, pero ya esta solucionado. Actualiza la pagina presionando F5 que se corrige!", pero el problema persiste. En otra ocasion, me recomendaron "dsd tu explorador ingresá a Herram/opc d internet tildar eliminar el historial de exploracion al salir, aplicar, aceptar, salir y actualizar la página." pero tampoco no funciono ya que claramente es un error del servidor.

UPDATE (mas "soluciones" que ofrece personal, obviamente no entienden el problema):

- 06/06/2011: Ni bien publique este articulos, negaron nuevamente el problema y me recomendaron hacer "Borrado de cache" [@PersonalAr].
- 15/05/2011: Hola! No tenemos reportado novedades.Probaste borrar el historial d navegación? Intentá actualizar la pag reiteradas veces. LM [@PersonalAr]
- 19/05/2011: Hola! Intentá eliminar el historial de navegación. Saludos! NM @PersonalAr

Analisis del servicio

Analizando un poco como funciona el sevicio, pude ver que hay dos servidores que tienen estos formularios para enviar los mensajes: sms1.personal.com.ar y sms2.personal.com.ar; ambos servidores tiran el mismo error en los mismos periodos de tiempo. Decidi hacer un script muy basico que se compruebe cada un minuto si cada uno de estos dos servidores da error o carga el formulario completo para enviar un mensaje y generar unos graficos para que se puedan ver los problemas de disponibilidad de este servicio.

Aca vemos, por ejemplo, un grafico de sms1.personal.com.ar del 03/05/2011 desde las 20hs hasta el final del dia. Los cuadrados indican si en ese minuto hubo un error o si el formulario se cargaba correctamente. Lo ideal seria que este TODO VERDE.


El script intenta acceder a la pagina "http://sms1.personal.com.ar/Mensajes/sms.php" y buscar en su contenido indicios del error de MySQL que se encuentra al principio de la pagina. Si el error existe no se muestra el CAPTCHA, por lo tanto no es posible completar el formulario para enviar el SMS y mi grafico lo muestra en rojo. Cuando no encuentra el error, asume que vamos a poder enviar un SMS y lo marca en verde.

Otro ejemplo del mismo servidor durante todo el dia 04/05/2011:




Que nos dicen los grafiquitos chulos?

Podemos ver que desde las 00hs hasta las 12hs el servicio es usable y estable. A partir de las 12hs comienza a tener problemas menores de disponibiliad y desde las 20hs hasta las 00hs es practicamente inusable.

Se podra implementar el mismo sistema sin utilizar una base de datos (solo datos en la sesion de usuario)? Agregando un servidor mas a los dos que tienen, alcanzara para resolver los problemas de disponibilidad de la noche?


Algunos usuarios afectados

Cuando empeze a buscar en Twitter y Google encontre un monton, algunos como para tener de referencia:

* https://twitter.com/aldulovato/status/66325916665655296
* https://twitter.com/lucianita88/status/66310154454433792
* https://twitter.com/dreamcoders/status/65945527312850944
* http://twitoaster.com/ea00d009/el-cant-connect-to-local-mysql-server-through-socket-tmpmysqlsock-11-de-la-web-de-personal-me-tiene-podrido-personal-fail/
* http://www.taringa.net/posts/ebooks-tutoriales/5539478/No-anda-la-pagina-de-sms-personal-_Solucion_.html

Vuelta a Babylon

Despues de 9 meses de viaje en bicicleta (y mas de 6000Km!) en lo que denominamos Bikelab, ya estoy de vuelta en Buenos Aires. Resumiendo el viaje (el detalle en la pagina): salimos de Buenos Aires, pasamos por Santa Fe, Cordoba, Catamarca, Tucuman, Salta, Jujuy, Santiago del Estero, Chaco, Corrientes, Entre Rios y cruzamos a Uruguay. Uruguay lo atravesamos de oeste a este hasta la costa y bordeamos la costa hasta Colonia. Salvo Colonia-BuenosAires, todo el viaje fue a puro pedal y la estadia carpa/bolsa.

Ahora me aburro, no soporto la franja entre las 17hs y las 19hs en donde todos los autos roncan un drone de la ciudad horrible. No duermo bajo los arboles, ni me lavo la cara en el rio. Por suerte ya me encontre con mis amigos y con amigos que hice durante el viaje; y ya estoy planeando otra gran aventura quien sabe por donde y en que.

Haganlo.