2015-10-29

Original link: https://blog.g0tmi1k.com/dvwa/bruteforce-low/

This post is a "how to" for the "brute force" module set to "low" level security inside of Damn Vulnerable Web Application (DVWA). There are separate posts for the medium level (time delay) and high setting (CSRF tokens). There is a related post for the login screen as it was also brute forced (HTTP POST form with CSRF tokens).



Once more, let's forget the credentials we used to login to DVWA with (admin:password).

Let's not try the default login for the web application.

Let's play dumb and brute force DVWA... again.

TL;DR: Quick copy/paste

Table of Contents

Objectives

Setup

Tools

What is brute force?

Creating a Session Cookie

Information Gathering

Form HTML Code

Generating a Baseline

Test lab vs Production target

Blacklisting vs Whitelisting

Usernames & Wordlists

Threads & Timeouts

Hydra

Hydra Documentation

Debugging Hydra with Burp Proxy

Burp's Invisible Proxy Mode

Hydra Attack Command

Patator

Patator Documentation

Debugging Patator

Patator Attack Command

Burp Proxy

Failed Attempts

Medusa

Nmap

Ncrack

Metasploit Framework

Proof of Concept Scripts

Bash Template

Python Template

Summary

Hydra vs Patator Syntax

Benchmark

Conclusion

Objectives

The goal is to brute force an HTTP login page.

GET requests are made via a form.

The web page is in a sub folder.

Low

Straight forward HTTP GET brute force attack via a web form.

Bonus: SQL injection (
See here for more information
).

Medium

Extends on the "low" level - HTTP GET attack via a web form.

Adds in a static time delay (3 seconds) on failed logins.

High

Extends on the "low" level - HTTP GET attack via a web form.

This time uses a random time delay (between 0 and 4 seconds) instead.

Uses an anti Cross-Site Request Forgery (CSRF) token.

Impossible

Submits data via HTTP POST via web form

Accounts will lock out after 5 failed logins.

Time delay before becoming unlocked (15 minutes).

Unable to enumerate users on the system.

Possible "Denial of Service (DoS)" vector.

PHPIDS

Does not protect against this attack.

All attack methods are still the same!

Setup

Main target: DVWA v1.10 (Running on Windows Server 2012 Standard ENG x64 + IIS 8).

Target setup does not matter too much for this - Debian/Arch Linux/Windows, Apache/Nginx/IIS, PHP v5.x, or MySQL/MariaDB.

The main target is on the IP (192.168.1.44), port (80) and subfolder (/DVWA/), which is known ahead of time.

Because the target is Windows, it does not matter about case sensitive URL requests (/DVWA/ vs /dvwa/).

Attacker: Kali Linux v2 (+ Personal Custom Post-install Script).

Shell prompt will look different (due to ZSH/Oh-My-ZSH).

Added colour to tools output (thanks to GRC).

Both machines are running inside a Virtual Machine (VMware ESXi).

Tools

cURL - Information gathering (used for viewing source code & to automate generating sessions).

Could also use wget (wget -qO -) instead.

Or using Burp/Iceweasel, however, it is harder to automate them due to them being graphical, which makes doing repetitive stuff boring.

THC-Hydra v8.1 - A brute force tool.

Patator v0.5 - An alternative brute force tool.

Burp Proxy v16.0.1 - Debugging requests & brute force tool

Using FoxyProxy to switch proxy profiles in Iceweasel.

SecLists - General wordlists.

These are common, default and small wordlists.

Instead of using a custom built wordlist, which has been crafted for our target (e.g. generated with CeWL).

Failed brute force tools:

Medusa v2.1.1 - segmentation faults when sending a custom header and HTTP 200 response.

Metasploit v4.11.4-2015090201 - auxiliary/scanner/http/http_login does HTTP basic authentication, not web forms.

Ncrack v0.4 ALPHA - HTTP module only supports HTTP basic access authentication, not web forms.

Nmap v6.49 BETA5 - http-form-brute lacks required options to-do the attack (as it cannot send custom headers).

What is brute force?

For the people who are unaware of "brute force attacks", here is an overview of the most common points:

Brute forcing is a trial and error method of repeatedly trying out a task, sequentially changing a value each time, until a certain result is achieved.

So it forces its way in, and does not take "no" for an answer.

The values used in the attack may be predefined in a file (often called a wordlist or dictionary file - there is not a difference between terms), where only these certain values are used. Alternatively, every possible combination could be used in a given range. Example:

Brute force attack: AAA -> AAB -> AAC -> ... -> ZZY -> ZZZ

Dictionary attack: ANT -> BED -> CCC -> DOG -> EEE -> HOG

The values used & the order of them, all depends on how the attacker performs the attack.

A brute force attack will cover everything in its range; however, it will take longer than a dictionary attack based on the total amount of combinations.

A dictionary attack will use the pre-compiled values. However, there are values tools out there to "mangle" the wordlist in various ways, allowing for more possibilities and total combinations. An example: password -> password1999 (year at the end). password -> p@$$w0rd (1337 speak). The original value (password) is called "base word".

The best wordlist to use is one customized to the target. When using general wordlists, check for:

Leading/trailing spaces/tabs - ^ password$, ^password$, ^password $ (forgive the regular expressions!)

Duplicated entries (case sensitive!) - password, farm, PASSWORD, mouse, password, horse, Password

The ordering of the list - common_password, uncommon_password

If it is just base words - password, password99, password1999, p@55w0rd

The language - password, motdepasse, passwort, clave

In a brute force attack, multiple wordlists could be used. Example: one for the password, one for the username. The attacker may loop through all the passwords, before trying the next username or vice versa. Alternatively, the username and password lists may be increased at the same time.

An online attack refers to the attack being a network service, on a machine which is not the attacker's (aka a "remote machine"). An offline attack would be local to the attacker's machine.

A brute force attack speed runs at the slowest point. If it is an online attack, this is often the network connection, whereas, offline is commonly the CPU/GPU speed. Offline attacks are normally much quicker than online ones.

There are various ways to speed up brute force attacks, normally by increasing threads. This is how many tasks/requests are performed at once. Not using enough, means there could be additional performance gained as not all the resources are being used. However, using too many will overload causing, it to perform slower or to miss a successful attempt.

Creating a Session Cookie

