La semana pasada me encargaron reforzar la seguridad de algunos wordpress que estaban todos alojados en el mismo servidor porque se sospechaba que habían podido entrar en alguno por fuerza bruta. Efectivamente, en al menos uno de ellos entraron pero esa es otra historia. La cuestión es que el que me encargo el trabajo me dijo «Crea usuarios nuevos: uno que sea administrador (y que no se llame admin) y otro que sea redactor. Solo publicaremos con el usuario con permisos de redactor y así, si alguien busca en la web, solo encontrará ese usuario y no el que tiene privilegios de administrador». En principio tiene lógica: si alguien va en busca de nombres de usuario para intentar loguearse, en la web sólo verá páginas y artículos escritos por el usuario redactor con lo que si lograra entrar no tendría privilegios que pudiesen comprometer la seguridad del sitio.
A no ser, claro, que hubiese una forma previa de encontrar los demás login de usuario en wordpress. Y la hay. Se llama wordpress user enumeration. La manera de conseguirlo es sencilla, algo así: misitiowordpress.com/?author=id siendo id la id del usuario que queremos que wordpress nos muestre. Y lo hará independientemente de que haya publicado algo o no.
Este fallo tiene más años que los caminos. El porqué no se ha corregido es algo que no alcanzo a comprender. Supongo que automattic tendrá sus razones. Al igual que el hecho de que al intentar loguearse nos diga si es el usuario o la contraseña lo incorrecto.

Prueba de concepto con el usuario admin. WordPress nos señala en cada caso qué es incorrecto: user o password
Para comprobar esta vulnerabilidad de manera automática, creé este script en Python que dejo a continuación. Lo que hace es descargarse la página resultante de la consulta y buscar el author dentro de ella. La he probado con varias webs y no funciona con todas pero sí con la mayoría. Con esto quiero decir que el script es mejorable.
#!usr/bin/env python import urllib import urllib2 import re import sys #Este script enumera los usuarios de un sitio web creado con wordpress #a partir de su id if len(sys.argv) !=3: print "USO: wp_enum_users.py [sitio_web] [numero_maximo_id]" print "EJEMPLO: python wp_enum_users.py misitio.com 3" print "Busca los usuarios que tengan los id 1...3 de misitio.com" else: id_max = int (sys.argv[2]) web = str(sys.argv[1]) for i in range(1,id_max): aResp = urllib.urlopen("http://"+web+"/?author="+str(i)) html = aResp.read() match = re.search("(?<="+web+"/author/)[a-z0-9 _.\-@]+",html, re.M|re.I) if match: print match.group()+" ID: "+str(i)
¿Maneras de evitar esto?
Habrá unas cuantas pero yo lo arreglé instalando el plugin «Stop User Enumeration«. Solo hay que activarlo y ya está. No hay que configurar nada.
Hasta otra, «wordpresseros» de pro.