Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect passwordless Accounts #84

Closed
isotopp opened this issue Dec 18, 2022 · 2 comments
Closed

Detect passwordless Accounts #84

isotopp opened this issue Dec 18, 2022 · 2 comments
Labels
check This is a new type of check to be implemented

Comments

@isotopp
Copy link

isotopp commented Dec 18, 2022

Cadfael should detect accounts with no password.

In MySQL 8.0

mysql> create user cookie@"%";
mysql> select user, host, plugin, authentication_string from user where authentication_string = "";
...
| keks             | %         | caching_sha2_password |                                                                        |
...
  • Cadfael should flag accounts with an empty or NULL authentication_string field.

In MySQL 5.7

mysql [localhost:5734] {msandbox} (mysql) > select user, host, plugin, authentication_string from user where authentication_string = "";
+------+------+-----------------------+-----------------------+
| user | host | plugin                | authentication_string |
+------+------+-----------------------+-----------------------+
| keks | %    | mysql_native_password |                       |
+------+------+-----------------------+-----------------------+
1 row in set (0.00 sec)
  • Cadfael should flag account with an empty or NULL authentication_string field.

In MySQL 5.6

mysql [localhost:5644] {msandbox} (mysql) > select user, host, password, plugin, authentication_string from user where user = "keks";
+------+------+----------+-----------------------+-----------------------+
| user | host | password | plugin                | authentication_string |
+------+------+----------+-----------------------+-----------------------+
| keks | %    |          | mysql_native_password |                       |
+------+------+----------+-----------------------+-----------------------+
1 row in set (0.00 sec)
  • Cadfael should flag accounts with an empty Password field, if the plugin field has the value mysql_native_password.

In MySQL 5.5

mysql [localhost:5562] {msandbox} (mysql) > select user, host, password, plugin, authentication_string from user where user = "keks";
+------+------+----------+--------+-----------------------+
| user | host | password | plugin | authentication_string |
+------+------+----------+--------+-----------------------+
| keks | %    |          |        | NULL                  |
+------+------+----------+--------+-----------------------+
1 row in set (0.00 sec)
  • Cadfael should flag accounts with an empty Password field, if the plugin field is NULL or empty.
@isotopp
Copy link
Author

isotopp commented Dec 18, 2022

MySQL 5.5

As of MySQL 5.5.7, the mysql.user table has plugin and authentication_string columns for storing authentication plugin information.

If the plugin column for an account row is empty, the server uses its built-in authentication for connection attempts for the account. Clients must match the password in the Password column of the account row.

If an account row names a plugin in the plugin column, the server uses it to authenticate connection attempts for the account. Whether the plugin uses the value in the Password column is up to the plugin.

http://doc.docs.sk/mysql-refman-5.5/grant-table-structure.html

MySQL 5.6

The user table plugin, Password, and authentication_string columns store authentication plugin and credential information.

If an account row names a plugin in the plugin column, the server uses it to authenticate connection attempts for the account. It is up to the plugin whether it uses the Password and authentication_string column values.

If the plugin column for an account row is empty, the server authenticates the account using the mysql_native_password or mysql_old_password plugin implicitly, depending on the format of the password hash in the Password column. If the Password value is empty or a 4.1 password hash (41 characters), the server uses mysql_native_password. If the password value is a pre-4.1 password hash (16 characters), the server uses mysql_old_password. (For additional information about these hash formats, see Section 6.1.2.4, “Password Hashing in MySQL”.) Clients must match the password in the Password column of the account row.

https://dev.mysql.com/doc/refman/5.6/en/grant-tables.html

MySQL 5.7

https://dev.mysql.com/doc/refman/5.7/en/grant-tables.html

The Password column no longer exists.
It is no longer legal to have empty values in the plugin column (see also).
The mysql_old_password authentication is no longer supported.

MySQL 8.0

https://dev.mysql.com/doc/refman/8.0/en/grant-tables.html

In 8.0, the password storage default changes to caching_sha2_password, but mysql_native_password is still supported.
A lot of client libraries from external vendors do not yet support caching_sha2_password, so use of mysql_native_password is common.

Authentication got really compliated in 8.0:

  • Accounts can have multiple (2) passwords for password rotation (this is stupid, you want account rotation).
  • Accounts can have multi-factor-authentication (see also).

@xsist10 xsist10 added the check This is a new type of check to be implemented label Dec 26, 2022
xsist10 added a commit that referenced this issue Jan 1, 2023
Accounts without passwords should be flagged to avoid unintended
exposure. This goes doubly for accounts that are accessible outside
of localhost.

We don't currently case too much about what they have access to.
We could examine if they only have read access (and whether it's
limited to "monitoring" schemas like mysql or performance_schema)
but that's a future refinement once we see what hits we get.

Also required some refactoring of various bits of code and some
hint at the newer structure for data objects (heading towards
using readonly classes, using proper enums and named parameters
which means this also bumps our requirements up to PHP 8.* as well).

Ideally I want to be able to support multiple data sources (database,
SQL definition files, etc) without massive refactoring.
@xsist10
Copy link
Owner

xsist10 commented Jan 1, 2023

xsist10 added a commit that referenced this issue Jan 3, 2023
Added Passwordless Account check (#84)
@xsist10 xsist10 closed this as completed Jan 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
check This is a new type of check to be implemented
Projects
None yet
Development

No branches or pull requests

2 participants