I am learning infosec with DVWA (Damn Vulnerable Web Application). At first I've decided to write something to brute force admin login screen. I've downlaoded a list of most commonly used passwords and created a script which takes them and attempts to log in. What do you think of it, what could be improved?

#!/usr/bin/env python3

import requests

entry_found = False

(0, len(passwords) // 4),
(len(passwords) // 4 + 1, len(passwords) // 2),
(len(passwords) // 2 + 1, 3 * (len(passwords) // 4)),
(3 * (len(passwords) // 4) + 1, len(passwords) - 1),
]
target=run_cracker,
args=(
)
) for split_point in password_list_split_points]

global entry_found
if entry_found:
break
# Passwords still contain last \n char which has to be stripped.
# This is set to True only once. No need for sync mechanisms.
entry_found = True

response = requests.post(
URL,
)

if bytes('Login failed', encoding='utf-8') not in response.content:
))
return True
else:
return False

if __name__ == '__main__':

print('[*] Wating for {} to join.'.format(thread.getName()))

• I assume this isn't intended for actual cracking. If so, python is not a great language for such a problem, given the speed. – Oscar Smith Nov 16 '17 at 4:11
• It's been used in creating some exploits and there are other bottlenecks than the language itself like network speed od server response speed. I am not using GPU hash cracking but simple bruteforce against (intendently) poorly designed web app. Metasploit is also based on scripting language (ruby). I think I'll compare it with some java, swift or C++ in some time, but currently it serves it purpose well enough :-) – gonczor Nov 16 '17 at 6:55

Recommendations

• Right now the create_threads function is skipping passwords and is hard-coded to only work with four threads. I'll go over ways to fix both of these issues.

• The password skipping occurs because taking a slice of a Python list is a non-inclusive operation.

For example:

n = 100
a = range(n)
b = a[0 : n // 4]          # equals [0, 1, ... , 23, 24]
c = a[n // 4 + 1 : n // 2] # equals [26, 27, ..., 47, 48]

• Notice that a[25] is being skipped. You can fix this by slicing a in the following way: [a[i : i + n // 4] for i in range(0, n, n // 4)]

• The problem is that this solution assumes that n % 4 == 0. Or, to bring it back to your code, that len(passwords) % 4 == 0. In the code below we can fix this issue by keeping track of the value of the modulus operation in the variable m. If m != 0 then we can replace the last list (in our list of password slices, xs) with the appropriate slice.

• Fortunately all of this makes it easier to replace the hard-coded thread number with a variable (t in the code below).

Code

def create_threads(t, passwords):
x = n // t
m = n % t
xs = [passwords[i:i+x] for i in range(0, n, x)]
if m:
assert(sum([len(l) for l in xs]) == n)
return [
]


This seems to me like your create_threads and run_cracker functions are trying to reinvent something that look like multiprocessing.Pools. Using them, you just need to implement crack_password, managing the workload and spawning processes will be done by the pool.

This will however not short-circuit once a working password has been found.

Example implementation:

from multiprocessing import Pool

import requests

response = requests.post(
url,
)

if bytes('Login failed', encoding='utf-8') not in response.content: