DVWA – Task 0: Brute force main login page login.php

DVWA – Task 0: Brute force main login page login.php

Disclaimer: This tool should not be used to attack websites or services where you do not have permission to do so. Use this for legitimate testing purposes only and Reminder to read README on github

#DVWA #KaliVMserver #Hydra #Developer tools #Security:Impossible #DVWABruteForceLoginPage #DVWABruteForceLogin.php #Curl


In this tutorial, I will explain how I cracked the infamous main login page of DWVA using Hydra. The main login page is the following path; /dvwa/login.php not the actual task which points to /dvwa/vulnerabilities/brute This is not an actual task but in the spirit of brute forcing, why not!

There are very few resources that cover this excercise with a successful command execution or not explained in any great detail. I wanted to make an in depth guide on this task as I can understand how it can be challenging!

Note: the actual/official brute force task points to dvwa/vulnerabilities/bruteforce – check out my other article if you want to delve into that instead! Essentially, we will be brute forcing using the HTTP POST method with CSRF token (user_token)

Here is my Hydra command POC which has successfully brute forced the correct/desired path which is login.php, the correct credential pair, returning only 1 value (not 16 etc) and it’s locally hosted through localhost (also doesn’t matter if you host the DVWA server to localhost or another machine on the network which may have an IP address beginning 192.168). Additionally notice how there are no additional switches to configure the timing or wait times! 


  • Objective – goal of the task
  • Task URL – confirming target
  • Tools – tools required to formulate and execute brute force
  • Setup infrastructure – Preparing our environment
  • Information required for Hydra – High level
  • Information gathering – Reconnaissance
  • Refresh page only
  • Submit an arbitrary login pair
  • Inspecting data
  • Target path
  • PHP session ID
  • Login form in CLI – High level view of login.php page
  • Login form in CLI – Deep dive
  • Login form – view same data in GUI
  • Login form – Inspecting data 
  • Information conclusion – Learns for far
  • Command for Hydra – POC
  • Breaking down the command – Understanding components with rationale
  • Executing Hydra – Full command built ready to brute force
  • Hydra success – Hydra was able to find a match to our condition (flag)
  • Login success – Attempt login using credentials output by Hydra
  • Summary – Outcome broken down
  • Notes
  • Links including a video if you prefer to watch instead!

Objectivegoal of the task

As mentioned, in this video I will be brute forcing the main login page. This is the first page you see when you load up the DVWA as shown, not to be confused with the actual brute force task which relates to path; /dvwa/vulnerabilities/brute

This URL: localhost/dvwa/login.php

Not this URL: localhost/dvwa/vulnerabilities/bruteforce

Task URL confirming target

