DVWA - Brute force

4 June 2019

Starting the challenge

Refer to the post start DVWA with Docker to learn how to start DVWA. I will mostly use Burp Suite to solve the challenges. To configure Burp suite refer to the post configure burp suite for DVWA. Click on the Brute force button on the left menu to access the challenge.

Low Level - Understanding the application

We reach a page allowing us to log in something. We can put a username and password and click on the button login.

Application

If we try the username and password test we get the error message Username and/or password incorrect.

Failed attempt

As we can see from the URL, the username and password are passed as GET parameters.

Low Level - Brute forcing the credentials

We would like to connect to the application but we do not know what the credentials are. The administrator may have entered some default and predictable username and password. To try these predictable credentials we will use the Burp Intruder.

Please refer to the post setup burp intruder to learn how to configure the attack.

You can use the usernames.txt and passwords_quick.txt lists from IntruderPayloads for your attack.

In the end we can see that the credentials were "admin/password".

Low Level - Vulnerability

There are multiple ways to improve the security in this case. We can :

  1. Educate people to use password managers and stronger passwords.
  2. Enforce the use of a unique password that was never leaked.
  3. Block too many login attempts to slow down the attacker.

Medium level

The medium level is basically identical except that the developer implemented a sleep() function to nag attackers. This is clearly useless as the same method used in the low level will work perfectly.

    else {
        // Login failed
        sleep( 2 );
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }

High level

This level is a little bit different. When we send a request with the credentials test/test we can see that a new parameter is being sent along the credentials : the user_token.

Here is the form we have on the login page :

<form action="#" method="GET">Username:
    <br />
    <input type="text" name="username">
    <br />
    Password:
    <br />
    <input type="password" AUTOCOMPLETE="off" name="password">
    <br />
    <br />
    <input type="submit" value="Login" name="Login">
    <input type='hidden' name='user_token' value='76ec861542aa9bbe797a98e9b7d86300' />
</form>

To be able to brute force the application we must give the proper user_token in our login request. Here is a login request sent from our browser:

GET /vulnerabilities/brute/?username=test&password=test&Login=Login&user_token=76ec861542aa9bbe797a98e9b7d86300 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost/vulnerabilities/brute/
DNT: 1
Connection: close
Cookie: PHPSESSID=c8f9p19iv3b8s0cm58d7pm1e25; security=high
Upgrade-Insecure-Requests: 1

To do so with Burp Suite we will have to create a macro.

Creating the macro

We go to Project options > Sessions > Macros > Add to record a new macro.

The Burp Macro Recorder window pops up. We select the item where the token is given to us in the response of the GET request, and we click OK.

Brute force macro

We continue with the Macro Editor window. We change the description to Fetch token. And we click OK.

Brute force macro

We now have a macro that is capable of retrieving the login page. We just have to extract the token from the login page now.

Session handling rule

To define the rule that will extract the user token we navigate to Project options > Sessions > Session Handling Rules > Add.

We name our rule "Anti-CSRF token" and click Add under Rule Actions.

Brute force rule

We select Run a macro in the drop down menu and then we select the macro Fetch token and click OK.

In the Scope tab we select Intruder : the tool the rule will be applied to.

Brute force rule

Now we click the Up button to move the rule up.

Brute force rule

We can test the rule with the repeater. If we get an error password incorrect then everything worked properly.

Brute forcing

We start the brute force as usual. The vulnerability is the same as before.

Impossible level

In the impossible level, the developper implements a lockout mechanism to slow down attackers.

    // Check to see if the user has been locked out.
    if( ( $data->rowCount() == 1 ) && ( $row[ 'failed_login' ] >= $total_failed_login ) )  {
        // User locked out.  Note, using this method would allow for user enumeration!
        //echo "<pre><br />This account has been locked due to too many incorrect logins.</pre>";

        // Calculate when the user would be allowed to login again
        $last_login = strtotime( $row[ 'last_login' ] );
        $timeout    = $last_login + ($lockout_time * 60);
        $timenow    = time();

        /*
        print "The last login was: " . date ("h:i:s", $last_login) . "<br />";
        print "The timenow is: " . date ("h:i:s", $timenow) . "<br />";
        print "The timeout is: " . date ("h:i:s", $timeout) . "<br />";
        */

        // Check to see if enough time has passed, if it hasn't locked the account
        if( $timenow < $timeout ) {
            $account_locked = true;
            // print "The account is locked<br />";
        }
    }

Each time a failed attempt is made, the lockout time is increased.