Skip to content

Commit

Permalink
Implementation of workers that manage tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
atarantini committed Aug 6, 2011
1 parent 3b5b535 commit 03c21f3
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 38 deletions.
71 changes: 35 additions & 36 deletions wpbf.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,22 @@
import urllib2, urlparse
import sys, threading, Queue, time, argparse

import config, wplib
import config, wplib, wptask

class WpbfThread(threading.Thread):
"""Handle threads that consume the wordlist queue and try to login for each word"""
def __init__(self, wordlist_queue):
class WpbfWorker(threading.Thread):
"""Handle threads that consume the tasks queue"""
def __init__(self, task_queue):
threading.Thread.__init__(self)
self._queue = wordlist_queue
self._queue = task_queue

def run(self):
while self._queue.qsize() > 0:
try:
word = self._queue.get()
if wp.login(config.username, word):
logger.info("Password '%s' found for username '%s' on %s", word, config.username, wp.get_login_url())
self._queue.queue.clear()
task = self._queue.get()
task.run()
self._queue.task_done()
except urllib2.HTTPError, e:
logger.debug("HTTP Error: %s for: %s", str(e), word)
self._queue.put(word)
logger.debug("Requeued: %s", word)
except wptask.WpTaskStop:
self._queue.queue.clear()

if __name__ == '__main__':
#parse command line arguments
Expand Down Expand Up @@ -94,7 +90,7 @@ def run(self):
exit(0)

# queue
queue = Queue.Queue()
task_queue = Queue.Queue()

# check URL and username
logger.info("Checking URL & username...")
Expand Down Expand Up @@ -127,50 +123,53 @@ def run(self):
logger.info("Check if proxy is well configured and running")
sys.exit(0)

# load fingerprint task into queue
if args.nofingerprint:
task_queue.put(wptask.WpTaskFingerprint(config.wp_base_url, config.script_path, config.proxy))

# check for Login LockDown plugin
logger.debug("Checking for Login LockDown plugin")
if wp.check_loginlockdown():
logger.warning("Login LockDown plugin is active, bruteforce will be useless")
sys.exit(0)

# load username into queue
if config.username not in queue.queue:
queue.put(config.username)

# load wordlist into queue
wordlist = [config.username] # add username to the wordlist
logger.debug("Loading wordlist...")
try:
[queue.put(w.strip()) for w in open(config.wordlist, "r").readlines()]
[wordlist.append(w.strip()) for w in open(config.wordlist, "r").readlines()]
except IOError:
logger.error("Can't open '%s' the wordlist will not be used!", config.wordlist)
logger.debug("%s words loaded from %s", str(queue.qsize()), config.wordlist)
logger.debug("%s words loaded from %s", str(len(wordlist)), config.wordlist)

# load into queue additional keywords from blog main page
if args.nokeywords:
logger.info("Load into queue additional words using keywords from blog...")
queue.put(wplib.filter_domain(urlparse.urlparse(wp.get_base_url()).hostname)) # add domain name to the queue
[queue.put(w) for w in wp.find_keywords_in_url(config.min_keyword_len, config.min_frequency, config.ignore_with) ]

# wordpress version
if args.nofingerprint:
if wp.fingerprint():
logger.info("WordPress version: %s", wp.get_version())

# spawn threads
logger.info("Bruteforcing...")
logger.info("Loading additional keywords from blog to the wordlist...")
wordlist.append(wplib.filter_domain(urlparse.urlparse(wp.get_base_url()).hostname)) # add domain name to the queue
[wordlist.append(w) for w in wp.find_keywords_in_url(config.min_keyword_len, config.min_frequency, config.ignore_with) ]

# load logins into task queue
for password in wordlist:
login_task = wptask.WpTaskLogin(config.wp_base_url, config.script_path, config.proxy)
login_task.setUsername(config.username)
login_task.setPassword(password)
task_queue.put(login_task)

# start workers
logger.info("Starting workers...")
for i in range(config.threads):
t = WpbfThread(queue)
t = WpbfWorker(task_queue)
t.start()

# feedback to stdout
while queue.qsize() > 0:
while task_queue.qsize() > 0:
try:
# poor ETA implementation
start_time = time.time()
start_queue = queue.qsize()
start_queue = task_queue.qsize()
time.sleep(10)
delta_time = time.time() - start_time
current_queue = queue.qsize()
current_queue = task_queue.qsize()
delta_queue = start_queue - current_queue
try:
wps = delta_time / delta_queue
Expand All @@ -179,6 +178,6 @@ def run(self):
print str(current_queue)+" words left / "+str(round(1 / wps, 2))+" passwords per second / "+str( round((wps*current_queue / 60)/60, 2) )+"h left"
except KeyboardInterrupt:
logger.info("Clearing queue and killing threads...")
queue.queue.clear()
task_queue.queue.clear()
for t in threading.enumerate()[1:]:
t.join()
3 changes: 1 addition & 2 deletions wplib.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ def find_username(self, url=False):
"""Try to find a suitable username searching for common strings used in templates that refers to authors of blog posts
url -- Any URL in the blog that can contain author references
proxy -- URL of a HTTP proxy
"""
if url:
data = self.request(url, [], True)
Expand Down Expand Up @@ -334,7 +333,7 @@ def check_loginlockdown(self):
def fingerprint(self):
"""Try to fetch WordPress version from "generator" meta tag in main page
return - WordPress version or false if now found
return - WordPress version or false if not found
"""
data = self.request(self._base_url, [], True)
m = re.search('<meta name="generator" content="[Ww]ord[Pp]ress (\d\.\d\.?\d?)" />', data)
Expand Down
54 changes: 54 additions & 0 deletions wptask.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""
wpbf is a WordPress BruteForce script to remotely test password strength of the WordPress blogging software
Copyright 2011 Andres Tarantini (atarantini@gmail.com)
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 3 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, see <http://www.gnu.org/licenses/>.
"""
from wplib import Wp

class WpTask():
"""Base task class"""
def run(self):
pass

class WpTaskStop(Exception):
"""Stop all tasks"""
def __str__(self):
return 'Stop all tasks!'

class WpTaskFingerprint(Wp, WpTask):
"""Perform WordPress fingerprint and, is positive, log the results"""
def run(self):
self.logger.info("WordPress version: %s", self.fingerprint())

class WpTaskLogin(Wp, WpTask):
"""Perform WordPress login. If login is positive, will return true or false otherwise.
Note that username and password must be set invoking setUsername and setPassword methods.
"""
_username = ''
_password = ''

def setUsername(self, username):
self._username = username

def setPassword(self, password):
self._password = password

def run(self):
if self.login(self._username, self._password):
# username and password found: log data and stop all tasks
self.logger.info("Password '%s' found for username '%s' on %s", self._password, self._username, self.get_login_url())
raise WpTaskStop

0 comments on commit 03c21f3

Please sign in to comment.