localhost/dvwa/login.php (you can input and this has no effect on Hydra’s command/brute forcing as the OS will interpret localhost as 

Toolstools required to formulate and execute brute force

  • Hydra – which is a parallelized login guesser, which essentially means it’s a tool for guessing valid login/password pairs – very quickly! You could also use Patator although the syntax is slightly different and also Burp suite (which also replaces the need for web developer tools)
  • DVWA server – I’m using a Kali based server running from a Virtual box VM
  • Firefox browser – GUI web browser option 
  • Web browser developer tools (Ctrl + Shift + I) – built into a browser
  • Curl – CLI based browser option. We need to view source code (also I initially needed to automate token creation but this was not needed which is explained towards the end)
  • Wordlists – Inbuilt wordlist within Kali linux or Seclists

Setup infrastructure – Preparing our environment

  • Start your DVWA web server: sudo service mysql start and then sudo service apache2 start
  • Hydra should come pre-installed in Kali Linux, but if you need to install it then the command is; sudo apt-get install hydra (or hydra-gtk). Note: there was a reported bug in version 9.1 so update to the latest stable repo. To check your version, type; hydra –version
  • Update your repositories; sudo apt-get update && sudo apt-get upgrade -y
  • Launch browser and point to your self hosted DVWA website localhost/dvwa
  • In my setup, I will clear cookies from the web browser (Firefox) to remove any saved data from interfering with the results/attack

Information required for Hydra High level

  • Hostname/IP: this is effectively the DVWA web server folder name
  • URL Service/Method/Scheme: Protocol to access the resource i.e. Whether it is a HTTPS or HTTP service/protocol and; 
  • Form type: GET or POST (or both)
  • Parameters of the request within double quotes;
  • Path: The relative path to the target location
  • Iteration fields: direct Hydra where to iterate field(s) and with what data
  • Flag: establish the difference in response between Success and Failure and which flag to be used
  • Session cookies: Whether any session cookies are required to be set or maintained
  • Lockout features: What lockout features and thresholds apply to the form
  • Wordlists: To allow iteration of respective fields i.e. username and or password field
  • Port number: Port number used should be automatically established by Hydra when the Method/Scheme section is defined. Port number should only need to be set if using a different port to the officially known port numbers or there is error. We will not be defining port number but it will be port 80 which will be visible when the Hydra executes.  This would change to port 443 if we installed an SSL certificate on our web server.

Information gathering – Reconnaissance

Let’s launch firefox and head over to the main login page; localhost/dvwa/login.php and refresh the page and then submit an arbitrary login pair just to observe the traffic inside the Web Developer Tools (Ctrl + Shift + I)

Refresh page only
When we simply refresh the page, we see that there are 3 Methods which are all GET requests

Submit an arbitrary login pair
However, when we enter arbitrary credentials i.e. username = anything and password = anything, we see a change. 

Inspecting data
We notice a POST request in the 2nd field. This implies to me that we maybe dealing with a redirection from the [Apache] web server. After inspecting each method, there is a good indicator that we should pay attention to the POST request. Within the Request tab of this data, we can see the credentials we input. 

Note the other 2 fields do not contain these credentials. The data is telling us that upon submitting credentials, the server responds with a 200 OK message which is a success status response code indicating the request succeeded. The additional information telling us its a GET method means the resource has been fetched and is transmitted in the message body.

The POST method submits our details as this is a login form and hence why the credentials are details in this field. The server response code is 302 the HTTP 302 Found redirect status response code indicates that the resource requested has been temporarily moved to the URL given by the Location header. A browser redirects to said page. This is another indicator that there is a redirect being performed by the web server. 

The server then uses the information submitted to do something. Whilst we assume it will try to authenticate the login details as a valid or invalid user, this has not yet been confirmed albeit this should be the purpose of this server to client communication. To support our current theory, we now have data in the Response tab which states “the requested URL was not found on this server”

That completes the round trip communication that occurs upon submitting a set of arbitrary or incorrect credentials. We may need to refer back to this data to help create a Failure flag for Hydra if appropriate, seen as we have some idea/information on what the output of an incorrect login pair/credential looks like. This explains why we will use the post form method; http-form-post

We can see that the flow/sequence upon submitting a login credential are the following in order (Status code | Method | File);

  1. We request the website page for the URL path (localhost/dvwa/login.php)
  2. 200 | GET | login.php (Server providing the page which rendered the main login page we see)
  3. 302 | POST | login.php (we POST our credentials in the form and submit to the server)
  4. 404 | GET | favicon.ico (Server responds stating Login failed and the HTML response states the requested URL was not found on this server, implying a redirection rule maybe present)

Additional info on server status codes shown:

  • 200 = OK: The resource has been fetched and is transmitted in the message body
  • 302 = Found: The resource requested has been temporarily moved to the URL given by the Location header (another clue of redirection). A browser redirects to the respective page
  • 404 = Not found: The server can not find the requested resource. In the browser, this means the URL is not recognized

Target path
The path to enter the credentials is inside a subfolder /login.php
When you enter localhost/dvwa in the URL field, you are redirected to localhost/dvwa/login.php 

At this stage, we are not sure if this will be useful, but good to build a picture around redirects due to other indicators pointing to this rule/feature which may help later. Here I use Curl which is a command line browser to demonstrate and observe URL path behaviour. Command; curl localhost/dvwa
When we enter this command, we get a response. However when we enter localhost/dvwa/ there is no response! 

We will explore a bit more by adding a curl switch, in this case the -i switch which outputs protocol response headers. When entering curl localhost/dvwa the server (Apache) redirects us to a page which adds a trailing ‘/’ as shown in the Location field. This redirects localhost/dvwa to localhost/dvwa/

The HTTP header status code is 301 Moved Permanently. No field populated for Set-Cookie

When we enter curl -i localhost/dvwa/localhost/ the server redirects to login.php as seen in the Location field. The HTTP status code is 302 Found and there are cookie values as shown in the Set-Cookie fields.

Entering curl -i localhost/dvwa/login.php does not redirect. The HTTP status code is 200 OK and there are cookie values – Set-Cookie fields. 

Now I will instruct curl to follow the links where possible so we reach the end of the communication. This is done by using the -L switch. Command curl -i localhost/dvwa/ -L

When looking at the data given back, we see/understand that the form method is POST and this is where the username, password fields are present. We can also see a “hidden value” which is referred to as a user_token.

PHP session ID
We also notice the presence of session cookie being set in the Set-Cookie field. The name of the cookie is PHPSESSID indicating a cookie which is related to PHP. PHPSESSID is an auto generated session cookie by the server. As the name implies, it should be valid only for that current session. 

This is a method a web application uses to recognise a particular user. Instead of having to store and send the user login credentials each time, the session value is used to provide  authentication instead. The session ID is being stored inside the browser in the form of a cookie. 

We can resubmit the request and notice that both the PHPSESSID and the user_token value refresh, so they’re not static. There appears to be at least some level of security feature present in the infrastructure that we need to consider further.  

However when looking at the Web Developer Tools in Firefox, I noticed that the PHPSESSID remains the same within a single submission because upon looking at the initial 200 GET and the subsequent 302 POST as shown in the Request Headers they are both the same. 

The PHP session ID only changes if we re-submit the form [data]. 

Login form in CLI – High level view of login.php page
High level view of login.php page which relates to the first request – 200 GET request. We can render the login prompt in text form continuing in CLI form (or use a web browsers web dev tools) to get a snapshot of the fields that are given in the response;

Curl localhost/dvw/login.php -L | html2text 

This is the CLI equivalent of refreshing the webpage localhost/dvwa/login.php in a GUI browser. This is the page the server has fetched and given back to fulfil your initial request

Login form in CLI Deep dive
Let’s now look a bit deeper to see what code we submit/post to the server i.e. login credentials. It would be useful to see how this GET request data/page is made up by looking at underlying html code. Code important to us is held within the HTML form tags. We can observe this data from the previous command, but to condense the data to a single page in CLI, we can use sed;  curl -s -i -v "localhost/dvwa/login.php" | sed -n '/<form/,/<\/form/p'

Curl switches
-s silent/quiet mode, which doesn’t show a progress bar or error messages
-i include, which outputs protocol response headers
-v verbose, which adds details to see what is happening/extra information

Sed and switches
sed is a stream editor that works on piped input or files of text. With sed you can do all of the following; select text, substitute text, add lines to text, delete lines from text and Modify (or preserve) an original file.
-n quiet option used to suppress unmatched text

This code provides useful fields of the form (helps formatting/syntax to feed into Hydra). To make it easier to drill down into the areas we need specifically, we can extract the name and value parameters by using grep which is displayed in bold red format

curl -s -i -v "localhost/dvwa/login.php" | sed -n '/<form/,/<\/form/p' | grep -o -E "(name|value)=['\"].*['\"]"

Grep switches  
-o, –only-matching will show only non empty parts of lines that match
-E, –extended-regexp PATTERNS are extended regular expressions

Login form view same data in GUI
Another option to using Curl in CLI, is to use a web browser and it’s inbuilt web developer tools. Or it can be used to cross reference information in GUI form. Whether you use CLI or GUI, the data is the same but I tend to notice key data more easily when comparing between them. 

Login formInspecting data 
An interesting piece of data we have found is the presence of a user_token which is an alphanumeric value (probably a hashed code based on the format and name) submitted along with my arbitrary login pair. 

We can establish what type of hash this could be by using either tunnelsup.com (provides additional information) or hashes.com (WYSIWYG)

After submitting the hash, we have a strong indication this is an MD5 hashing algorithm

I also noticed that this user_token is generated within the 200 GET request and also the 302 POST request but they are different, indicating a fresh token is generated upon each submission. 

Researching user_tokens

  • user tokens are pre-generated
  • user token can’t be used to authenticate to the user interface (e.g., in URLs)
  • user tokens are a form of authentication

When I tried to re-enter/extract a user_token from the developer tools and submit it within a new request to the server, I was presented with a message stating “CSRF token is incorrect”. I’m bringing forward this information here, as I will interchangeably refer to user_tokens (as described by the developer tools/server) as CSRF tokens, or more accurately anti-CSRF tokens, which is the true purpose of this code implementation – I will cover this more in a moment.

Information conclusionLearns for far
Based on the information gathered, I’m equipped with the following information. We have a PHP session ID and an anti-CSRF token which are generated and submitted along with a login pair as part of the authentication process by the server. 

In a single submission, the PHPSESSID remains the same in both the GET and POST request but the user_token will change/refresh in between the GET and POST requests. The session ID is static for a period of time/session. The duration of the session is managed by PHP (settings) and web application. However, the CSRF token is being refreshed/regenerated upon a page request. This is an expected behaviour of a feature which is designed to mitigate a CSRF attack. 

CSRF tokens should not be re-usable and not be known beforehand to ensure they meet their security objective – preventing a CSRF. If they could be re-used then they could be crafted ahead of time which would be a security vulnerability and therefore not fit for purpose as we could extract and use them. To check this theory, I’ll head to the terminal and enter arbitrary values including a random user_token. 

curl -s -i -b dvwa.cookie -d "username=123&password=123&Login=Login&user_token=123" "localhost/dvwa/login.php" -L

We are issued a response stating “CSRF token is incorrect”

Curl switches
-s silent/quiet mode, which doesn’t show a progress bar or error messages
-i include protocol response headers
-b send the data to the HTTP server as a cookie. It is supposedly the data previously received from the server in a “Set-Cookie:” line. The data should be in the format “NAME1=VALUE1; NAME2=VALUE2”
-d HTTP post data
-L follow redirects if the server reports that the requested page has moved – indicated with a Location: header and a 3XX response code

We can also work out when the server has checked/is happy with the user_token value as when we enter arbitrary login credentials into the localhost/dvwa/login.php website, the response is “Login failed”. 

The server is paying attention to the validity of the user_token prior to checking the login credentials. This means even if the login credentials were correct, we still cannot authenticate without a [valid] user_token. The PHP session is handled by PHP, whereas the CSRF token is handled by the web application. It is assumed these codes are being tracked, since it was able to detect me trying to re-use a CSRF token but we appear to be able to re-use a PHP session ID. We can conclude that a session ID (PHPSESSID) and anti-CSRF token (user_token) will need to be crafted and fed into Hydra as part of the brute force command. 

Note: we could have also used curl to pipe the output of submitting a standard login request; curl -s -i localhost/dvwa/login.php > file1.txt vs the output of an incorrect login attempt; curl -s -i -L -d $’username=user&password=pass&user_token=123&Login=Login’ localhost/dvwa/login.php > file2.txt

This would also provide a way to have a baseline and start working out what is different/changes between them. You can input diff='diff --colurauto' to highlight the differences between the files. Then you can compare the files in the following format; diff file1.txt file2.txt                                                                                                                                                                                                        

We’ve now gathered enough information about the infrastructure and have a good idea of how, where and what information to use to formulate our Hydra command. First, I’ll show you the correct working command and the output followed by a full breakdown of how and why the command was built out. 

Command for Hydra – POC

hydra localhost http-form-post "/dvwa/login.php:username=^USER^&password=^PASS^&user_token=${CSRF}&Login=Login:S=index.php:H=Cookie:security=low; PHPSESSID=${SESSIONID}" -l admin -P /usr/share/wordlists/rockyou.txt.gz

Successful brute force command: here is the output to the Hydra command;

[DATA] max 16 tasks per 1 server, overall 16 tasks, 14344399 login tries (l:1/p:14344399), ~896525 tries per task

[DATA] attacking http-post-form://localhost:80/dvwa/login.php:username=^USER^&password=^PASS^&user_token=&Login=Login:S=index.php:H=Cookie:security=low; PHPSESSID=

[80][http-post-form] host: localhost   login: admin   password: password

1 of 1 target successfully completed, 1 valid password found

Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2022-03-07 18:16:06

Breaking down the command – Understanding components with rationale

Although we have already amassed considerable information already, I will obtain some information again to have a better flow, especially for those following from this point on. Additionally, I will try and explain some areas differently which maybe useful and if nothing else, it’s always good to double check and cross reference information to avoid unnecessary errors!

Hydra localhost

This calls the program hydra followed by the hostname or IP which in this instance could also be 


Let’s launch firefox and point to the main login page localhost/dvwa/login.php

And enter arbitrary login credentials. We’ll use the web developer tools (Ctrl + Shift + I) to view the source code. 

When we scroll through the Request data, we find the data relating to credentials being submitted is the 302 POST request. This also reminds us of a redirection from the [Apache] web server. 

This data would usually help crafting a Failure flag for Hydra because we have some clue as to what the output of an incorrect login pair/credential looks like. This explains why we will use the post form method.


This value is simply taken from the URL path from the URL field. This also confirms that we are focusing on the main login page which is /login.php


Using the 302 POST and curl used earlier, we see the values we will need to pass into Hydra which are username and password. We can also see the full HTML form data in the first 200 GET, Response (Raw), which confirms;

<label for="user">Username</label> <input type="text" class="loginInput" size="20" name="username"><br />

This is interpreted as username=^USER^ which converts it into a Hyra friendly syntax. We essentially focus on name and value fields. Same concept applies to the password fields. 


Initially I created a variable to generate user_token and PHPSESSID values. I assumed the token and ID were not literally tied/linked together as a pair (like the connection between a public and private key in cryptography). After spending time experimenting with a variable which generated new/fresh user_tokens and PHPSESSID, for some reason it was not able to brute force. This maybe because the variable generated a fresh set of values but when running the Hydra brute force command, it was only fresh for the first brute force attempt. Theoretically on this basis, it would be re-using the PHPSESSID which testing demonstrated was accepted by the server but not the user_token (removes the ability of preventing CSRF attacks). 

After taking a break I came back to my system and turned it on from a cold boot. I was going through the process of debugging Hydra’s command to see what was happening and I ran my command and it cracked the password! I realised that I didn’t set a variable for the user_token ${CSRF} or the PHP session ID (PHPSESSID). 

I confirmed my variables were empty by running echo $CSRF and $SESSIONID which returned empty. I ran the command in debugging mode so I  could try to understand why it was working as essentially I inserted a placeholder for these values without configuring a variable.  

In debugging mode, I could see that PHP session ID’s and CSRF tokens were being generated hence why the brute force was successful. I learned that when using a placeholder without a value, the server appeared to be assign a value instead. This meant that the server was generating the values itself (in whichever way and method it was designed), hence it would always be valid!

I will show you the command in debug mode in Hydra which is the -d switch, the -v switch which let’s us correlate the password attempt into the human readable form and also the -F switch which stops the command execution once a valid credential found so we have a way cutting off/separating the data which may seem overwhelming. I’ll also put this output in a file which I’ll create a link to if you want to inspect it yourself (hydrasuccessdebug.txt).


This input is taken from the 200 GET, Response data. We are mimicking the equivalent of physically clicking login or the enter key on our keyboard after each login attempt. 

The code shows as; <p class="submit"><input type="submit" value="Login" name="Login"></p>

Technically we are after the name and value fields which are Login and submit respectively. Using Login=Login is also accepted by Hydra (both inputs work).


Normally I don’t use the Success flag (S=something is a success flag i.e. something you instruct Hydra to look for whereas F=something is a failure flag instructing Hydra to ignore everything which has this value, similar concept to a firewall). You are more likely to know the output of a failure message than a successful message, that said, there are some situations where you can obtain a success message i.e. creating a new user on a website to discover a success message. 

I initially played around with Failure flags but these attempts took a ridiculously long time. In theory a failure flag such as F=login.php should work smoothly but whilst I was experimenting, I was successful using a Success flag, where the results returned far quicker than the results of my Failure flag. In the end I did not wait around long enough for the Failure flag command to finish executing .To clarify, I’m not saying the F=login.php won’t work, just that my trial with this failure flag ended up being inconclusive. 

So what was my logic behind using a Success flag given that I was intending to use a Failure flag? When we enter incorrect credentials, we are “redirected” back to the login page to try again – normal and somewhat expected behaviour, along with some kind of error message. Both of which occurred in our case – we’re redirected back to /login.php and the error message is “Login failed”

However, I anticipated the same would not be logical if you entered the correct credentials (still unknown at this stage). In this case you should be redirected to a some sort of “user welcome” area, which to me would be a standard and sensible login workflow. So, if you enter incorrect login credentials, you are sent back to /login.php to try again, so my logic is that you would not be sent back to to this same path if you entered the correct login credentials. I now have an idea of what not to look for (Failure flag) but not something it [Hydra] should look for (Success flag). As explained, the Failure flag was not working, perhaps due to the redirection in play. 

Leaning on some experience from web development, I knew that inputting /index.php at the end of the main URL/domain can redirect to the root folder/home page. This is essentially what I wanted to do so that I could get the server to generate [valid] user_tokens and PHPSESSID (and anything else that I could have potentially missed!), so I tried it in a web browser (Firefox) and entered localhost/dvwa/index.php which redirected to localhost/dvwa

I attempted the same process in curl and I got redirected to /login.php 

Brilliant, this is the behaviour I wanted!

This theory did indeed work and it was my first guess! Here we can see the Location field is /login.php i.e. where we wanted the server to redirected us to. Hydra was able to better detect a Successful login path and completed the attack very quickly without any additional switches to configure the timing or wait times. It would have been fun to work this out but in reality, guess work is also a valid methodology! If this didn’t work then I’d dig deeper into finding out why my Failure flags weren’t working i.e. deep dive into redirects and using Hydra in debugging mode! 

A short time later…My OCD kicked in and I wanted to find out anyway! 

After doing some further research and using curl, it appears that we can send as many POST requests as we like reusing the same PHPSESSID and user_token as long as we do not follow redirects i.e. avoid using the -L switch in Curl

When sending a GET request to follow the redirect, a new user_token is generated. Whilst this maybe a good security feature, it means we can’t use the error output of entering incorrect login credentials; “Login failed” as a failure flag because this is only valid with a GET request. If using Burp suite, then it would probably rule out Content-Length as an indicator, as it will always be 0.

Note: I also checked to see what would happen trying login.php as a Success flag anyway just to see what happens. This resulted in 16 “valid passwords found”. Clearly this is showing us false positives as there is only 1 correct login pair. 

:H=Cookie:security=low; PHPSESSID=${SESSIONID}" 

The easiest way to extract the cookie related fields (including the PHP session ID/PHPSESSID) is to look at the 200 GET, Headers, Request headers, Raw. We can easily copy/paste the Cookie related data. We start the line using :H=Cookie:

For the PHPSESSID (and user_token), I mentioned that I created variables which later were not required, so these ended up being empty placeholders. Initially it seemed the PHPSESSID and CSRF token were implemented somewhat securely as we couldn’t reuse the CSRF token, they were being generated fresh and the server was keeping track of the codes. However as my brute force attempt worked without even setting the variables, it turns out that it may not have been implemented securely/correctly after all.

To reconfirm if the login submission is generating a fresh set of data for the user_token and/or the PHPSESSID we can quickly check again using Curl. 

curl -i -u anything:anything http://localhost/dvwa/login.php

Curl switches:
-i displays header information and -u allows input of the username and password fields)