To get the web form that we want to brute force (http://192.168.1.44/DVWA/vulnerabilities/brute/), we must already be logged in. This in itself is a bit of an odd thing to-do as most of the time, you would not be authenticated hence the brute forcing... Anyway, as we are going to be using a lot of command line tools, we need to create an active and valid session to interact with DVWA. Normally, you would not have to-do this. This is just for DVWA.

I'm going to be re-running these commands often, however, this is overkill. This is because it will make it easier for people who are copying/pasting or stop/starting a lot (hence their session times out) or people jumping around the page (skipping sections out). As long as the admin's password has not been changed from the default value (password), this will work (depending on your target's IP address).



Note, depending on the web server & its configuration, it may respond slightly differently (in the screenshot: 192.168.1.11 is Nginx,192.168.1.22 is Apache & 192.168.1.44 is IIS). This is a possible method to fingerprint an IIS web server.

The first line grabs the "Anti Cross-Site Request Forgery (CSRF)" token (as explained when brute forcing the main login page), and extracts the user_token field) which will be a unique value each time and paired to the session ID.
We then send a request that would be the same as filling in the form with the user credentials (again, see the main login page being brute forced to see how this was constructed), using the same cookie which was set from our first request.
Lastly we remove the security level from the cookie value. As this would be a "static" value, and ideally we want it to be "dynamic" (so we can change the level based in our request).

Information Gathering

If this was a "real world" scenario, we would clone the target's production setup as best we could (e.g. find if it is using "off the shelf" software, web server information, what versions etc.) and clone it into a test lab. This means we could fully control the web application, allowing us to understand it better. For example, we could create a user on the system and watch how the program responses with a successful login, rather than just guessing and hoping.

However, we will take a slightly different approach as this shows why doing information gathering as you go along is important as well using different techniques and methods.

Form HTML Code

The first thing we want to-do is to see what we are going up against. Same idea as before; let's see the returned HTML code. This is done by using sed to extract between the HTML tags we want (known ahead of time).



sed -n '/<div class="body_padded/,/<\/div/p' extracts everything between <div class="body_padded and its matching </div. I knew to use these values as I had looked at the complete page output beforehand, the HTML output is far too long, hence why sed is used to snip out the necessary lines!

sed -n '/<form/,/<\/form/p' is then done as this is everything which would be sent in the request when trying to login.

Generating a Baseline

Now we are going to create a "baseline" which is a request before we try to login (before.txt), and then make another request made afterwards using an incorrect login attempt (after.txt). The last step would be to compare the differences between them. This way we can see how the web app responds and start to get a feel of how it works.

Note, both requests were made within a second of each other, because of this there the time and date stamp are the same!

Well this is not exactly what we were expecting! One request says the login is incorrect (after.txt), the other (before.txt) says we are logged in - yet we did not attempt to! A possible reason for this could because of the cURL command before, logging us into the core DVWA rather than us using the brute force form. We can confirm our suspicions by making another baseline request.

"Bash fu" alert, we can repeat the last cURL command (!curl), and replace a value (:gs/after/again/). People using ZSH shells will also find it will expand the command before executing it. Another tip, by using before{,_again}.txt our shell will see it as bash.txt before.txt before_again.txt which saves us typing a bit!

Just as we thought, the You have logged in as 'admin' message is the core DVWA response rather than the brute force module so we need to ignore this for the brute force module.

Test lab vs Production target

TL;DR: In a test lab, you will have full administrative access. A production target, you may not even have an account to the system.

Even though DVWA is a "test lab", we are treating it as a production target system. Because it is a "black box test", we have not been given credentials to login. The web application does not have a "sign up/register" page so we cannot create a user for ourselves. We could try phish a user to get their login, however, this starts to go out of scope, as it is not really brute forcing.

If DVWA was in a test lab (so we fully control the target, allowing us to created a user ourselves, meaning we know the values to use), or we knew of a valid account to login with on the production server (e.g. default user, demo account, or a given one in the scope of the pentest), we could find a "marker" to signal what happens when you log in (such as output on the page being redirected to a different page, the page size being different, additional headers etc.).

For demonstration purposes, I will show this. First cURL command will remove the unwanted text. The next request is a "failed" log in (user:pass), the last is successful (admin:password). By comparing the responses, we can see the page size is different (failed: 4945, success: 5007), as well as the HTML output (failed: Username and/or password incorrect., success: Welcome to the password protected area).

Blacklisting vs Whitelisting

TL;DR: Blacklisting, you are ignoring all results that do not contain phrase. Whitelisting, you are looking for a specific value to be successful.

We need to identify a key point to "mark" how the web application will respond when a login is incorrect (aka blackisting) or if it was successful (aka whitelisting).

Blacklisting often contains more false positives, where it believes it has successfully logged in, when it really failed. This is because you have to rule out "every" possible combination other than a successful login.
Depending on the web application, it may respond differently for any number of reasons at any stage. If the marker does not appear on the page, it will believe it logged in correctly.
An example: if the marker was set to incorrect password, or if the web app responded with incorrect username/password because it is not an exact match, the program will believe it is a correct login. If the web application responded with incorrect CSRF token, the program would believe it was a successful login, even though it was not. Using incorrect would be better here as it appears in both statements. However, if the marker is too general, this may cause issues. The marker needs to be as unique as possible.

The advantage of using blacklisting is that it is easier to discover a failed login attempt rather than a successful one, so it is easier to begin with. Another benefit is, you get to see how the web application responds differently over time and all responses. This means it is easier to debug issues more quickly.

For whitelisting, they give a more accurate way of knowing if you have logged in correctly, rather than having to rule out every response which is incorrect. The down side to it is if, during the request the page starts to respond differently, we might not be aware, and will just blindly keep attacking, which might be a waste of time. An example is, if an API key has reached its maximum amount of requests for a given period of time.

The "best" way would be to use a mixture of them; ignore all pages that respond in a certain way, print pages which do not match any known response, and quit if a certain value is found (Hydra does not support this, but Patator supports various operators and condition requirements).

Anyway... Getting back to DVWA brute forcing, we could risk doing a whitelist attack and make an educated guess at the response (such as: welcome, logged in, successful, hello, thank you etc.), as we do not know what a correct login looks like (because we are ignoring the section above). However, this means we might have to wait as we make multiple complete attempts and also hope a user's password is in our wordlist. So rather than guessing, let's use what we know, (and understand the attack might not work due to an unknown page response, and having to repeat it).

This means we can use either the HTML output of Username and/or password incorrect., or the page length being 4945 as markers to ignore. As the HTML is more of a unique marker, we will start by using that (sometimes web applications put various statics in the response, such as page generation time, or a full data stamp which may cause the page length to be different each request - comparing multiple reponses could rule this out). This means any pages which do contain it as incorrect. Therefore any pages which do not contain the phrase, will be seen as "successful" (hopefully this is correct and the web app does not start to behave differently). If it does, we will need ether to also include the additional value or to re-think the marker completely.

Usernames & Wordlists

Normally, people are after the "main" user account on the system (often called admin, root, system), as this is the account that normally has most access over the system. Often this has user id "1" as it is the "first" user account on the system. Depending on the web application there might be "group" control, allowing multiple users to share certain values. If this is the case, there is often an "administrative" group control which is desirable to attackers, which will be a good alterative if the main account is inaccessible.

So during our attacks, we will do two commands. One for a "single user", where we try for the main account (in DVWA case, admin), and then another command to attack multiple users. DVWA by default comes with a total of five accounts. We want to target them all!

We have crafted a username wordlist ourselves. How do we know what values? Depends on the web application! There are various ways to enumerate users on the system (Are they made public at all? Are we able to exact anything from "Forgotten user password"? Can we map "User IDs" to usernames? Email addresses? Can we just "guest"?). However, in this case, for DVWA:

There is not a list of public usernames on the web applications.

There is not a "sign up" or "forgotten password" function.

Being an end user - we are able to map User IDs to first/last names (not usernames) by a core function in the web application using the "SQL injection module".

Using this, we could start to build up a custom username wordlist.

Example: user id: 2, First name: Gordon, Surname: Brown.

This would be all the information need to figure out his uname is: gordonb (<surname><first letter of first name>).

Web application is free & open source. Looking at the source code, there are five default accounts, hardcoded into the setup (and passwords in plain text).

Some are usernames hinted at in the "help page".

There is also a SQL injection in the page (when on low security level):

Able to enumerate the whole user database (get a list of usernames).

Extract the hash value of the passwords (allowing for offline brute force attack, which is MUCH quicker than online brute force).

Replace the hashes with known values.

...more about this later
.

A wordlist (sometimes referred to as a dictionary file) is just a plain text file, which contains possible values to try separated out by a common perimeter (often a new line). The file extension does not matter for the text file (often they are .lst, .dic, .txt or missing completely)!

We are going to cycle through the usernames before trying the next password, allowing us to focus on the password. This is an in-built feature in Hydra (-u), and Patator supports this based on the ID value of the wordlist. It will not matter if there is a single user in the attack, only when trying multiple usernames. The reason why this could speed up an attack is, (un)fortunately people (still) use common passwords. Different users may have the same password as they do not have to be unique (whereas usernames do). e.g. this means every user who has password as their password, will be discovered very close together.

Threads & Timeouts

TL;DR: Depends on your network connection & target machine. There is not often a need to alter it from default values (unless trying to debug)

Brute forcing is slow. The speed will be because of the slowest point in the system, and there are various places where it will slow down.

System resources

Applies to both for the attacker and target machine

Researched CPU limit? Maxed out on RAM? Hard drive input/output rate?

Network speed (both up/down stream of both parties)

What is the target?

What is the service? (HTTP? SSH? FTP?)

What is the application? (Open source? Custom made?)

Does it use a database? Is it local to the target? How many requests does the application make to the database?

What functions does the application perform? (E.g. calculating password hashes. Certain ones can be more demanding, therefore, increasing the work load).

Any other users, using the target at the same time?

Port exhaustion? Can the target handle all those requests?

...and all of this is before any brute force protection is in place (e.g. firewalls, account lockouts etc.)!

Because the amount of requests is username * password, the total requests can quickly grow, therefore taking much longer to complete. This is a reason why information gathering & profiling is useful, to know the exact username(s) to target (rather than just guessing). Thereforce using custom built wordlists should give a higher success rate than using a general one (e.g. the chance of a target's password being in an English 65GB wordlist is low if the target does not speak English/have an English keyboard).

Due to the amount of time it may possibly take, there is an urge to tweak the brute force method (e.g. increase the thread count, lower the wait time). However, there is not a fixed "magic number" (it is more of an "art", than a "science"). Altering these values too much, may cause more issues in the long run.

Example: putting the thread count "too high", could cause an extreme amount of requests to a web server. An issue could be the attacker is able to product more network traffic than the target OS/application can handle. Another thing could be, for each request the OS sets aside a certain amount of system resources and soon the target system may run out of memory. It all depends on the setup, the target, and, its configuration. The more requests sent to the target, the harder it has to work, therefore, the response time will start to be slower (so the wait time/timeout values would also need to be increased).

If everything is working "correctly" lowering the wait time does not often archive anything. Example: if the timeout is set to 10 seconds, but it takes less than 1 second to respond, having it at 5 seconds or even 3 seconds will not make any difference. On one hand, having the value too low could mean valid requests are ignored. However, if there starts to be an increase in requests requests taking a longer period of time to response back, for whatever reason, you may be waiting unnecessary (this could signal there is another issue/protection in place).

Another thing to keep in mind, depending on the tool used, it may not display if a request "timed out" or even check periodically to see if the service is still active. Meaning the part of the attack could be pointless.

The last point is, the system may respond differently depending "how it pushed" and "how much it was pushed".

Instead, what might be a better methodology, is having the wordlist sorted in a certain order. This may help speed up the attack (having the more common values at the start). There are various ways to create a custom targeted wordlist, but this going offtopic. Just bare in mind, you may not have to go through the complete wordlist, there is a 50% chance it will be in the first half ;-).

It might also mean taking multiple runs for it to be successful, one at once (serial rather than parallel). E.g. one wordlist with default credentials, another with commonly used passwords, and another with just a baseline wordlist then another try with "mangled rule" applied to the prior1 wordlist. So each time the size of the wordlist would grow, taking longer, but there will be less chance of missing the "low hanging fruit". I believe it is "better" to make lots of smaller attacks rather than being lazy and making one big one.

During the debugging stage, I used a single thread (so it is easier to follow the request in a proxy/watching web logs), with a larger timeout value (as I could then tweak the values in Burp's intercept screen), and added in a delay after the thread finished (so I could check all the output).
For the "final" attack, I was on a LAN connection, rather than WAN/Internet, therefore, the speeds would be quicker. Because the response times were so low, the slowest point normally was not the network connection (therefore increasing the threads would not help a great deal in this case). See the benchmark results!

Getting the attack to use the maximum performance first time is rare =).

Hydra

Hydra Documentation

First tool we are going to use is THC-Hydra (more commonly known as just Hydra). This is probably the "most well-known" tool (as it has been around since August 2000 with the public release of v0.3). Since Hydra has been around for so long, it supports a very wide range of modules/attack methods in any tool, and it is still getting updates!

Here are snippets from the documentation (readme.txt, help screens: hydra -h & hydra -U http-post-form, & man page: man hydra).

Debugging Hydra with Burp Proxy

We could use wireshark or tcpdump to monitor what is sent to and from Hydra, as well as use the in-built "debug" flag (-d). However, the issue with all of these is there is an awful lot of data put on the screen, which makes it harder to understand what is going on.

Incomes the use of a "proxy". Rather than it being used in an attempt to "hide your IP" (by using another machine fisrt in order to connect to the target, instead of going directt), we can use it to inspect the traffic. Using Burp Proxy Suite, we can monitor what is being sent to and from our target. This way we can check to see if Hydra is acting in our desired way and reacts correctly when there is a successful login. By using Burp, we are able to quickly filter, sort and compare all of the requests.
It is also worth noting that Hydra does come with a verbose option (-v) to display more information than standard, but not as much as debug!

Let's break down the lines:

rm -f hydra.restore; - when you break from Hydra before the brute force attack is complete, it will automatically create a session file, allowing you to restore. We do not want that now.

export HYDRA_PROXY_HTTP=http://127.0.0.1:8080 - this is a bash variable that instructs Hydra to use a proxy.

hydra - the main program itself

-l admin - a single static username, admin.

-p password - a single static username, password.

-e ns - try a "null" password for the user & "same" username as password

-F - quit after logging in successfully

-t 1 - single thread

-w 5 - timeout value of 5 seconds

-W 1 - wait 1 second before going on to the next thread

-v - enable verbose

-V - show login attempts (will print out username and password combinations)

192.168.1.44 - the target IP

http-get-form - the module to use for the method of the attack

"/DVWA/vulnerabilities/brute/ - the path to the web form to target

:username=^USER^&password=^PASS^&Login=Login - how to use the wordlists in the request.

:F=Username and/or password incorrect. - Failed logins will contain the following string (aka blacklisting)

If we wanted to use the page length instead: :F=Content-Length\: 4945

:H=Cookie\: security=low; PHPSESSID=${SESSIONID}" - the cookie information to send.

Becuase we are debugging, the thread count is set to 1, using a larger timeout value as well as to wait after each thread finishes. This is because, when there are multiple requests being made without any delay, it makes it harder managed and to track Hydra's progress inside of Burp.

Note, if we are going to use Burp, make sure "Invisible Proxy Mode" is enabled (see below)!

Burp's Invisible Proxy Mode

TL;DR: Enable Burp's "Invisible Proxy Mode" when using Hydra.

<rambles>

I noticed when I made the first request, Burp did not detect any GET parameters in the URL. They were missing (e.g. ?username=...).

Checking the web logs on the target, I saw that the parameters were definitely not making it to the target's web server.

As I could see the combinations attempts (-V), Hydra believes that it was sending out the correct combinations. So the next option was using the debug c

Show more