User_token: <input type=’hidden’ name=‘user_token’ value=’c2334c47c8e7eaeb6962e44d337b9410′ />

PHPSESSID: Set-Cookie: PHPSESSID=5fbl3rq1gec60l9fjmksrodogc; path=/

Now if we submit the request again (press the UP arrow key to recall the last command) and enter, we can see a new PHPSESSID and user_token is generated;

-l admin -P /usr/share/wordlists/rockyou.txt.gz

These values instruct Hydra to use the username admin (therefore not bruteforce username field) but brute force the password field using a file/list in the path given (rockyou.txt). I have pre-fed the username admin in case we need to troubleshoot as it just saves time during the brute force process in case the command doesn’t work. 

Executing Hydra – Full command built ready to brute force

Once the command is pieced together, Hydra should be able to find the correct login pair;

Hydra success Hydra was able to find a match to our condition (flag)
Hydra was able to use the Success flag (S=index.php) to identify the login credential that when attempted, results in a response which has index.php. Remember, that we are assuming that a valid login is linked to being redirected to a page other than login.php. At this stage, we are assuming it could be index.php (just something different to login.php)

Hydra doesn’t know at this stage that the user credentials are correct, it just knows that it found a response which matches the Success flag condition upon entering these credentials (highlighted in the terminal as a bold-turquoise colour). We now need to actually try these credentials to verify they are correct and our theory up until now can be proven to achieve the goal of successful login..

Login success Attempt login using credentials output by Hydra
Here is the result of inputting the login credential filtered out by Hydra; 

SummaryOutcome broken down
We can now confirm the following;

  • we have successfully logged in to the DVWA
  • Hydra has found the correct login credentials; username:admin password: password
  • The success flag was effective in finding our desired credentials
  • We are redirected to dvwa/index.php and this was the “welcome login area”
  • Web server uses the POST method to submit login credentials

Notes – any other information to add

Be careful with syntax, Hydra is very unforgiving with syntax so this should be the first thing you check before moving onto more complex fixes and investigations. 

On other similar brute force tasks, you may submit a GET form instead of a POST. This will vary so it always pays to investigate and poke around with the infrastructure to get a baseline of how things communicate in the environment. 

The debug tool in Hydra was useful so we could inspect the traffic and see the underlying communication. This meant that I didn’t need to setup the environment again in Burp suite purley for the purposes of inspecting the traffic using the proxy. 

I realised that the command works when inputting security:low even though it is and should be security:impossible

That concludes extracting the correct login credentials on the main login page, login.php using Hydra. I hope you find my resource useful and if you want to bring anything to my attention then feel free to connect!