#
# This script is Copyright (C) 2004-2021 and is owned by Tenable, Inc. or an Affiliate thereof.
#
# This script is released under the Tenable Subscription License and
# may not be used from within scripts released under another license
# without authorization from Tenable, Inc.
#
# See the following licenses for details:
#
# http://static.tenable.com/prod_docs/Nessus_6_SLA_and_Subscription_Agreement.pdf
#
# @PROFESSIONALFEED@
# $Revision: 1.0 $
# $Date: 2021/09/21 $
#
# Description : This document implements the security configuration as recommended by the
# CIS Oracle MySQL 8.0 Enterprise Edition v1.1.0 Benchmark
#
#
#CIS MySQL 8.0 Enterprise Database L1 v1.1.0
#
# CIS
# MySQL 8.0 Enterprise Database L1
# 1.1.0
# https://workbench.cisecurity.org/files/3477
#
#database,cis,mysql,mysql_8,mysql_8.0,mysql_8.0_enterprise
#LEVEL,CIS_Recommendation
#
type : SQL_POLICY
description : "MySQL 8.0 is installed"
sql_request : "show variables like 'version' ;"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "version", regex:"8\..*"
check_option : CAN_NOT_BE_NULL
type : SQL_POLICY
description : "MySQL 8.0 Enterprise Edition is installed"
sql_request : "show variables like 'license' ;"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "license", "Commercial"
check_option : CAN_NOT_BE_NULL
description : "CIS_MySQL_8.0_Enterprise_Benchmark_v1.1.0_Level_1_DB.audit from CIS Oracle MySQL 8.0 Enterprise Edition v1.1.0"
see_also : "https://workbench.cisecurity.org/files/3477"
type : SQL_POLICY
description : "1.1 Place Databases on Non-System Partitions"
info : "It is generally accepted that host operating systems should include different filesystem partitions for different purposes. One set of filesystems is typically called system partitions, and these are generally reserved for host system/application operation. The other set of filesystems is typically called 'non-system partitions', and such locations are generally reserved for storing data.
Rationale:
Moving the database off the system partition will reduce the probability of denial of service caused by exhaustion of available disk space to the operating system.
Impact:
Moving database files and directories to a non-system partition may be difficult depending on whether there was only a single partition when the operating system was set up and whether there are additional non-system partitions available."
solution : "Perform the following steps to remediate this setting for the datadir:
Backup the database.
Choose a non-system partition new location for MySQL data.
Stop mysqld using a command like: service mysql stop.
Copy the data using a command like: cp -rp.
Set the datadir location to the new location in the MySQL configuration file.
Start mysqld using a command like: service mysql start.
Note: On some Linux distributions you may need to additionally modify apparmor settings. For example, on a Ubuntu 14.04.1 system edit the file /etc/apparmor.d/usr.sbin.mysqld so that the datadir access is appropriate. The original might look like this:
# Allow data dir access
/var/lib/mysql/ r,
/var/lib/mysql/** rwk,
Alter those two paths to be the new location you chose above. For example, if that new location were /media/mysql, then the /etc/apparmor.d/usr.sbin.mysqld file should include something like this:
# Allow data dir access
/media/mysql/ r,
/media/mysql/** rwk,
Default Value:
Not Applicable."
reference : "800-53|SC-5(2),CIS_Recommendation|1.1,CSF|PR.DS-4,ITSG-33|SC-5(2),LEVEL|1M,NESA|T3.3.1,NIAv2|GS8e,NIAv2|GS10c,QCSC-v1|8.2.1,SWIFT-CSCv1|6.4"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "show variables like 'datadir' ;"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "datadir", regex:".+"
type : SQL_POLICY
description : "2.5 Do Not Reuse Usernames"
info : "Database user accounts should not be reused for multiple applications or users.
Rationale:
Utilizing unique database accounts across applications will reduce the impact of a compromised MySQL account.
Impact:
If a user is reused, then a compromise of this user will compromise multiple parts of the system and/or application.
NOTE: Nessus has provided the target output to assist in reviewing the benchmark to ensure target compliance.
NOTE: Nessus has provided the target output to assist in reviewing the benchmark to ensure target compliance."
solution : "Add/Remove users so that each user is only used for one specific purpose."
reference : "800-171|3.5.7,800-53|IA-5(1)(a),CIP|007-6-R5.5,CIS_Recommendation|2.5,CN-L3|7.1.2.7(e),CN-L3|7.1.3.1(b),CSF|PR.AC-1,HIPAA|164.308(a)(5)(ii)(D),ISO/IEC-27001|A.9.4.3,ITSG-33|IA-5(1)(a),LEVEL|1M,NESA|T5.2.3,NIAv2|AM19a,NIAv2|AM19b,NIAv2|AM19c,NIAv2|AM19d,NIAv2|AM22a,PCI-DSSv3.1|8.2.3,PCI-DSSv3.2|8.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2,SWIFT-CSCv1|4.1,TBA-FIISB|26.2.1,TBA-FIISB|26.2.4"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT host, user, plugin, IF(plugin = 'mysql_native_password', 'WEAK SHA1', 'STRONG SHA2') AS HASHTYPE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys') AND plugin NOT LIKE 'auth%' AND plugin <> 'mysql_no_login' AND LENGTH(authentication_string) > 0 ORDER BY plugin;"
sql_types : POLICY_VARCHAR
sql_expect : "ManualReviewRequired"
severity : MEDIUM
type : SQL_POLICY
description : "2.7 Ensure 'password_lifetime' is Less Than or Equal to '365'"
info : "Password expiration provides users with a unique time bounded password lifetime.
Rationale:
Allows additional security factors pertinent to a specific user to provide further password security; predetermined by varying security needs and usability requirements in a system or organization."
solution : "To configure the global password lifetime to 365 by executing the following command:
set persist default_password_lifetime = 365;
Alternatively, configure the password lifetime for each user returned by the audit procedure by executing the following command:
ALTER USER ''@'' PASSWORD EXPIRE INTERVAL 365 DAY;
Default Value:
NULL"
reference : "800-171|3.5.2,800-53|IA-5(1)(d),CIP|007-6-R5.6,CIS_Recommendation|2.7,CN-L3|7.1.2.7(e),CN-L3|7.1.3.1(b),CSF|PR.AC-1,HIPAA|164.308(a)(5)(ii)(D),ISO/IEC-27001|A.9.4.3,ITSG-33|IA-5(1)(d),LEVEL|1A,NESA|T5.2.3,NIAv2|AM20,NIAv2|AM21,PCI-DSSv3.1|8.2.4,PCI-DSSv3.2|8.2.4,QCSC-v1|5.2.2,QCSC-v1|13.2,SWIFT-CSCv1|4.1,TBA-FIISB|26.2.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT VARIABLE_NAME, VARIABLE_VALUE FROM performance_schema.global_variables where VARIABLE_NAME like 'default_password_lifetime';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "default_password_lifetime", regex:"\b(?:36[0-5]|3[0-5]\d|[12]\d{2}|[1-9]\d?)\b"
check_option : CAN_NOT_BE_NULL
type : SQL_POLICY
description : "2.8 Ensure Password Complexity is Configured"
info : "Passwords that are too complex in nature make it harder for users to remember, leading to bad practices. In addition, composition requirements provide no defense against common attack types such as social engineering or insecure password storage. In keeping with the overall goal of having users create a password that is not overly weak, it's best to have at least 14 characters for a password only account.
Rationale:
Malicious actors regularly attempt to compromise databases by attacking or guessing passwords. Stolen credentials may be used to gain access to steal information, engage in financial fraud, and more.
By enforcing practical and secure policies, end user cooperation grows. In general, longer passwords are better (harder to crack), but a forced password length requirement can cause user behavior that is predictable and undesirable. Having a reasonable minimum length with no maximum character limit increases the resulting average password length used and thus increases the security of that password.
Impact:
Enforcing too much complexity or length may be difficult for users to memorize. This may cause users to use predictable patterns or other bad practices, resulting in weaker passwords."
solution : "If not already installed, install the password policy component:
INSTALL COMPONENT 'file://component_validate_password';
Set password policies in accordance with the organizationally defined policy and security best practices:
set persist validate_password.check_user_name='ON';
set persist validate_password.dictionary_file='';
set persist validate_password.length=14;
Use with care. Passwords that are too complex in nature make it harder for users to remember, leading to bad practices.
set persist validate_password.mixed_case_count=1;
set persist validate_password.special_char_count=1;
set persist validate_password.number_count=1;
Default Value:
The MySQL validate password complexity component is not installed by default."
reference : "800-171|3.5.2,800-53|IA-5(1),CIS_Recommendation|2.8,CSF|PR.AC-1,ITSG-33|IA-5(1),LEVEL|1A,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2,SWIFT-CSCv1|4.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT component_urn from mysql.component WHERE component_urn='file://component_validate_password' group by component_urn;"
sql_types : POLICY_VARCHAR
sql_expect : "file://component_validate_password"
check_option : CAN_NOT_BE_NULL
type : SQL_POLICY
description : "2.9 Ensure Password Resets Require Strong Passwords - password_history"
info : "Disabling password reuse, enforcing password strength, and denying reuse can be implemented to prevent successful usage of stolen or previously guessed passwords by malicious users.
Restricted accounts using passwords on the basis of the number of password changes and length ensure a password cannot be chosen from a specified number of the most recent passwords.
Rationale:
Repeated use of old passwords can increase risk of a compromise. This may lead to access by malicious users who have discovered a user's prior password(s)."
solution : "Set a global policy that passwords may not be reused for a minimum of five password changes:
SET PERSIST password_history = 5;
Set a global policy that passwords have a lifetime to approximately one year (in days)
SET PERSIST password_reuse_interval = 365;
Default Value:
Both password_history and password_reuse_interval are 0 (off) by default."
reference : "800-171|3.5.2,800-53|IA-5(1),CIS_Recommendation|2.9,CSF|PR.AC-1,ITSG-33|IA-5(1),LEVEL|1A,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2,SWIFT-CSCv1|4.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : " SELECT VARIABLE_NAME, VARIABLE_VALUE FROM performance_schema.global_variables where VARIABLE_NAME in ('password_history');"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "password_history", regex:"^[1-9][0-9]*$"
check_option : CAN_NOT_BE_NULL
type : SQL_POLICY
description : "2.9 Ensure Password Resets Require Strong Passwords - password_reuse_interval"
info : "Disabling password reuse, enforcing password strength, and denying reuse can be implemented to prevent successful usage of stolen or previously guessed passwords by malicious users.
Restricted accounts using passwords on the basis of the number of password changes and length ensure a password cannot be chosen from a specified number of the most recent passwords.
Rationale:
Repeated use of old passwords can increase risk of a compromise. This may lead to access by malicious users who have discovered a user's prior password(s)."
solution : "Set a global policy that passwords may not be reused for a minimum of five password changes:
SET PERSIST password_history = 5;
Set a global policy that passwords have a lifetime to approximately one year (in days)
SET PERSIST password_reuse_interval = 365;
Default Value:
Both password_history and password_reuse_interval are 0 (off) by default."
reference : "800-171|3.5.2,800-53|IA-5(1),CIS_Recommendation|2.9,CSF|PR.AC-1,ITSG-33|IA-5(1),LEVEL|1A,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2,SWIFT-CSCv1|4.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : " SELECT VARIABLE_NAME, VARIABLE_VALUE FROM performance_schema.global_variables where VARIABLE_NAME in ('password_reuse_interval');"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "password_reuse_interval", regex:"^[1-9][0-9]*$"
check_option : CAN_NOT_BE_NULL
type : SQL_POLICY
description : "2.19 Implement Connection Delays to Limit Failed Login Attempts - CONNECTION_CONTROL"
info : "MySQL Server can enable administrators to introduce an increasing delay in server response to clients after a certain number of consecutive failed connection attempts.
Rationale:
Delaying connection attempts provides a deterrent that slows down brute force attacks that attempt to access MySQL user accounts."
solution : "Add the following lines to my.cnf:
[mysqld]
plugin-load-add=connection_control.so
connection-control=FORCE_PLUS_PERMANENT
connection-control-failed-login-attempts=FORCE_PLUS_PERMANENT
connection_control_failed_connections_threshold=5
connection_control_min_connection_delay=60000
connection_control_max_connection_delay=1920000
Delays are in milliseconds for server response to failed connection attempt.
60000 (ms - 1 minute)
1920000 (ms, 32 minutes)
For each user set
ALTER USER FAILED_LOGIN_ATTEMPTS 12;"
reference : "800-171|3.5.2,800-53|IA-5.,CIS_Recommendation|2.19,CSF|PR.AC-1,ITSG-33|IA-5,LEVEL|1A,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE ('CONNECTION_CONTROL');"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "CONNECTION_CONTROL", regex:"ACTIVE"
check_option : CAN_NOT_BE_NULL
type : SQL_POLICY
description : "2.19 Implement Connection Delays to Limit Failed Login Attempts - CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS"
info : "MySQL Server can enable administrators to introduce an increasing delay in server response to clients after a certain number of consecutive failed connection attempts.
Rationale:
Delaying connection attempts provides a deterrent that slows down brute force attacks that attempt to access MySQL user accounts."
solution : "Add the following lines to my.cnf:
[mysqld]
plugin-load-add=connection_control.so
connection-control=FORCE_PLUS_PERMANENT
connection-control-failed-login-attempts=FORCE_PLUS_PERMANENT
connection_control_failed_connections_threshold=5
connection_control_min_connection_delay=60000
connection_control_max_connection_delay=1920000
Delays are in milliseconds for server response to failed connection attempt.
60000 (ms - 1 minute)
1920000 (ms, 32 minutes)
For each user set
ALTER USER FAILED_LOGIN_ATTEMPTS 12;"
reference : "800-171|3.5.2,800-53|IA-5.,CIS_Recommendation|2.19,CSF|PR.AC-1,ITSG-33|IA-5,LEVEL|1A,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE ('CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS');"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS", regex:"ACTIVE"
check_option : CAN_NOT_BE_NULL
type : SQL_POLICY
description : "2.19 Implement Connection Delays to Limit Failed Login Attempts - connection_control_failed_connections_threshold"
info : "MySQL Server can enable administrators to introduce an increasing delay in server response to clients after a certain number of consecutive failed connection attempts.
Rationale:
Delaying connection attempts provides a deterrent that slows down brute force attacks that attempt to access MySQL user accounts."
solution : "Add the following lines to my.cnf:
[mysqld]
plugin-load-add=connection_control.so
connection-control=FORCE_PLUS_PERMANENT
connection-control-failed-login-attempts=FORCE_PLUS_PERMANENT
connection_control_failed_connections_threshold=5
connection_control_min_connection_delay=60000
connection_control_max_connection_delay=1920000
Delays are in milliseconds for server response to failed connection attempt.
60000 (ms - 1 minute)
1920000 (ms, 32 minutes)
For each user set
ALTER USER FAILED_LOGIN_ATTEMPTS 12;"
reference : "800-171|3.5.2,800-53|IA-5.,CIS_Recommendation|2.19,CSF|PR.AC-1,ITSG-33|IA-5,LEVEL|1A,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT VARIABLE_NAME, VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME LIKE 'connection_control_failed_connections_threshold';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "connection_control_failed_connections_threshold", regex:"[5-9]|[1-9][0-9]"
check_option : CAN_NOT_BE_NULL
type : SQL_POLICY
description : "2.19 Implement Connection Delays to Limit Failed Login Attempts - connection_control_min_connection_delay"
info : "MySQL Server can enable administrators to introduce an increasing delay in server response to clients after a certain number of consecutive failed connection attempts.
Rationale:
Delaying connection attempts provides a deterrent that slows down brute force attacks that attempt to access MySQL user accounts."
solution : "Add the following lines to my.cnf:
[mysqld]
plugin-load-add=connection_control.so
connection-control=FORCE_PLUS_PERMANENT
connection-control-failed-login-attempts=FORCE_PLUS_PERMANENT
connection_control_failed_connections_threshold=5
connection_control_min_connection_delay=60000
connection_control_max_connection_delay=1920000
Delays are in milliseconds for server response to failed connection attempt.
60000 (ms - 1 minute)
1920000 (ms, 32 minutes)
For each user set
ALTER USER FAILED_LOGIN_ATTEMPTS 12;"
reference : "800-171|3.5.2,800-53|IA-5.,CIS_Recommendation|2.19,CSF|PR.AC-1,ITSG-33|IA-5,LEVEL|1A,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT VARIABLE_NAME, VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME LIKE 'connection_control_min_connection_delay';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "connection_control_min_connection_delay", regex:"(6000\d|600[1-9]\d|60[1-9]\d{2}|6[1-9]\d{3}|[7-9]\d{4}|[1-9]\d{5,8}|1\d{9}|20\d{8})"
check_option : CAN_NOT_BE_NULL
type : SQL_POLICY
description : "2.19 Implement Connection Delays to Limit Failed Login Attempts - connection_control_max_connection_delay"
info : "MySQL Server can enable administrators to introduce an increasing delay in server response to clients after a certain number of consecutive failed connection attempts.
Rationale:
Delaying connection attempts provides a deterrent that slows down brute force attacks that attempt to access MySQL user accounts."
solution : "Add the following lines to my.cnf:
[mysqld]
plugin-load-add=connection_control.so
connection-control=FORCE_PLUS_PERMANENT
connection-control-failed-login-attempts=FORCE_PLUS_PERMANENT
connection_control_failed_connections_threshold=5
connection_control_min_connection_delay=60000
connection_control_max_connection_delay=1920000
Delays are in milliseconds for server response to failed connection attempt.
60000 (ms - 1 minute)
1920000 (ms, 32 minutes)
For each user set
ALTER USER FAILED_LOGIN_ATTEMPTS 12;"
reference : "800-171|3.5.2,800-53|IA-5.,CIS_Recommendation|2.19,CSF|PR.AC-1,ITSG-33|IA-5,LEVEL|1A,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT VARIABLE_NAME, VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME LIKE 'connection_control_max_connection_delay';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "connection_control_max_connection_delay", regex:"(192000\d|19200[1-9]\d|1920[1-9]\d{2}|192[1-9]\d{3}|19[3-9]\d{4}|[2-9]\d{6}|[1-9]\d{7,8}|1\d{9}|20\d{8}|21[0-9]\d{9})"
check_option : CAN_NOT_BE_NULL
type : SQL_POLICY
description : "3.1 Ensure 'datadir' Has Appropriate Permissions - datadir Has Appropriate Permissions and Ownership"
info : "The data directory is the location of the MySQL databases.
Rationale:
Limiting the accessibility of these objects will protect the confidentiality, integrity, and availability of the MySQL database. If someone other than the MySQL user is allowed to read files from the data directory, it may be possible to read data from the mysql.user table which contains passwords. Additionally, the ability to create files can lead to denial of service, or might otherwise allow someone to gain access to specific data by manually creating a file with a view definition."
solution : "Execute the following commands at a terminal prompt:
chmod 750
chown mysql:mysql "
reference : "800-53|SC-5(2),CIS_Recommendation|3.1,CSF|PR.DS-4,ITSG-33|SC-5(2),LEVEL|1A,NESA|T3.3.1,NIAv2|GS8e,NIAv2|GS10c,QCSC-v1|8.2.1,SWIFT-CSCv1|6.4"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "show variables like 'datadir';"
sql_types : POLICY_VARCHAR
sql_expect : regex :".+"
type : SQL_POLICY
description : "3.2 Ensure 'log_bin_basename' ob体育s Have Appropriate Permissions - log_bin_basename ob体育s Have Appropriate Permissions and Ownership"
info : "MySQL can operate using a variety of log files, each used for different purposes. These are the binary log (which can be encrypted), error log, slow query log, relay log, general log, and in the enterprise edition, the audit log (which can be encrypted). Because these are files on the host operating system, they are subject to the permissions and ownership structure provided by the host and may be accessible by users other than the MySQL user. Additionally, using secure key management and at rest MySQL encryption can further protect data from OS users.
Rationale:
Limiting the accessibility of these objects will protect the confidentiality, integrity, and availability of the MySQL logs.
Impact:
Changing the permissions and ownership of the relay logs and binary log files might have impact on external tools.
If the permissions on the relay logs and binary log files are accidentally changed to exclude the user account which is used to run the MySQL service, then this might break replication.
The binary log file can be used for point-in-time recovery so this can also affect backup, restore, and disaster recovery procedures."
solution : "Execute the following command for each log file location requiring corrected permissions and ownership:
chmod 660
chown mysql:mysql "
reference : "800-53|SC-5(2),CIS_Recommendation|3.2,CSF|PR.DS-4,ITSG-33|SC-5(2),LEVEL|1A,NESA|T3.3.1,NIAv2|GS8e,NIAv2|GS10c,QCSC-v1|8.2.1,SWIFT-CSCv1|6.4"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "show variables like 'log_bin_basename';"
sql_types : POLICY_VARCHAR
sql_expect : regex :".+"
type : SQL_POLICY
description : "3.3 Ensure 'log_error' Has Appropriate Permissions - log_error Has Appropriate Permissions and Ownership"
info : "MySQL can operate using a variety of log files, each used for different purposes. These are the binary log (which can be encrypted), error log, slow query log, relay log, general log, and in the enterprise edition, the audit log (which can be encrypted). Because these are files on the host operating system, they are subject to the permissions and ownership structure provided by the host and may be accessible by users other than the MySQL user. Additionally, using secure key management and at rest MySQL encryption can further protect data from OS users.
Much of the information about the state of MySQL exists in MySQL, the MySQL performance_schema or informations_schema. In cases where the information you need is within a running MySQL, use these methods as they are more secure as do not require OS login and access.
Rationale:
Limiting the accessibility of these objects will protect the confidentiality, integrity, and availability of the MySQL logs.
Impact:
Changing the permissions of the error log files might have impact on monitoring tools which use an error log file adapter."
solution : "Execute the following command for each log file location requiring corrected permissions and ownership:
chmod 600
chown mysql:mysql "
reference : "800-171|3.3.8,800-171|3.3.9,800-53|AU-9(4),CIS_Recommendation|3.3,CN-L3|8.1.4.3(d),CSF|PR.PT-1,ISO/IEC-27001|A.12.4.2,ITSG-33|AU-9(4),ITSG-33|AU-9(4)(a),ITSG-33|AU-9(4)(b),LEVEL|1A,NESA|M1.2.2,NESA|M5.2.3,NESA|M5.5.2,NIAv2|SM5,NIAv2|SM6,QCSC-v1|8.2.1,QCSC-v1|13.2,SWIFT-CSCv1|5.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "show variables like 'log_error';"
sql_types : POLICY_VARCHAR
sql_expect : regex :".+"
type : SQL_POLICY
description : "3.4 Ensure 'slow_query_log' Has Appropriate Permissions - slow_query_log Has Appropriate Permissions and Ownership"
info : "MySQL can operate using a variety of log files, each used for different purposes. These are the binary log (which can be encrypted), error log, slow query log, relay log, general log, and in the enterprise edition, the audit log (which can be encrypted). Because these are files on the host operating system, they are subject to the permissions and ownership structure provided by the host and may be accessible by users other than the MySQL user. Additionally, using secure key management and at rest MySQL encryption can further protect data from OS users.
Much of the information about the state of MySQL exists in MySQL, the MySQL performance_schema or informations_schema. If you can get the information you need from within MySQL that is more secure as it does not require OS access. If you are not going to use log files it is best to first disable (don't enable) and remove any prior logs.
Rationale:
Limiting the accessibility of these objects will protect the confidentiality, integrity, and availability of the MySQL logs.
Impact:
Changing the permissions of the log files may impact monitoring tools which use a log file adapter. Also, the slow query log can be used for performance analysis by application developers.
The information about the performance exists in MySQL performance_schema or sys schema views. In cases where the information you need is within a running MySQL, disable the slow query log and instead use these methods as they are more secure and do not require OS login and access."
solution : "Set slow query log to OFF (instead use SYS schema views or query Performance_Schema)
SET PERSIST slow_query_log = OFF;
If slow query is enabled, execute the following command to correct permissions and ownership:
chmod 660
chown mysql:mysql
Default Value:
Slow query log is off by default."
reference : "800-171|3.3.8,800-171|3.3.9,800-53|AU-9(4),CIS_Recommendation|3.4,CN-L3|8.1.4.3(d),CSF|PR.PT-1,ISO/IEC-27001|A.12.4.2,ITSG-33|AU-9(4),ITSG-33|AU-9(4)(a),ITSG-33|AU-9(4)(b),LEVEL|1A,NESA|M1.2.2,NESA|M5.2.3,NESA|M5.5.2,NIAv2|SM5,NIAv2|SM6,QCSC-v1|8.2.1,QCSC-v1|13.2,SWIFT-CSCv1|5.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "show variables like 'slow_query_log_file';"
sql_types : POLICY_VARCHAR
sql_expect : regex :".+"
type : SQL_POLICY
description : "3.5 Ensure 'relay_log_basename' ob体育s Have Appropriate Permissions - relay_log_basename ob体育s Have Appropriate Permissions and Ownership"
info : "MySQL can operate using a variety of log files, each used for different purposes. These are the binary log (which can be encrypted), error log, slow query log, relay log (which can be encrypted), general log, and in the enterprise edition, the audit log (which can be encrypted). Because these are files on the host operating system, they are subject to the permissions and ownership structure provided by the host and may be accessible by users other than the MySQL user. Additionally, using secure key management and at rest MySQL encryption can further protect data from OS users.
Rationale:
Limiting the accessibility of these objects will protect the confidentiality, integrity, and availability of the MySQL logs.
Impact:
If the permissions on the relay logs and binary log files are accidentally changed to exclude the user account which is used to run the MySQL service, then this might break replication.
The binary log file can be used for point in time recovery so this can also affect backup, restore and disaster recovery procedures."
solution : "Execute the following command for each log file location requiring corrected permissions and ownership:
chmod 660
chown mysql:mysql
Default Value:
+ '/' + + '-relay-bin'"
reference : "800-171|3.3.8,800-171|3.3.9,800-53|AU-9(4),CIS_Recommendation|3.5,CN-L3|8.1.4.3(d),CSF|PR.PT-1,ISO/IEC-27001|A.12.4.2,ITSG-33|AU-9(4),ITSG-33|AU-9(4)(a),ITSG-33|AU-9(4)(b),LEVEL|1A,NESA|M1.2.2,NESA|M5.2.3,NESA|M5.5.2,NIAv2|SM5,NIAv2|SM6,QCSC-v1|8.2.1,QCSC-v1|13.2,SWIFT-CSCv1|5.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "show variables like 'relay_log_basename';"
sql_types : POLICY_VARCHAR
sql_expect : regex :".+"
type : SQL_POLICY
description : "3.6 Ensure 'general_log_file' Has Appropriate Permissions - general_log is enabled"
sql_request : "select @@general_log"
sql_types : POLICY_VARCHAR
sql_expect : 1
type : SQL_POLICY
description : "3.6 Ensure 'general_log_file' Has Appropriate Permissions - general_log_file Has Appropriate Permissions and Ownership"
info : "MySQL can operate using a variety of log files, each used for different purposes. These are the binary log (which can be encrypted), error log, slow query log, relay log (which can be encrypted), general log, and in the enterprise edition, the audit log (which can be encrypted). Because these are files on the host operating system, they are subject to the permissions and ownership structure provided by the host and may be accessible by users other than the MySQL user. Additionally, using secure key management and at rest MySQL encryption can further protect data from OS users.
Much of the information about the state of MySQL exists in MySQL, the MySQL performance_schema or informations_schema. If you can get the information you need from within MySQL that is more secure as it does not require OS access. If you are not going to use log files it is best to first disable (don't enable) and remove any prior logs.
Rationale:
Limiting the accessibility, or existence, of these log files will protect the confidentiality, integrity, and availability of the MySQL logs.
Impact:
Changing the permissions of the general log files may impact monitoring tools which use a log file adapter."
solution : "If you can, use MySQL SYS, PERFORMANCE_SCHEMA, or MySQL Auditing as these are more secure options.
By default the general_log is disabled (0). Its most secure to disable the general_log.
To disable the general_log_file:
SET PERSIST @@GENERAL_LOG=0;
If you must use general_log then assure the permissions are correct. Execute the following command for each log file location requiring corrected permissions and ownership:
chmod 600
chown mysql:mysql
Default Value:
The general log file is off by default."
reference : "800-171|3.3.8,800-171|3.3.9,800-53|AU-9(4),CIS_Recommendation|3.6,CN-L3|8.1.4.3(d),CSF|PR.PT-1,ISO/IEC-27001|A.12.4.2,ITSG-33|AU-9(4),ITSG-33|AU-9(4)(a),ITSG-33|AU-9(4)(b),LEVEL|1A,NESA|M1.2.2,NESA|M5.2.3,NESA|M5.5.2,NIAv2|SM5,NIAv2|SM6,QCSC-v1|8.2.1,QCSC-v1|13.2,SWIFT-CSCv1|5.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "show variables like 'general_log_file';"
sql_types : POLICY_VARCHAR
sql_expect : regex :".+"
type : SQL_POLICY
description : "3.6 Ensure 'general_log_file' Has Appropriate Permissions - general_log_file Has Appropriate Permissions and Ownership"
info : "MySQL can operate using a variety of log files, each used for different purposes. These are the binary log (which can be encrypted), error log, slow query log, relay log (which can be encrypted), general log, and in the enterprise edition, the audit log (which can be encrypted). Because these are files on the host operating system, they are subject to the permissions and ownership structure provided by the host and may be accessible by users other than the MySQL user. Additionally, using secure key management and at rest MySQL encryption can further protect data from OS users.
Much of the information about the state of MySQL exists in MySQL, the MySQL performance_schema or informations_schema. If you can get the information you need from within MySQL that is more secure as it does not require OS access. If you are not going to use log files it is best to first disable (don't enable) and remove any prior logs.
Rationale:
Limiting the accessibility, or existence, of these log files will protect the confidentiality, integrity, and availability of the MySQL logs.
Impact:
Changing the permissions of the general log files may impact monitoring tools which use a log file adapter."
solution : "If you can, use MySQL SYS, PERFORMANCE_SCHEMA, or MySQL Auditing as these are more secure options.
By default the general_log is disabled (0). Its most secure to disable the general_log.
To disable the general_log_file:
SET PERSIST @@GENERAL_LOG=0;
If you must use general_log then assure the permissions are correct. Execute the following command for each log file location requiring corrected permissions and ownership:
chmod 600
chown mysql:mysql
Default Value:
The general log file is off by default."
reference : "800-171|3.3.8,800-171|3.3.9,800-53|AU-9(4),CIS_Recommendation|3.6,CN-L3|8.1.4.3(d),CSF|PR.PT-1,ISO/IEC-27001|A.12.4.2,ITSG-33|AU-9(4),ITSG-33|AU-9(4)(a),ITSG-33|AU-9(4)(b),LEVEL|1A,NESA|M1.2.2,NESA|M5.2.3,NESA|M5.5.2,NIAv2|SM5,NIAv2|SM6,QCSC-v1|8.2.1,QCSC-v1|13.2,SWIFT-CSCv1|5.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "show variables like 'general_log_file';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "general_log_file", ""
type : SQL_POLICY
description : "3.7 Ensure SSL Key ob体育s Have Appropriate Permissions"
info : "When configured to use SSL/TLS, MySQL relies on Secure Sockets Layer (SSL) key files, which are stored on the host's filesystem. These SSL key files are subject to the host's permissions and ownership structure.
MySQL 8.0 provides ways to create the SSL certificate, SSL key files and RSA key-pair files required to support encrypted connections using SSL and secure password exchange using RSA over unencrypted connections, if those files are missing the server will attempt to autogenerate these files at startup if compiled with OpenSSL.
Rationale:
Limiting the accessibility of these objects will protect the confidentiality, integrity, and availability of the MySQL database and the communication with the client.
If the contents of the SSL key file are known to an attacker, he or she might impersonate the server. This can be used for a man-in-the-middle attack.
Depending on the SSL cipher suite, the key might also be used to decipher previously captured network traffic.
Impact:
If the permissions or ownership for the SSL key file are configured incorrectly, this can cause SSL to be disabled when MySQL is restarted or can cause MySQL not to start at all.
If other applications are using the same key pair, then changing the permissions or ownership of the SSL key file will affect this application. If this were to occur a new key pair must be generated for MySQL."
solution : "Execute the following commands at a terminal prompt to remediate these settings using the Value from the audit procedure:
chown mysql:mysql
chmod 400 "
reference : "800-171|3.1.1,800-53|AC-3.,CIS_Recommendation|3.7,CN-L3|8.1.4.2(f),CN-L3|8.1.4.11(b),CN-L3|8.1.10.2(c),CN-L3|8.5.3.1,CN-L3|8.5.4.1(a),CSF|PR.AC-4,CSF|PR.PT-3,ISO/IEC-27001|A.9.4.1,ISO/IEC-27001|A.9.4.5,ITSG-33|AC-3,LEVEL|1A,NESA|T4.2.1,NESA|T5.4.4,NESA|T5.4.5,NESA|T5.5.4,NESA|T5.6.1,NESA|T7.5.2,NESA|T7.5.3,NIAv2|AM3,NIAv2|SS29,QCSC-v1|3.2,QCSC-v1|5.2.2,QCSC-v1|13.2,TBA-FIISB|31.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT * FROM performance_schema.global_variables WHERE REGEXP_LIKE(VARIABLE_NAME,'^.*ssl_(ca|capath|cert|crl|crlpath|key)$') AND VARIABLE_VALUE <> '';"
sql_types : POLICY_VARCHAR
sql_expect : regex :".+"
type : SQL_POLICY
description : "3.8 Ensure Plugin Directory Has Appropriate Permissions"
info : "The plugin directory is the location of the MySQL plugins. Plugins are storage engines or user defined functions (UDFs).
Rationale:
Limiting the accessibility of these objects will protect the confidentiality, integrity, and availability of the MySQL database. If someone can modify plugins then these plugins might be loaded when the server starts and the code will get executed.
Impact:
Users other than the MySQL user will no longer be able to update and add/remove plugins unless they're able to switch to the MySQL user."
solution : "To remediate these settings, execute the following commands at a terminal prompt using the plugin_dir Value from the audit procedure. MySQL server must not be allowed to write to this location.
chmod 550 (or use 554)
chown mysql:mysql "
reference : "800-171|3.4.2,800-53|CM-6b.,CIS_Recommendation|3.8,CN-L3|8.1.10.6(d),CSF|PR.IP-1,ITSG-33|CM-6b.,LEVEL|1A,NESA|T3.2.1,SWIFT-CSCv1|2.3"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "show variables like 'plugin_dir';"
sql_types : POLICY_VARCHAR
sql_expect : regex :".+"
type : SQL_POLICY
description : "3.9 Ensure 'audit_log_file' Has Appropriate Permissions - audit_log_file has Appropriate Permissions and Ownership"
info : "MySQL can operate using a variety of log files, each used for different purposes. These are the binary log, error log, slow query log, relay log, audit log and general log. Because these are files on the host operating system, they are subject to the permissions and ownership structure provided by the host and may be accessible by users other than the MySQL user.
Rationale:
Limiting the accessibility of these objects will protect the confidentiality, integrity, and availability of the MySQL logs.
Impact:
Changing the permissions and ownership of the audit log file may have an impact on who can access and edit the audit log. Such changes can affect monitoring tools which maybe using a log file adapter or scripted alternatives. Also, the audit log may be used for alerting by infrastructure teams which can affect real-time audit capability."
solution : "Execute the following commands for the audit_log_file discovered in the audit procedure:
chmod 660
chown mysql:mysql "
reference : "800-171|3.3.8,800-171|3.3.9,800-53|AU-9(4),CIS_Recommendation|3.9,CN-L3|8.1.4.3(d),CSF|PR.PT-1,ISO/IEC-27001|A.12.4.2,ITSG-33|AU-9(4),ITSG-33|AU-9(4)(a),ITSG-33|AU-9(4)(b),LEVEL|1A,NESA|M1.2.2,NESA|M5.2.3,NESA|M5.5.2,NIAv2|SM5,NIAv2|SM6,QCSC-v1|8.2.1,QCSC-v1|13.2,SWIFT-CSCv1|5.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "show variables like 'audit_log_file';"
sql_types : POLICY_VARCHAR
sql_expect : regex :".+"
type : SQL_POLICY
description : "4.1 Ensure Latest Security Patches Are Applied"
info : "Periodically, updates to MySQL server are released to resolve bugs, mitigate vulnerabilities, and provide new features. It is recommended that MySQL installations are up to date with the latest security updates.
Rationale:
Maintaining currency with MySQL patches will help reduce risk associated with known vulnerabilities present in the MySQL server.
Without the latest security patches MySQL might have known vulnerabilities which could be used by an attacker to gain access.
Impact:
To update the MySQL server a restart is required."
solution : "Install the latest patches for your version or upgrade to the latest version."
reference : "800-171|3.14.1,800-53|SI-2.,CIS_Recommendation|4.1,CN-L3|8.1.4.4(e),CN-L3|8.1.10.5(a),CN-L3|8.1.10.5(b),CN-L3|8.5.4.1(b),CN-L3|8.5.4.1(d),CN-L3|8.5.4.1(e),CSF|ID.RA-1,CSF|PR.IP-12,HIPAA|164.308(a)(5)(ii)(A),ITSG-33|SI-2,LEVEL|1NS,NESA|T7.6.2,NESA|T7.7.1,NIAv2|PR9,QCSC-v1|11.2,SWIFT-CSCv1|2.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "show variables like 'version' ;"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "version", regex :".+"
type : SQL_POLICY
description : "4.2 Ensure Example or Test Databases are Not Installed on Production Servers"
info : "The default MySQL installation does not contain any example or test databases. However, it is a good idea to review for common example databases and ensure they have been removed from production systems.
Rationale:
Dropping example databases will reduce the attack surface of the MySQL server."
solution : "Execute the following SQL statement to drop an example database:
DROP DATABASE ;
Default Value:
By default, MySQL 8.0 does not contain any example or test databases."
reference : "800-171|3.4.4,800-53|CM-4(1),CIS_Recommendation|4.2,CSF|PR.DS-7,CSF|PR.IP-3,ISO/IEC-27001|A.12.1.4,ITSG-33|CM-4(1),LEVEL|1A,NESA|T3.2.3,NESA|T3.3.2,NESA|T7.5.1,NESA|T7.6.2,NESA|T7.6.3,QCSC-v1|5.2.1,QCSC-v1|7.2,QCSC-v1|13.2,SWIFT-CSCv1|7.4"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : " SELECT * FROM information_schema.SCHEMATA where SCHEMA_NAME not in ('mysql','information_schema', 'sys', 'performance_schema');"
sql_types : POLICY_VARCHAR
sql_expect : NULL
type : SQL_POLICY
description : "4.4 Harden Usage for 'local_infile' on MySQL Clients"
info : "The local_infile parameter dictates whether files located on the MySQL client's computer can be loaded or selected via LOAD DATA INFILE or SELECT local_file.
Rationale:
For MySQL client programs and connectors prior to 8.0.21, disabling local_infile reduces an attacker's ability to read sensitive files off the affected server via an SQL injection vulnerability.
Impact:
Disabling local_infile will impact the functionality of solutions that rely on it."
solution : "Upgrade all MySQL clients and connectors to 8.0.21 or higher.
In the case where using local_infile is needed, the following changes further harden security:
On client side, secure by:
Limiting the location from where data can be read using --load-data-local-dir.
mysql --local-infile=0 --load-data-local-dir=/my/local/data
Adding TLS connection to assure server identity by requiring verification.
mysql --local-infile=0 --load-data-local-dir=/my/local/data --ssl-mode=VERIFY_IDENTITY
If local_infile is not in use or if clients are not upgraded - add the following line to the [mysqld] section of the MySQL configuration file and restart the MySQL service:
local-infile=0
Default Value:
0 (OFF)"
reference : "800-171|3.4.6,800-171|3.4.7,800-53|CM-7b.,CIP|007-6-R1,CIS_Recommendation|4.4,CN-L3|7.1.3.5(c),CN-L3|7.1.3.7(d),CN-L3|8.1.4.4(b),CSCv6|9.1,CSF|PR.IP-1,CSF|PR.PT-3,ITSG-33|CM-7a.,LEVEL|1A,NIAv2|SS13b,NIAv2|SS14a,NIAv2|SS14c,PCI-DSSv3.1|2.2.2,PCI-DSSv3.1|2.2.3,PCI-DSSv3.2|2.2.2,PCI-DSSv3.2|2.2.3,QCSC-v1|3.2,SWIFT-CSCv1|2.3"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "show variables like 'local_infile';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "local_infile", "OFF"
type : SQL_POLICY
description : "4.6 Ensure Symbolic Links are Disabled"
info : "The symbolic-links and skip-symbolic-links options for MySQL determine whether symbolic link support is available. When use of symbolic links is enabled, they have different effects depending on the host platform. When symbolic links are disabled, then symbolic links stored in files or entries in tables are not used by the database.
Rationale:
Prevents symbolic links from being used for database files. This is especially important when MySQL is executing as root as arbitrary files may be overwritten. The symbolic-links option might allow someone to direct actions by the MySQL server to other files and/or directories."
solution : "Perform the following actions to remediate this setting:
Open the MySQL configuration file (my.cnf)
Locate skip_symbolic_links in the configuration
Set the skip_symbolic_links to YES
Note: If skip_symbolic_links does not exist, add it to the configuration file in the mysqld section."
reference : "800-171|3.4.2,800-53|CM-6b.,CIS_Recommendation|4.6,CN-L3|8.1.10.6(d),CSCv6|3.1,CSF|PR.IP-1,ITSG-33|CM-6b.,LEVEL|1A,NESA|T3.2.1,PCI-DSSv3.1|2.2.4,PCI-DSSv3.2|2.2.4,SWIFT-CSCv1|2.3"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "show variables like 'have_symlink';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "have_symlink", "disabled"
type : SQL_POLICY
description : "4.7 Ensure the 'daemon_memcached' Plugin is Disabled - daemon_memcached Plugin Is Disabled"
info : "The InnoDB memcached Plugin allows users to access data stored in InnoDB with the memcached protocol.
Rationale:
By default, the plugin doesn't do authentication, which means that anyone with access to the TCP/IP port of the plugin can access and modify the data. However, not all data is exposed by default."
solution : "To remediate this setting, issue the following command in the MySQL command-line client:
uninstall plugin daemon_memcached;
This uninstalls the memcached plugin from the MySQL server.
Default Value:
disabled"
reference : "800-171|3.4.6,800-171|3.4.7,800-53|CM-7b.,CIP|007-6-R1,CIS_Recommendation|4.7,CN-L3|7.1.3.5(c),CN-L3|7.1.3.7(d),CN-L3|8.1.4.4(b),CSCv6|9.1,CSF|PR.IP-1,CSF|PR.PT-3,ITSG-33|CM-7a.,LEVEL|1A,NIAv2|SS13b,NIAv2|SS14a,NIAv2|SS14c,PCI-DSSv3.1|2.2.2,PCI-DSSv3.1|2.2.3,PCI-DSSv3.2|2.2.2,PCI-DSSv3.2|2.2.3,QCSC-v1|3.2,SWIFT-CSCv1|2.3"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT PLUGIN_NAME, PLUGIN_STATUS FROM information_schema.plugins WHERE PLUGIN_NAME='daemon_memcached'"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : NULL, NULL
type : SQL_POLICY
description : "4.8 Ensure the 'secure_file_priv' is Configured Correctly"
info : "The secure_file_priv option restricts to paths used by LOAD DATA INFILE or SELECT local_file. It is recommended that this option be set to a file system location that contains only resources expected to be loaded by MySQL. Even better, if data import/export using LOAD DATA INFILE or SELECT local_file is not used, the functionality should be disabled entirely by setting --secure-file-priv to NULL.
Rationale:
Setting secure_file_priv reduces an attacker's ability to read sensitive files off the affected server via a SQL injection vulnerability.
Impact:
Solutions that rely on loading data from various sub-directories may be negatively impacted by this change. Consider consolidating load directories under a common parent directory.
The server checks the value of secure_file_priv at startup and writes a warning to the error log if the value is insecure. A non-NULL value is considered insecure if it is empty, or the value is the data directory or a subdirectory of it, or a directory that is accessible by all users."
solution : "If you are not going to use this feature, remove secure_file_priv from the [mysqld] section of the MySQL configuration file and restart the MySQL service.
If you need this feature add the following line to the [mysqld] section of the MySQL configuration file and restart the MySQL service:
secure_file_priv=
Default Value:
No value set."
reference : "800-171|3.4.2,800-53|CM-6b.,CIS_Recommendation|4.8,CN-L3|8.1.10.6(d),CSCv6|3.1,CSF|PR.IP-1,ITSG-33|CM-6b.,LEVEL|1A,NESA|T3.2.1,PCI-DSSv3.1|2.2.4,PCI-DSSv3.2|2.2.4,SWIFT-CSCv1|2.3"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SHOW GLOBAL VARIABLES WHERE Variable_name = 'secure_file_priv';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "secure_file_priv", regex:".+"
type : SQL_POLICY
description : "5.1 Ensure Only Administrative Users Have Full Database Access 'mysql.db'"
sql_request : "SELECT user, host FROM mysql.db WHERE db = 'mysql' AND ((Select_priv = 'Y') OR (Insert_priv = 'Y') OR (Update_priv = 'Y') OR (Delete_priv = 'Y') OR (Create_priv = 'Y') OR (Drop_priv = 'Y'));"
sql_types : POLICY_VARCHAR,POLICY_VARCHAR
sql_expect : NULL, NULL
description : "5.1 Ensure Only Administrative Users Have Full Database Access - mysql.db"
info : "The mysql.user, mysql.db, and other mysql tables ending in _priv list a variety of privileges that can be granted (or denied) to MySQL users. Some of the privileges of concern include: Select_priv, Insert_priv, Update_priv, Delete_priv, Drop_priv, and so on. Typically, these privileges should not be available to every MySQL user and often are reserved for administrative use only. The information_schema.user_privileges provides a consolidated view of all user privileges.
Rationale:
Limiting the accessibility of the mysql database will protect the confidentiality, integrity, and availability of the data housed within MySQL. A user which has direct access to mysql.* might view password hashes, change permissions, or alter or destroy information intentionally or unintentionally."
solution : "Perform the following actions to remediate this setting:
Enumerate non-administrative users resulting from the audit procedure.
For each non-administrative user, use the REVOKE statement to remove privileges as appropriate."
reference : "800-171|3.1.5,800-53|AC-6(5),CIS_Recommendation|5.1,CN-L3|8.1.10.6(a),CSCv6|5.1,CSF|PR.AC-4,ISO/IEC-27001|A.9.2.3,ITSG-33|AC-6(5),LEVEL|1M,NESA|T5.1.1,NESA|T5.2.2,NESA|T5.6.1,NIAv2|AM32,NIAv2|AM33,NIAv2|VL3a,QCSC-v1|5.2.2,QCSC-v1|6.2,SWIFT-CSCv1|1.2,TBA-FIISB|31.4.2,TBA-FIISB|31.4.3"
see_also : "https://workbench.cisecurity.org/files/3477"
type : SQL_POLICY
description : "5.1 Ensure Only Administrative Users Have Full Database Access - mysql.db"
info : "The mysql.user, mysql.db, and other mysql tables ending in _priv list a variety of privileges that can be granted (or denied) to MySQL users. Some of the privileges of concern include: Select_priv, Insert_priv, Update_priv, Delete_priv, Drop_priv, and so on. Typically, these privileges should not be available to every MySQL user and often are reserved for administrative use only. The information_schema.user_privileges provides a consolidated view of all user privileges.
Rationale:
Limiting the accessibility of the mysql database will protect the confidentiality, integrity, and availability of the data housed within MySQL. A user which has direct access to mysql.* might view password hashes, change permissions, or alter or destroy information intentionally or unintentionally."
solution : "Perform the following actions to remediate this setting:
Enumerate non-administrative users resulting from the audit procedure.
For each non-administrative user, use the REVOKE statement to remove privileges as appropriate."
reference : "800-171|3.1.5,800-53|AC-6(5),CIS_Recommendation|5.1,CN-L3|8.1.10.6(a),CSCv6|5.1,CSF|PR.AC-4,ISO/IEC-27001|A.9.2.3,ITSG-33|AC-6(5),LEVEL|1M,NESA|T5.1.1,NESA|T5.2.2,NESA|T5.6.1,NIAv2|AM32,NIAv2|AM33,NIAv2|VL3a,QCSC-v1|5.2.2,QCSC-v1|6.2,SWIFT-CSCv1|1.2,TBA-FIISB|31.4.2,TBA-FIISB|31.4.3"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT user, host FROM mysql.db WHERE db = 'mysql' AND ((Select_priv = 'Y') OR (Insert_priv = 'Y') OR (Update_priv = 'Y') OR (Delete_priv = 'Y') OR (Create_priv = 'Y') OR (Drop_priv = 'Y'));"
sql_types : POLICY_VARCHAR,POLICY_VARCHAR
sql_expect : "root", regex:".+"
type : SQL_POLICY
description : "5.1 Ensure Only Administrative Users Have Full Database Access 'mysql.user'"
sql_request : "SELECT user, host FROM mysql.user WHERE ((Select_priv = 'Y') OR (Insert_priv = 'Y') OR (Update_priv = 'Y') OR (Delete_priv = 'Y') OR (Create_priv = 'Y') OR (Drop_priv = 'Y'));"
sql_types : POLICY_VARCHAR,POLICY_VARCHAR
sql_expect : NULL, NULL
description : "5.1 Ensure Only Administrative Users Have Full Database Access - mysql.user"
info : "The mysql.user, mysql.db, and other mysql tables ending in _priv list a variety of privileges that can be granted (or denied) to MySQL users. Some of the privileges of concern include: Select_priv, Insert_priv, Update_priv, Delete_priv, Drop_priv, and so on. Typically, these privileges should not be available to every MySQL user and often are reserved for administrative use only. The information_schema.user_privileges provides a consolidated view of all user privileges.
Rationale:
Limiting the accessibility of the mysql database will protect the confidentiality, integrity, and availability of the data housed within MySQL. A user which has direct access to mysql.* might view password hashes, change permissions, or alter or destroy information intentionally or unintentionally."
solution : "Perform the following actions to remediate this setting:
Enumerate non-administrative users resulting from the audit procedure.
For each non-administrative user, use the REVOKE statement to remove privileges as appropriate."
reference : "800-171|3.1.5,800-53|AC-6(5),CIS_Recommendation|5.1,CN-L3|8.1.10.6(a),CSCv6|5.1,CSF|PR.AC-4,ISO/IEC-27001|A.9.2.3,ITSG-33|AC-6(5),LEVEL|1M,NESA|T5.1.1,NESA|T5.2.2,NESA|T5.6.1,NIAv2|AM32,NIAv2|AM33,NIAv2|VL3a,QCSC-v1|5.2.2,QCSC-v1|6.2,SWIFT-CSCv1|1.2,TBA-FIISB|31.4.2,TBA-FIISB|31.4.3"
see_also : "https://workbench.cisecurity.org/files/3477"
type : SQL_POLICY
description : "5.1 Ensure Only Administrative Users Have Full Database Access - mysql.user"
info : "The mysql.user, mysql.db, and other mysql tables ending in _priv list a variety of privileges that can be granted (or denied) to MySQL users. Some of the privileges of concern include: Select_priv, Insert_priv, Update_priv, Delete_priv, Drop_priv, and so on. Typically, these privileges should not be available to every MySQL user and often are reserved for administrative use only. The information_schema.user_privileges provides a consolidated view of all user privileges.
Rationale:
Limiting the accessibility of the mysql database will protect the confidentiality, integrity, and availability of the data housed within MySQL. A user which has direct access to mysql.* might view password hashes, change permissions, or alter or destroy information intentionally or unintentionally."
solution : "Perform the following actions to remediate this setting:
Enumerate non-administrative users resulting from the audit procedure.
For each non-administrative user, use the REVOKE statement to remove privileges as appropriate."
reference : "800-171|3.1.5,800-53|AC-6(5),CIS_Recommendation|5.1,CN-L3|8.1.10.6(a),CSCv6|5.1,CSF|PR.AC-4,ISO/IEC-27001|A.9.2.3,ITSG-33|AC-6(5),LEVEL|1M,NESA|T5.1.1,NESA|T5.2.2,NESA|T5.6.1,NIAv2|AM32,NIAv2|AM33,NIAv2|VL3a,QCSC-v1|5.2.2,QCSC-v1|6.2,SWIFT-CSCv1|1.2,TBA-FIISB|31.4.2,TBA-FIISB|31.4.3"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT user, host FROM mysql.user WHERE ((Select_priv = 'Y') OR (Insert_priv = 'Y') OR (Update_priv = 'Y') OR (Delete_priv = 'Y') OR (Create_priv = 'Y') OR (Drop_priv = 'Y'));"
sql_types : POLICY_VARCHAR,POLICY_VARCHAR
sql_expect : "root", regex:".+"
type : SQL_POLICY
description : "5.2 Ensure 'file_priv' is Not Set to 'Y' for Non-Administrative Users - Y for Non-Administrative Users"
info : "The ob体育_priv privilege found in the mysql.user table is used to allow or disallow a user from reading and writing files on the server host. Any user with the ob体育_priv right granted has the ability to:
Read files from the local file system that are readable by the MySQL server (this includes world-readable files).
Write files to the local file system where the MySQL server has write access.
Rationale:
The ob体育_priv right allows mysql users to read files from disk and to write files to disk. This may be leveraged by an attacker to further compromise MySQL. It should be noted that the MySQL server should not overwrite existing files."
solution : "Perform the following steps to remediate this setting:
Enumerate the non-administrative users found in the result set of the audit procedure.
For each user, issue the following SQL statement (replace with the non-administrative user):
REVOKE FILE ON *.* FROM '';"
reference : "800-171|3.1.5,800-53|AC-6(5),CIS_Recommendation|5.2,CN-L3|8.1.10.6(a),CSCv6|5.1,CSF|PR.AC-4,ISO/IEC-27001|A.9.2.3,ITSG-33|AC-6(5),LEVEL|1M,NESA|T5.1.1,NESA|T5.2.2,NESA|T5.6.1,NIAv2|AM32,NIAv2|AM33,NIAv2|VL3a,QCSC-v1|5.2.2,QCSC-v1|6.2,SWIFT-CSCv1|1.2,TBA-FIISB|31.4.2,TBA-FIISB|31.4.3"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "select user, host from mysql.user where ob体育_priv = 'Y' ;"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "root", regex:".+"
type : SQL_POLICY
description : "5.4 Ensure 'SUPER' is Not Granted to Non-Administrative Users"
info : "The SUPER privilege is a powerful and far-reaching privilege and should not be granted lightly. In MySQL 8.0, SUPER is deprecated and will be removed in a future version of MySQL.
The SUPER privilege shown in the INFORMATION_SCHEMA.USER_PRIVILEGES table governs the use of a variety of MySQL features. These features include, CHANGE MASTER TO, KILL, mysqladmin kill option, PURGE BINARY LOGS, SET GLOBAL, mysqladmin debug option, logging control, and more.
In MySQL 8.0, SUPER is deprecated and will be removed in a future version of MySQL. Migrating Accounts from SUPER to Dynamic Privileges is recommended.
Rationale:
The SUPER privilege allows principals to perform many actions, including view and terminate currently executing MySQL statements (including statements used to manage passwords). This privilege also provides the ability to configure MySQL, such as enable/disable logging, alter data, disable/enable features. Limiting the accounts that have the SUPER privilege reduces the chances that an attacker can exploit these capabilities.
It is more secure to migrate administrative users off SUPER and instead assign the specific and minimal set of mysql Dynamic Privileges needed to perform their tasks.
Impact:
When the SUPER privilege is denied to a given user, that user will be unable to take advantage of certain capabilities, such as certain mysqladmin options.
NOTE: Nessus has provided the target output to assist in reviewing the benchmark to ensure target compliance."
solution : "Perform the following steps to remediate this setting:
Enumerate the non-administrative users found in the result set of the audit procedure
For each user, issue the following SQL statement (replace with the non-administrative user:
REVOKE SUPER ON *.* FROM '';
Next minimize administrator rights
Assess the minimal set of Dynamic Permissions needed by a user to perform their duties.
For each user assign the appropriate Dynamic Permission and then revoke that SUPER capability.
For example, if administrator 'u1'@'localhost' requires SUPER for binary log purging and system variable modification, these statements make the required changes to the account thus limiting rights to what is needed:
GRANT BINLOG_ADMIN, SYSTEM_VARIABLES_ADMIN ON *.* TO 'u1'@'localhost';
REVOKE SUPER ON *.* FROM 'u1'@'localhost';"
reference : "800-171|3.1.1,800-53|AC-3.,CIS_Recommendation|5.4,CN-L3|8.1.4.2(f),CN-L3|8.1.4.11(b),CN-L3|8.1.10.2(c),CN-L3|8.5.3.1,CN-L3|8.5.4.1(a),CSF|PR.AC-4,CSF|PR.PT-3,ISO/IEC-27001|A.9.4.1,ISO/IEC-27001|A.9.4.5,ITSG-33|AC-3,LEVEL|1M,NESA|T4.2.1,NESA|T5.4.4,NESA|T5.4.5,NESA|T5.5.4,NESA|T5.6.1,NESA|T7.5.2,NESA|T7.5.3,NIAv2|AM3,NIAv2|SS29,QCSC-v1|3.2,QCSC-v1|5.2.2,QCSC-v1|13.2,TBA-FIISB|31.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : " SELECT GRANTEE FROM INFORMATION_SCHEMA.USER_PRIVILEGES WHERE PRIVILEGE_TYPE = 'SUPER';"
sql_types : POLICY_VARCHAR
sql_expect : "ManualReviewRequired"
severity : MEDIUM
type : SQL_POLICY
description : "5.5 Ensure 'shutdown_priv' is Not Set to 'Y' for Non-Administrative Users - Y for Non-Administrative Users"
info : "The SHUTDOWN privilege simply enables use of the shutdown option to the mysqladmin command, which allows a user with the SHUTDOWN privilege the ability to shut down the MySQL server.
Rationale:
The SHUTDOWN privilege allows principals to shutdown MySQL. This may be leveraged by an attacker to negatively impact the availability of MySQL."
solution : "Perform the following steps to remediate this setting:
Enumerate the non-administrative users found in the result set of the audit procedure.
For each user, issue the following SQL statement (replace with the non-administrative user):
REVOKE SHUTDOWN ON *.* FROM '';"
reference : "800-171|3.1.5,800-53|AC-6(5),CIS_Recommendation|5.5,CN-L3|8.1.10.6(a),CSCv6|5.1,CSF|PR.AC-4,ISO/IEC-27001|A.9.2.3,ITSG-33|AC-6(5),LEVEL|1M,NESA|T5.1.1,NESA|T5.2.2,NESA|T5.6.1,NIAv2|AM32,NIAv2|AM33,NIAv2|VL3a,QCSC-v1|5.2.2,QCSC-v1|6.2,SWIFT-CSCv1|1.2,TBA-FIISB|31.4.2,TBA-FIISB|31.4.3"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "select user, host from mysql.user where Shutdown_priv = 'Y' ;"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "root", regex:".+"
type : SQL_POLICY
description : "5.6 Ensure 'create_user_priv' is Not Set to 'Y' for Non-Administrative Users - Y for Non-Administrative Users"
info : "The CREATE USER privilege governs the right of a given user to add or remove users, change existing users' names, or revoke existing users' privileges.
Rationale:
Reducing the number of users granted the CREATE USER right minimizes the number of users able to add/drop users, alter existing users' names, and manipulate existing users' privileges.
Impact:
Users that are denied the CREATE USER privilege will not only be unable to create a user, but they may be unable to drop a user, rename a user, or otherwise revoke a given user's privileges."
solution : "Perform the following steps to remediate this setting:
Enumerate the non-administrative users found in the result set of the audit procedure
For each user, issue the following SQL statement (replace with the non-administrative user):
REVOKE CREATE USER ON *.* FROM '';"
reference : "800-171|3.1.5,800-53|AC-6(5),CIS_Recommendation|5.6,CN-L3|8.1.10.6(a),CSCv6|5.1,CSF|PR.AC-4,ISO/IEC-27001|A.9.2.3,ITSG-33|AC-6(5),LEVEL|1M,NESA|T5.1.1,NESA|T5.2.2,NESA|T5.6.1,NIAv2|AM32,NIAv2|AM33,NIAv2|VL3a,QCSC-v1|5.2.2,QCSC-v1|6.2,SWIFT-CSCv1|1.2,TBA-FIISB|31.4.2,TBA-FIISB|31.4.3"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "select user, host from mysql.user where Create_user_priv = 'Y' ;"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "root", regex:".+"
type : SQL_POLICY
description : "5.7 Ensure 'grant_priv' is Not Set to 'Y' for Non-Administrative Users - mysql.user"
info : "The GRANT OPTION privilege exists in different contexts (mysql.user, mysql.db) for the purpose of governing the ability of a privileged user to manipulate the privileges of other users.
Rationale:
The GRANT privilege allows a principal to grant other principals additional privileges. This may be used by an attacker to compromise MySQL."
solution : "Perform the following steps to remediate this setting:
Enumerate the non-administrative users found in the result sets of the audit procedure
For each user, issue the following SQL statement (replace with the non-administrative user:
REVOKE GRANT OPTION ON *.* FROM ;"
reference : "800-171|3.1.5,800-53|AC-6(5),CIS_Recommendation|5.7,CN-L3|8.1.10.6(a),CSCv6|5.1,CSF|PR.AC-4,ISO/IEC-27001|A.9.2.3,ITSG-33|AC-6(5),LEVEL|1M,NESA|T5.1.1,NESA|T5.2.2,NESA|T5.6.1,NIAv2|AM32,NIAv2|AM33,NIAv2|VL3a,QCSC-v1|5.2.2,QCSC-v1|6.2,SWIFT-CSCv1|1.2,TBA-FIISB|31.4.2,TBA-FIISB|31.4.3"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "select user, host from mysql.user where Grant_priv = 'Y' ;"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "root", regex:".+"
type : SQL_POLICY
description : "5.7 Ensure 'grant_priv' is Not Set to 'Y' for Non-Administrative Users - mysql.db"
info : "The GRANT OPTION privilege exists in different contexts (mysql.user, mysql.db) for the purpose of governing the ability of a privileged user to manipulate the privileges of other users.
Rationale:
The GRANT privilege allows a principal to grant other principals additional privileges. This may be used by an attacker to compromise MySQL."
solution : "Perform the following steps to remediate this setting:
Enumerate the non-administrative users found in the result sets of the audit procedure
For each user, issue the following SQL statement (replace with the non-administrative user:
REVOKE GRANT OPTION ON *.* FROM ;"
reference : "800-171|3.1.5,800-53|AC-6(5),CIS_Recommendation|5.7,CN-L3|8.1.10.6(a),CSCv6|5.1,CSF|PR.AC-4,ISO/IEC-27001|A.9.2.3,ITSG-33|AC-6(5),LEVEL|1M,NESA|T5.1.1,NESA|T5.2.2,NESA|T5.6.1,NIAv2|AM32,NIAv2|AM33,NIAv2|VL3a,QCSC-v1|5.2.2,QCSC-v1|6.2,SWIFT-CSCv1|1.2,TBA-FIISB|31.4.2,TBA-FIISB|31.4.3"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "select user, host from mysql.db where Grant_priv = 'Y' ;"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "root", regex:".+"
type : SQL_POLICY
description : "5.8 Ensure 'repl_slave_priv' is Not Set to 'Y' for Non-Replica Users"
info : "The REPLICATION SLAVE privilege governs whether a given user (in the context of the source server) can request updates that have been made on the source server.
Rationale:
The REPLICATION SLAVE privilege allows a principal to fetch binlog files containing all data changing statements and/or changes to table data from the source. This may be used by an attacker to read/fetch sensitive data from MySQL."
solution : "Perform the following steps to remediate this setting:
Enumerate the non-replica users found in the result set of the audit procedure
For each user, issue the following SQL statement (replace with the non-replica user):
REVOKE REPLICATION SLAVE ON *.* FROM ;
Use the REVOKE statement to remove the SUPER privilege from users who shouldn't have it."
reference : "800-171|3.1.5,800-53|AC-6(5),CIS_Recommendation|5.8,CN-L3|8.1.10.6(a),CSCv6|5.1,CSF|PR.AC-4,ISO/IEC-27001|A.9.2.3,ITSG-33|AC-6(5),LEVEL|1M,NESA|T5.1.1,NESA|T5.2.2,NESA|T5.6.1,NIAv2|AM32,NIAv2|AM33,NIAv2|VL3a,QCSC-v1|5.2.2,QCSC-v1|6.2,SWIFT-CSCv1|1.2,TBA-FIISB|31.4.2,TBA-FIISB|31.4.3"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT user, host FROM mysql.user WHERE Repl_slave_priv = 'Y' ;"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "root", regex:".+"
type : SQL_POLICY
description : "5.9 Ensure DML/DDL Grants are Limited to Specific Databases and Users"
info : "DML/DDL includes the set of privileges used to modify or create data structures. This includes INSERT, SELECT, UPDATE, DELETE, DROP, CREATE, and ALTER privileges.
Rationale:
INSERT, SELECT, UPDATE, DELETE, DROP, CREATE, and ALTER are powerful privileges in any database. Such privileges should be limited only to those users requiring such rights. By limiting the users with these rights and ensuring that they are limited to specific databases, the attack surface of the database is reduced."
solution : "Perform the following steps to remediate this setting:
Enumerate the unauthorized users, hosts, and databases returned in the result set of the audit procedure
For each user, issue the following SQL statement (replace with the unauthorized user, with host name, and with the database name):
REVOKE SELECT ON . FROM ;
REVOKE INSERT ON . FROM ;
REVOKE UPDATE ON . FROM ;
REVOKE DELETE ON . FROM ;
REVOKE CREATE ON . FROM ;
REVOKE DROP ON . FROM ;
REVOKE ALTER ON . FROM ;"
reference : "800-171|3.1.5,800-53|AC-6(5),CIS_Recommendation|5.9,CN-L3|8.1.10.6(a),CSCv6|5.1,CSF|PR.AC-4,ISO/IEC-27001|A.9.2.3,ITSG-33|AC-6(5),LEVEL|1M,NESA|T5.1.1,NESA|T5.2.2,NESA|T5.6.1,NIAv2|AM32,NIAv2|AM33,NIAv2|VL3a,QCSC-v1|5.2.2,QCSC-v1|6.2,SWIFT-CSCv1|1.2,TBA-FIISB|31.4.2,TBA-FIISB|31.4.3"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT User,Host,Db FROM mysql.db WHERE Select_priv='Y' OR Insert_priv='Y' OR Update_priv='Y' OR Delete_priv='Y' OR Create_priv='Y' OR Drop_priv='Y' OR Alter_priv='Y';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "root", regex:".+", regex:".+"
description : "5.10 Securely Define Stored Procedures and Functions DEFINER and INVOKER"
info : "Stored procedure and stored function declarations include a definition of permissions which can be used to escalate permissions. It's important to inspect these settings to ensure they do not unnecessarily escalate privileges.
Rationale:
A stored procedure or function that improperly escalates privileges may provide unintended access rights which can be improperly used.
NOTE: Nessus has not performed this check. Please review the benchmark to ensure target compliance."
solution : "Drop and recreate stored procedures and functions using proper DEFINER and INVOKER settings, or other code changes."
reference : "800-53|AC-3,CIS_Recommendation|5.10,CSCv7|14.6,CSCv8|16.10,LEVEL|1M"
see_also : "https://workbench.cisecurity.org/files/3477"
type : SQL_POLICY
description : "6.1 Ensure 'log_error' is configured correctly"
info : "The error log contains information about events such as mysqld starting and stopping, when a table needs to be checked or repaired, and, depending on the host operating system, stack traces when mysqld fails.
Rationale:
Enabling error logging can increase the ability to detect malicious attempts against MySQL, and other critical messages. For example, if the error log is not enabled then a connection error could go unnoticed.
When configured to stderr MySQL will send log data to the console. Logging to the console is useful, but remember it is ephemeral. This is not recommended due to the fact that logging to console does not provide a means to force restricted access via permissions strictly to MySQL and dedicated MySQL audit accounts. This may compromise the confidentiality of the MySQL log data. Furthermore use caution if co-mingling log data from multiple sources as that can complicate log inspection. Additionally from a security auditing perspective, it's difficult and error prone to verify logging is correct using stderr or redirected stderr."
solution : "Perform the following actions to remediate this setting:
Open the MySQL configuration file (my.cnf or my.ini).
Set the log-error option to the path for the error log.
Default Value:
./stderr.err"
reference : "800-171|3.3.1,800-171|3.3.2,800-53|AU-12c.,CIS_Recommendation|6.1,CN-L3|7.1.3.3(a),CN-L3|7.1.3.3(b),CN-L3|7.1.3.3(c),CN-L3|8.1.3.5(a),CN-L3|8.1.3.5(b),CN-L3|8.1.4.3(a),CSF|DE.CM-1,CSF|DE.CM-3,CSF|DE.CM-7,CSF|PR.PT-1,ISO/IEC-27001|A.12.4.1,ITSG-33|AU-12c.,LEVEL|1A,NESA|T3.6.2,NESA|T3.6.5,NESA|T3.6.6,NIAv2|SM8,QCSC-v1|3.2,QCSC-v1|6.2,QCSC-v1|8.2.1,QCSC-v1|13.2,SWIFT-CSCv1|6.4,TBA-FIISB|45.1.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SHOW variables LIKE 'log_error';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "log_error", regex:".+"
type : SQL_POLICY
description : "6.2 Ensure Log ob体育s are Stored on a Non-System Partition"
info : "MySQL log files can be set in the MySQL configuration to exist anywhere on the filesystem. It is common practice to ensure that the system filesystem is left uncluttered by application logs. System filesystems include the root, /var, or /usr.
Rationale:
Moving the MySQL logs off the system partition will reduce the probability of denial of service via the exhaustion of available disk space to the operating system."
solution : "Perform the following actions to remediate this setting:
Open the MySQL configuration file (my.cnf)
Locate the log-bin entry and set it to a file not on root (/), /var, or /usr"
reference : "800-53|SC-5(2),CIS_Recommendation|6.2,CSF|PR.DS-4,ITSG-33|SC-5(2),LEVEL|1A,NESA|T3.3.1,NIAv2|GS8e,NIAv2|GS10c,QCSC-v1|8.2.1,SWIFT-CSCv1|6.4"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "show GLOBAL VARIABLES WHERE Variable_Name = 'log_bin_basename' AND Value LIKE 'C:%' OR Variable_Name = 'log_bin_basename' AND Value = '/' OR Variable_Name = 'log_bin_basename' AND Value = '/var%' OR Variable_Name = 'log_bin_basename' AND Value = '/usr%';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : NULL, NULL
type : SQL_POLICY
description : "6.5 Ensure Audit Filters Capture Connection Attempts"
info : "The functions audit_log_filter_set_filter() and audit_log_filter_set_user() are used to define rules for auditing. With this feature you can easily audit successful and/or failed connection events and write to the audit log file.
Rationale:
The audit_log_filter_set_filter function which defines auditing filters. The users for which filter(s) apply is defined by audit_log_filter_set_user. One or more filters can be created to log connections success and/or failure.
Impact:
If the audit rule and application of the rule to targeted or all users is not properly configured, it will not log failed connections, successful connections or any other connection related events."
solution : "To remediate this configuration setting, execute one of the following SQL statements:
Log All connections - Successful and Failed:
SET @f = '{ 'filter': { 'class': { 'name': 'connection' } } }';
SELECT audit_log_filter_set_filter('log__all_conn_events', @f);
SELECT audit_log_filter_set_user('%', 'log_all_conn_events');
Or Log Only Failed Connections:
SET @f='
{
'filter': {
'log': false,
'class': {
'name': 'connection',
'event': [
{ 'name': 'connect', 'log' : { 'not': { 'field': { 'name': 'status', 'value': 0 } } } },
{ 'name': 'disconnect', 'log': false }
]
}
}
}';
select @f;
SELECT audit_log_filter_set_filter('log_conn_events', @f);
SELECT audit_log_filter_set_user('%', 'log_conn_events');
Default Value:
The default value for audit_log_connection_policy is ALL."
reference : "800-171|3.3.1,800-171|3.3.2,800-53|AU-12c.,CIS_Recommendation|6.5,CN-L3|7.1.3.3(a),CN-L3|7.1.3.3(b),CN-L3|7.1.3.3(c),CN-L3|8.1.3.5(a),CN-L3|8.1.3.5(b),CN-L3|8.1.4.3(a),CSF|DE.CM-1,CSF|DE.CM-3,CSF|DE.CM-7,CSF|PR.PT-1,ISO/IEC-27001|A.12.4.1,ITSG-33|AU-12c.,LEVEL|1M,NESA|T3.6.2,NESA|T3.6.5,NESA|T3.6.6,NIAv2|SM8,QCSC-v1|3.2,QCSC-v1|6.2,QCSC-v1|8.2.1,QCSC-v1|13.2,SWIFT-CSCv1|6.4,TBA-FIISB|45.1.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SHOW variables LIKE '%audit_log_connection_policy%';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : regex:".*audit_log_connection_policy.*", regex:"(ALL|ERRORS)"
type : SQL_POLICY
description : "6.8 Ensure the Audit Plugin Can't be Unloaded"
info : "Set audit_log to FORCE_PLUS_PERMANENT
Rationale:
This disables unloading on the plugin.
Impact:
If someone can unload the plugin it would be possible to perform actions on the database without audit events being logged to the audit log. If the audit log plugin can be unloaded the audit log can be temporarily or permanently disabled."
solution : "To remediate this setting, follow these steps:
Open the MySQL configuration file (my.cnf)
Ensure the following line is found in the mysqld section
audit_log = 'FORCE_PLUS_PERMANENT'
Default Value:
ON"
reference : "800-171|3.3.8,800-53|AU-9.,CIS_Recommendation|6.8,CN-L3|7.1.2.3(d),CN-L3|7.1.3.3(f),CN-L3|8.1.3.5(c),CN-L3|8.1.4.3(c),CSF|PR.PT-1,ISO/IEC-27001|A.12.4.2,ITSG-33|AU-9,LEVEL|1A,NESA|M5.2.3,NESA|M5.5.2,NESA|T3.6.4,NESA|T8.2.9,NIAv2|SM5,NIAv2|SM6,QCSC-v1|8.2.1,QCSC-v1|13.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT LOAD_OPTION FROM information_schema.plugins WHERE PLUGIN_NAME='audit_log';"
sql_types : POLICY_VARCHAR
sql_expect : "FORCE_PLUS_PERMANENT"
type : SQL_POLICY
description : "7.1 Ensure default_authentication_plugin is Set to a Secure Option"
info : "The -default-authentication-plugin system variable governs two things:
Authentication plugin used by a new user account if a plugin is not specified explicitly through CREATE USER statement
Initial authentication data payload generated by server in case of a new connection.
Caching SHA-2 Authentication is the new default in MySQL 8.0. It provides stronger password protection than the prior Native Authentication and provides better performance than SHA2 Authentication. Alternatively, there are additional methods to securely connect using Lightweight Directory Access Protocol (LDAP) and Active Directory authentication.
Rationale:
MySQL Native Authentication relies on the Secure Hash Algorithm 1 (SHA1) algorithm and the National Institute of Standards and Technology (NIST) has suggested to stop using it.
The MySQL Native Authentication plugin leverages this weak hashing algorithm that can be quickly brute forced."
solution : "Configure mysql to default to the caching_sha2_password plugin.
Require caching_sha2_password plugin to be used by default for new accounts.
Edit my.cnf, in the section [mysqld] add:
default_authentication_plugin=caching_sha2_password
Determine if any users are using mysql_native_password.
select host, user, plugin from mysql.user;
Migrate these users from mysql_native_password.
ALTER USER user
IDENTIFIED WITH caching_sha2_password IDENTIFIED BY RANDOM PASSWORD PASSWORD EXPIRE;
Provide users the random password value through a secure mechanism - on next login they will be forced to change the password.
Default Value:
New users default to caching_sha2_password. Migrated users will initially be mysql_native or other authentication method."
reference : "800-171|3.5.2,800-53|IA-5.,CIS_Recommendation|7.1,CSF|PR.AC-1,ITSG-33|IA-5,LEVEL|1A,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SHOW VARIABLES WHERE Variable_name = 'default_authentication_plugin';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "default_authentication_plugin", regex:"^(?:(?!mysql_native_password).)*$"
type : SQL_POLICY
description : "7.3 Ensure Passwords are Set for All MySQL Accounts"
info : "Blank passwords allow a user to login without using a password.
Rationale:
Without a password only knowing the username and the list of allowed hosts will allow someone to connect to the server and assume the identity of the user. This, in effect, bypasses authentication mechanisms."
solution : "For each row returned from the audit procedure, reset the password for the given user using the following statement (as an example):
ALTER USER
@ IDENTIFIED BY RANDOM PASSWORD PASSWORD EXPIRE;
This resets the password temporarily to a RANDOM string and returns that temporary password as a result.
The user can then use this temporary password to login and is forced to set the password to one of their choosing upon login.
Note: Replace , with appropriate values."
reference : "800-171|3.5.7,800-53|IA-5(1)(a),CIP|007-6-R5.5,CIS_Recommendation|7.3,CN-L3|7.1.2.7(e),CN-L3|7.1.3.1(b),CSF|PR.AC-1,HIPAA|164.308(a)(5)(ii)(D),ISO/IEC-27001|A.9.4.3,ITSG-33|IA-5(1)(a),LEVEL|1A,NESA|T5.2.3,NIAv2|AM19a,NIAv2|AM19b,NIAv2|AM19c,NIAv2|AM19d,NIAv2|AM22a,PCI-DSSv3.1|8.2.3,PCI-DSSv3.2|8.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2,SWIFT-CSCv1|4.1,TBA-FIISB|26.2.1,TBA-FIISB|26.2.4"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT User,host FROM mysql.user WHERE (plugin IN('mysql_native_password', 'mysql_old_password','') AND (LENGTH(authentication_string) = 0 OR authentication_string IS NULL)) OR (plugin='sha256_password' AND LENGTH(authentication_string) = 0);"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : NULL, NULL
type : SQL_POLICY
description : "7.4 Set 'default_password_lifetime' to Require a Yearly Password Change"
info : "Password expiry provides passwords with a time bounded lifetime.
Rationale:
The 'default_password_lifetime' global variable prevents a password being set for an indefinite period. Excessive password expiration requirements do more harm than good, because these requirements make users select predictable passwords, composed of sequential words and numbers that are closely related to each other. More importantly, when events occur that could compromise password security account passwords should be expired immediately.
Impact:
Scripted clients or users dependent on automated login in a controlled environment will need to consider their authentication procedures. The server will accept the user but the user is placed in restricted mode. In restricted mode, operations performed within the session result in an error until the user establishes a new account password."
solution : "To remediate this recommendation, execute the following command:
SET GLOBAL default_password_lifetime=365;
Default Value:
360"
reference : "800-171|3.5.2,800-53|IA-5(1)(d),CIP|007-6-R5.6,CIS_Recommendation|7.4,CN-L3|7.1.2.7(e),CN-L3|7.1.3.1(b),CSF|PR.AC-1,HIPAA|164.308(a)(5)(ii)(D),ISO/IEC-27001|A.9.4.3,ITSG-33|IA-5(1)(d),LEVEL|1A,NESA|T5.2.3,NIAv2|AM20,NIAv2|AM21,PCI-DSSv3.1|8.2.4,PCI-DSSv3.2|8.2.4,QCSC-v1|5.2.2,QCSC-v1|13.2,SWIFT-CSCv1|4.1,TBA-FIISB|26.2.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SHOW VARIABLES LIKE 'default_password_lifetime';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "default_password_lifetime", regex:"\b(?:36[0-5]|3[0-5]\d|[12]\d{2}|[1-9]\d?)\b"
check_option : CAN_NOT_BE_NULL
type : SQL_POLICY
description : "7.5 Ensure Password Complexity Policies are in Place - 'validate_password_length'"
info : "Password complexity includes password characteristics such as length, case, numerical, and character sets.
Rationale:
Complex passwords help mitigate dictionary, brute forcing, and other password attacks. This recommendation prevents users from choosing weak passwords which can easily be guessed."
solution : "Install component_validate_password component:
INSTALL COMPONENT 'file://component_validate_password';
Persist following configuration:
SET PERSIST validate_password.length=14;
SET PERSIST validate_password.check_user_name=ON;
SET PERSIST validate_password.dictionary_file=;
SET PERSIST validate_password.policy=STRONG;
Optionally set one or more of these - ensuring complexity is not overly onerous
SET PERSIST validate_password.mixed_case_count=1;
SET PERSIST validate_password.number_count=1;
SET PERSIST validate_password.special_char_count=1;
And change passwords for users which have passwords which are identical to their username.
Default Value:
By default component_validate_password is not installed.
validate_password.length=8
validate_password.mixed_case_count=1
validate_password.number_count=1
validate_password.policy=MEDIUM
validate_password.special_char_count=1"
reference : "800-171|3.5.2,800-53|IA-5.,CIS_Recommendation|7.5,CSF|PR.AC-1,ITSG-33|IA-5,LEVEL|1A,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SHOW VARIABLES LIKE 'validate_password_length'"
sql_types : POLICY_VARCHAR, POLICY_INTEGER
sql_expect : "validate_password.length", regex:"(1[4-9]|[2-9][0-9])"
type : SQL_POLICY
description : "7.5 Ensure Password Complexity Policies are in Place - 'validate_password_mixed_case_count'"
info : "Password complexity includes password characteristics such as length, case, numerical, and character sets.
Rationale:
Complex passwords help mitigate dictionary, brute forcing, and other password attacks. This recommendation prevents users from choosing weak passwords which can easily be guessed."
solution : "Install component_validate_password component:
INSTALL COMPONENT 'file://component_validate_password';
Persist following configuration:
SET PERSIST validate_password.length=14;
SET PERSIST validate_password.check_user_name=ON;
SET PERSIST validate_password.dictionary_file=;
SET PERSIST validate_password.policy=STRONG;
Optionally set one or more of these - ensuring complexity is not overly onerous
SET PERSIST validate_password.mixed_case_count=1;
SET PERSIST validate_password.number_count=1;
SET PERSIST validate_password.special_char_count=1;
And change passwords for users which have passwords which are identical to their username.
Default Value:
By default component_validate_password is not installed.
validate_password.length=8
validate_password.mixed_case_count=1
validate_password.number_count=1
validate_password.policy=MEDIUM
validate_password.special_char_count=1"
reference : "800-171|3.5.2,800-53|IA-5.,CIS_Recommendation|7.5,CSF|PR.AC-1,ITSG-33|IA-5,LEVEL|1A,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SHOW VARIABLES LIKE 'validate_password_mixed_case_count'"
sql_types : POLICY_VARCHAR, POLICY_INTEGER
sql_expect : "validate_password.mixed_case_count", regex:"[1-9]"
type : SQL_POLICY
description : "7.5 Ensure Password Complexity Policies are in Place - 'validate_password_number_count'"
info : "Password complexity includes password characteristics such as length, case, numerical, and character sets.
Rationale:
Complex passwords help mitigate dictionary, brute forcing, and other password attacks. This recommendation prevents users from choosing weak passwords which can easily be guessed."
solution : "Install component_validate_password component:
INSTALL COMPONENT 'file://component_validate_password';
Persist following configuration:
SET PERSIST validate_password.length=14;
SET PERSIST validate_password.check_user_name=ON;
SET PERSIST validate_password.dictionary_file=;
SET PERSIST validate_password.policy=STRONG;
Optionally set one or more of these - ensuring complexity is not overly onerous
SET PERSIST validate_password.mixed_case_count=1;
SET PERSIST validate_password.number_count=1;
SET PERSIST validate_password.special_char_count=1;
And change passwords for users which have passwords which are identical to their username.
Default Value:
By default component_validate_password is not installed.
validate_password.length=8
validate_password.mixed_case_count=1
validate_password.number_count=1
validate_password.policy=MEDIUM
validate_password.special_char_count=1"
reference : "800-171|3.5.2,800-53|IA-5.,CIS_Recommendation|7.5,CSF|PR.AC-1,ITSG-33|IA-5,LEVEL|1A,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SHOW VARIABLES LIKE 'validate_password_number_count'"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "validate_password.number_count", regex:"[1-9]"
type : SQL_POLICY
description : "7.5 Ensure Password Complexity Policies are in Place - 'validate_password_special_char_count'"
info : "Password complexity includes password characteristics such as length, case, numerical, and character sets.
Rationale:
Complex passwords help mitigate dictionary, brute forcing, and other password attacks. This recommendation prevents users from choosing weak passwords which can easily be guessed."
solution : "Install component_validate_password component:
INSTALL COMPONENT 'file://component_validate_password';
Persist following configuration:
SET PERSIST validate_password.length=14;
SET PERSIST validate_password.check_user_name=ON;
SET PERSIST validate_password.dictionary_file=;
SET PERSIST validate_password.policy=STRONG;
Optionally set one or more of these - ensuring complexity is not overly onerous
SET PERSIST validate_password.mixed_case_count=1;
SET PERSIST validate_password.number_count=1;
SET PERSIST validate_password.special_char_count=1;
And change passwords for users which have passwords which are identical to their username.
Default Value:
By default component_validate_password is not installed.
validate_password.length=8
validate_password.mixed_case_count=1
validate_password.number_count=1
validate_password.policy=MEDIUM
validate_password.special_char_count=1"
reference : "800-171|3.5.2,800-53|IA-5.,CIS_Recommendation|7.5,CSF|PR.AC-1,ITSG-33|IA-5,LEVEL|1A,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SHOW VARIABLES LIKE 'validate_password_special_char_count'"
sql_types : POLICY_VARCHAR, POLICY_INTEGER
sql_expect : "validate_password.special_char_count", regex:"[1-9]"
type : SQL_POLICY
description : "7.5 Ensure Password Complexity Policies are in Place - 'validate_password_policy'"
info : "Password complexity includes password characteristics such as length, case, numerical, and character sets.
Rationale:
Complex passwords help mitigate dictionary, brute forcing, and other password attacks. This recommendation prevents users from choosing weak passwords which can easily be guessed."
solution : "Install component_validate_password component:
INSTALL COMPONENT 'file://component_validate_password';
Persist following configuration:
SET PERSIST validate_password.length=14;
SET PERSIST validate_password.check_user_name=ON;
SET PERSIST validate_password.dictionary_file=;
SET PERSIST validate_password.policy=STRONG;
Optionally set one or more of these - ensuring complexity is not overly onerous
SET PERSIST validate_password.mixed_case_count=1;
SET PERSIST validate_password.number_count=1;
SET PERSIST validate_password.special_char_count=1;
And change passwords for users which have passwords which are identical to their username.
Default Value:
By default component_validate_password is not installed.
validate_password.length=8
validate_password.mixed_case_count=1
validate_password.number_count=1
validate_password.policy=MEDIUM
validate_password.special_char_count=1"
reference : "800-171|3.5.2,800-53|IA-5.,CIS_Recommendation|7.5,CSF|PR.AC-1,ITSG-33|IA-5,LEVEL|1A,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SHOW VARIABLES LIKE 'validate_password_policy'"
sql_types : POLICY_VARCHAR, POLICY_INTEGER
sql_expect : "validate_password.policy", regex:"(MEDIUM|STRONG)"
type : SQL_POLICY
description : "7.6 Ensure No Users Have Wildcard Hostnames"
info : "MySQL can make use of host wildcards when granting permissions to users on specific databases. For example, you may grant a given privilege to ''@'%'.
Rationale:
Avoiding the use of wildcards within hostnames helps control the specific locations from which a given user may connect to and interact with the database."
solution : "Perform the following actions to remediate this setting:
Enumerate all users returned after running the audit procedure.
Either ALTER the user's host to be specific or DROP the user."
reference : "800-171|3.1.1,800-53|AC-3.,CIS_Recommendation|7.6,CN-L3|8.1.4.2(f),CN-L3|8.1.4.11(b),CN-L3|8.1.10.2(c),CN-L3|8.5.3.1,CN-L3|8.5.4.1(a),CSF|PR.AC-4,CSF|PR.PT-3,ISO/IEC-27001|A.9.4.1,ISO/IEC-27001|A.9.4.5,ITSG-33|AC-3,LEVEL|1A,NESA|T4.2.1,NESA|T5.4.4,NESA|T5.4.5,NESA|T5.5.4,NESA|T5.6.1,NESA|T7.5.2,NESA|T7.5.3,NIAv2|AM3,NIAv2|SS29,QCSC-v1|3.2,QCSC-v1|5.2.2,QCSC-v1|13.2,TBA-FIISB|31.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "select user,host from mysql.user where host = '%' ;"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : NULL, NULL
type : SQL_POLICY
description : "7.7 Ensure No Anonymous Accounts Exist"
info : "Anonymous accounts are users with empty usernames (''). Anonymous accounts have no passwords, so anyone can use them to connect to the MySQL server.
Rationale:
Removing anonymous accounts will help ensure that only identified and trusted principals are capable of interacting with MySQL.
Impact:
Any applications relying on anonymous database access will be adversely affected by this change."
solution : "Perform the following actions to remediate this setting:
Enumerate the anonymous users returned from executing the audit procedure.
For each anonymous user, DROP or assign them a name.
Note: As an alternative, you may execute the mysql_secure_installation utility."
reference : "800-53|AC-14a.,CIS_Recommendation|7.7,ITSG-33|AC-14a.,LEVEL|1A,NESA|T5.6.1,QCSC-v1|5.2.2,QCSC-v1|13.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT user,host FROM mysql.user WHERE user = '';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : NULL,NULL
type : SQL_POLICY
description : "have_ssl' is Set to 'YES'"
sql_request : "SHOW variables WHERE variable_name = 'have_ssl';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "have_ssl", "YES"
check_option : CAN_NOT_BE_NULL
type : SQL_POLICY
description : "have_openssl' is Set to 'YES'"
sql_request : "SHOW variables WHERE variable_name = 'have_openssl';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "have_openssl", "YES"
check_option : CAN_NOT_BE_NULL
description : "8.1 Ensure 'require_secure_transport' is Set to 'ON' and/or 'have_ssl' is Set to 'YES'"
info : "All network traffic must use SSL/TLS when traveling over untrusted networks.
Rationale:
The SSL/TLS-protected MySQL protocol helps to prevent eavesdropping and man-in-the-middle attacks.
Impact:
Enabling Secure Sockets Layer (SSL) will allow clients to encrypt network traffic and verify the identity of the server. This could have impact on network traffic inspection."
solution : "Follow the procedures as documented in the MySQL 8.0 Reference Manual to setup SSL.
Set global policy to force SSL for all connections:
set persist require_secure_transport=ON;
Default Value:
DISABLED"
reference : "800-171|3.1.13,800-171|3.3.1,800-171|3.3.2,800-53|AC-17(2),800-53|AU-12.,CIS_Recommendation|8.1,CN-L3|7.1.2.7(g),CN-L3|7.1.3.1(d),CN-L3|8.1.4.1(c),CSF|DE.CM-1,CSF|DE.CM-3,CSF|DE.CM-7,CSF|PR.AC-3,CSF|PR.PT-1,CSF|PR.PT-4,ISO/IEC-27001|A.6.2.2,ITSG-33|AC-17(2),ITSG-33|AU-12,LEVEL|1A,NESA|T5.4.2,NIAv2|AM37,QCSC-v1|3.2,QCSC-v1|5.2.1,QCSC-v1|5.2.2,QCSC-v1|6.2,QCSC-v1|8.2.1,QCSC-v1|13.2,SWIFT-CSCv1|2.6,SWIFT-CSCv1|6.4"
see_also : "https://workbench.cisecurity.org/files/3477"
type : SQL_POLICY
description : "8.1 Ensure 'require_secure_transport' is Set to 'ON' and/or 'have_ssl' is Set to 'YES'"
info : "All network traffic must use SSL/TLS when traveling over untrusted networks.
Rationale:
The SSL/TLS-protected MySQL protocol helps to prevent eavesdropping and man-in-the-middle attacks.
Impact:
Enabling Secure Sockets Layer (SSL) will allow clients to encrypt network traffic and verify the identity of the server. This could have impact on network traffic inspection."
solution : "Follow the procedures as documented in the MySQL 8.0 Reference Manual to setup SSL.
Set global policy to force SSL for all connections:
set persist require_secure_transport=ON;
Default Value:
DISABLED"
reference : "800-171|3.1.13,800-171|3.3.1,800-171|3.3.2,800-53|AC-17(2),800-53|AU-12.,CIS_Recommendation|8.1,CN-L3|7.1.2.7(g),CN-L3|7.1.3.1(d),CN-L3|8.1.4.1(c),CSF|DE.CM-1,CSF|DE.CM-3,CSF|DE.CM-7,CSF|PR.AC-3,CSF|PR.PT-1,CSF|PR.PT-4,ISO/IEC-27001|A.6.2.2,ITSG-33|AC-17(2),ITSG-33|AU-12,LEVEL|1A,NESA|T5.4.2,NIAv2|AM37,QCSC-v1|3.2,QCSC-v1|5.2.1,QCSC-v1|5.2.2,QCSC-v1|6.2,QCSC-v1|8.2.1,QCSC-v1|13.2,SWIFT-CSCv1|2.6,SWIFT-CSCv1|6.4"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "select @@require_secure_transport;"
sql_types : POLICY_VARCHAR
sql_expect : regex:"(ON|1)"
type : SQL_POLICY
description : "8.2 Ensure 'ssl_type' is Set to 'ANY', 'X509', or 'SPECIFIED' for All Remote Users - SPECIFIED for All Remote Users"
info : "All network traffic must use SSL/TLS when traveling over untrusted networks.
SSL/TLS should be enforced on a per-user basis for users which enter the system through the network.
Rationale:
The SSL/TLS-protected MySQL protocol helps to prevent eavesdropping and man-in-the-middle attacks.
Impact:
When SSL/TLS is enforced then clients which do not use SSL will not be able to connect. If the server is not configured for SSL/TLS then accounts for which SSL/TLS is mandatory will not be able to connect."
solution : "Use the ALTER USER statement to require the use of SSL:
ALTER USER 'my_user'@'app1.example.com' REQUIRE X509;
Note: REQUIRE SSL only enforces SSL. There are additional options REQUIRE ISSUER, REQUIRE SUBJECT which can be used to further restrict the connection.
Default Value:
On the server-side SSL is ON by default --ssl (permits but does not require secure connections) and require_secure_transport is OFF (turning ON allows only secure connections)"
reference : "800-171|3.13.8,800-53|SC-8(1),CIS_Recommendation|8.2,CN-L3|8.1.2.2(a),CN-L3|8.1.2.2(b),CN-L3|8.1.4.7(a),CN-L3|8.1.4.8(a),CN-L3|8.2.4.5(c),CN-L3|8.2.4.5(d),CN-L3|8.5.2.2,CSF|PR.DS-2,CSF|PR.DS-5,ISO/IEC-27001|A.10.1.1,ISO/IEC-27001|A.13.2.3,ITSG-33|SC-8(1),LEVEL|1A,NESA|T7.4.1,NIAv2|NS5d,NIAv2|NS6b,QCSC-v1|5.2.2,QCSC-v1|6.2,SWIFT-CSCv1|2.1,TBA-FIISB|29.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT user, host, ssl_type FROM mysql.user WHERE NOT HOST IN ('::1', '127.0.0.1', 'localhost');"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : regex: ".+", regex:".+", regex:"(ANY|X509|SPECIFIED)"
type : SQL_POLICY
description : "max_connections is set"
sql_request : "SELECT VARIABLE_NAME, VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME LIKE 'max_connections';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "max_connections", regex:"^[1-9][0-9]*$"
check_option : CAN_NOT_BE_NULL
description : "8.3 Set Maximum Connection Limits for Server and per User"
info : "Limiting concurrent connections to a MySQL server can be used to reduce risk of Denial of Service (DoS) attacks performed by exhausting connection resources.
Rationale:
Limiting the number of concurrent sessions at the server and per user level helps to reduce the risk of DoS attacks. MySQL provides mechanisms to limit the number of simultaneous connections that can be made at the server level or by any given account."
solution : "Connect to the MySQL Database as an administrator.
For example, to set the global default per user to 50 run the command:
SET PERSIST max_user_connections=50;
To control the maximum number of clients the server permits to connect simultaneously, set the max_connections system variable:
SET PERSIST max_connections=1000;
Additionally, this max user connections can be set per user as well as for a given period of time period using CREATE or ALTER.
For example:
ALTER USER 'fred'@'localhost'
WITH MAX_CONNECTIONS_PER_HOUR 5
MAX_USER_CONNECTIONS 2;
Default Value:
The default value of max_connections is 151, max_user_connections is 0 (unlimited, thus limited by max_connections)."
reference : "800-171|3.1.11,800-53|AC-12.,CIS_Recommendation|8.3,CN-L3|7.1.2.2(d),CN-L3|7.1.3.7(b),CN-L3|8.1.4.1(b),ITSG-33|AC-12,LEVEL|1M,NIAv2|NS49"
see_also : "https://workbench.cisecurity.org/files/3477"
type : SQL_POLICY
description : "8.3 Set Maximum Connection Limits for Server and per User"
info : "Limiting concurrent connections to a MySQL server can be used to reduce risk of Denial of Service (DoS) attacks performed by exhausting connection resources.
Rationale:
Limiting the number of concurrent sessions at the server and per user level helps to reduce the risk of DoS attacks. MySQL provides mechanisms to limit the number of simultaneous connections that can be made at the server level or by any given account."
solution : "Connect to the MySQL Database as an administrator.
For example, to set the global default per user to 50 run the command:
SET PERSIST max_user_connections=50;
To control the maximum number of clients the server permits to connect simultaneously, set the max_connections system variable:
SET PERSIST max_connections=1000;
Additionally, this max user connections can be set per user as well as for a given period of time period using CREATE or ALTER.
For example:
ALTER USER 'fred'@'localhost'
WITH MAX_CONNECTIONS_PER_HOUR 5
MAX_USER_CONNECTIONS 2;
Default Value:
The default value of max_connections is 151, max_user_connections is 0 (unlimited, thus limited by max_connections)."
reference : "800-171|3.1.11,800-53|AC-12.,CIS_Recommendation|8.3,CN-L3|7.1.2.2(d),CN-L3|7.1.3.7(b),CN-L3|8.1.4.1(b),ITSG-33|AC-12,LEVEL|1M,NIAv2|NS49"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT VARIABLE_NAME, VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME LIKE 'max_user_connections';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : "max_user_connections", regex:"^[1-9][0-9]*$"
check_option : CAN_NOT_BE_NULL
description : "9.1 Ensure Replication Traffic is Secured"
info : "The replication traffic between servers should be secured. Security measures should include ensuring the confidentiality and integrity of the traffic, and performing mutual authentication between the servers before performing replication.
Rationale:
The replication traffic should be secured as it gives access to all transferred information and might leak passwords.
Impact:
When the replication traffic is not secured someone might be able to capture passwords and other sensitive information when sent to the replica.
NOTE: Nessus has not performed this check. Please review the benchmark to ensure target compliance.
NOTE: Nessus has not performed this check. Please review the benchmark to ensure target compliance."
solution : "Secure the network traffic using one or more technologies to provide confidentiality and integrity for the traffic, and mutual authentication for the servers."
reference : "CIS_Recommendation|9.1,CSCv7|14.4,LEVEL|1M,800-53|SC-8"
see_also : "https://workbench.cisecurity.org/files/3477"
type : SQL_POLICY
description : "ssl_verify_server_cert setting on 8.0.23 or greater"
sql_request : "select ssl_verify_server_cert from mysql.replica_source_info;"
sql_types : POLICY_INTEGER
sql_expect : "1"
description : "9.2 Ensure 'SOURCE_SSL_VERIFY_SERVER_CERT' is Set to 'YES' or '1'"
info : "In the MySQL REPLICA (SLAVE is deprecated as of 8.0.22) context the setting SOURCE_SSL_VERIFY_SERVER_CERT (MASTER_SSL_VERIFY_SERVER_CERT is deprecated as of 8.0.22) indicates whether the REPLICA should verify the SOURCE's certificate. This configuration item may be set to Yes or No, and unless SSL has been enabled on the REPLICA, the value will be ignored.
Rationale:
When SSL is in use certificate verification is important to authenticate the party to which a connection is being made. In this case, the REPLICA (client) should verify the SOURCE's (server's) certificate to authenticate the SOURCE prior to continuing the connection.
Impact:
When using CHANGE REPLICATION SOURCE TO, (CHANGE MASTER is deprecated as of 8.0.23) be aware of the following:
REPLICA processes need to be stopped prior to executing CHANGE SOURCE TO
Use of CHANGE REPLICATION SOURCE TO starts new relay logs without keeping the old ones unless explicitly told to keep them
When CHANGE REPLICATION SOURCE TO is invoked, some information is dumped to the error log (previous values for SOURCE_HOST, SOURCE_PORT, SOURCE_LOG_FILE, and SOURCE_LOG_POS)
Invoking CHANGE REPLICATION SOURCE TO will implicitly commit any ongoing transactions in the session where the CHANGE REPLICATION SOURCE was run, but not all ongoing transactions on the database."
solution : "To remediate this setting, you must use the CHANGE SOURCE TO command.
From 8.0.23:
STOP REPLICA; -- required if replication was already running
CHANGE REPLICATION SOURCE TO SOURCE_SSL_VERIFY_SERVER_CERT=1;
START REPLICA; -- required if you want to restart replication
Prior to 8.0.23:
STOP SLAVE; -- required if replication was already running
CHANGE MASTER TO MASTER_SSL_VERIFY_SERVER_CERT=1;
START SLAVE; -- required if you want to restart replication"
reference : "800-171|3.5.2,800-53|IA-5(2)(a),CIS_Recommendation|9.2,CSF|PR.AC-1,ITSG-33|IA-5(2)(a),LEVEL|1M,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2"
see_also : "https://workbench.cisecurity.org/files/3477"
type : SQL_POLICY
description : "9.2 Ensure 'SOURCE_SSL_VERIFY_SERVER_CERT' is Set to 'YES' or '1'"
info : "In the MySQL REPLICA (SLAVE is deprecated as of 8.0.22) context the setting SOURCE_SSL_VERIFY_SERVER_CERT (MASTER_SSL_VERIFY_SERVER_CERT is deprecated as of 8.0.22) indicates whether the REPLICA should verify the SOURCE's certificate. This configuration item may be set to Yes or No, and unless SSL has been enabled on the REPLICA, the value will be ignored.
Rationale:
When SSL is in use certificate verification is important to authenticate the party to which a connection is being made. In this case, the REPLICA (client) should verify the SOURCE's (server's) certificate to authenticate the SOURCE prior to continuing the connection.
Impact:
When using CHANGE REPLICATION SOURCE TO, (CHANGE MASTER is deprecated as of 8.0.23) be aware of the following:
REPLICA processes need to be stopped prior to executing CHANGE SOURCE TO
Use of CHANGE REPLICATION SOURCE TO starts new relay logs without keeping the old ones unless explicitly told to keep them
When CHANGE REPLICATION SOURCE TO is invoked, some information is dumped to the error log (previous values for SOURCE_HOST, SOURCE_PORT, SOURCE_LOG_FILE, and SOURCE_LOG_POS)
Invoking CHANGE REPLICATION SOURCE TO will implicitly commit any ongoing transactions in the session where the CHANGE REPLICATION SOURCE was run, but not all ongoing transactions on the database."
solution : "To remediate this setting, you must use the CHANGE SOURCE TO command.
From 8.0.23:
STOP REPLICA; -- required if replication was already running
CHANGE REPLICATION SOURCE TO SOURCE_SSL_VERIFY_SERVER_CERT=1;
START REPLICA; -- required if you want to restart replication
Prior to 8.0.23:
STOP SLAVE; -- required if replication was already running
CHANGE MASTER TO MASTER_SSL_VERIFY_SERVER_CERT=1;
START SLAVE; -- required if you want to restart replication"
reference : "800-171|3.5.2,800-53|IA-5(2)(a),CIS_Recommendation|9.2,CSF|PR.AC-1,ITSG-33|IA-5(2)(a),LEVEL|1M,NESA|T5.2.3,QCSC-v1|5.2.2,QCSC-v1|13.2"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "select ssl_verify_server_cert from mysql.slave_master_info;"
sql_types : POLICY_INTEGER
sql_expect : "1"
type : SQL_POLICY
description : "9.4 Ensure 'super_priv' is Not Set to 'Y' for Replication Users - Y for Replication Users"
info : "The SUPER privilege found in the mysql.user table governs the use of a variety of MySQL features. These features include, CHANGE MASTER TO, KILL, mysqladmin kill option, PURGE BINARY LOGS, SET GLOBAL, mysqladmin debug option, logging control, and more.
Rationale:
The SUPER privilege allows principals to perform many actions, including view and terminate currently executing MySQL statements (including statements used to manage passwords). This privilege also provides the ability to configure MySQL, such as enable/disable logging, alter data, disable/enable features. Limiting the accounts that have the SUPER privilege reduces the chances that an attacker can exploit these capabilities.
Impact:
When the SUPER privilege is denied to a given user, that user will be unable to take advantage of certain capabilities, such as certain mysqladmin options."
solution : "Execute the following steps to remediate this setting:
Enumerate the replication users found in the result set of the audit procedure
For each replication user, issue the following SQL statement (replace repl with your replication user's name):
REVOKE SUPER ON *.* FROM 'repl';
Note: Prior to 8.0.21 if MySQL Replica Set was used to create the replications administrator (call to dba.configureReplicaSetInstance in MySQL Shell) after performing the above revoke you will need to grant the following dynamic privilege.
GRANT REPLICATION_SLAVE_ADMIN ON *.* TO 'repl WITH GRANT OPTION;"
reference : "800-171|3.1.5,800-53|AC-6(5),CIS_Recommendation|9.4,CN-L3|8.1.10.6(a),CSCv6|5.1,CSF|PR.AC-4,ISO/IEC-27001|A.9.2.3,ITSG-33|AC-6(5),LEVEL|1A,NESA|T5.1.1,NESA|T5.2.2,NESA|T5.6.1,NIAv2|AM32,NIAv2|AM33,NIAv2|VL3a,QCSC-v1|5.2.2,QCSC-v1|6.2,SWIFT-CSCv1|1.2,TBA-FIISB|31.4.2,TBA-FIISB|31.4.3"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "select user, host from mysql.user where user='repl' and Super_priv = 'Y';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : NULL, NULL
type : SQL_POLICY
description : "9.5 Ensure No Replication Users Have Wildcard Hostnames"
info : "MySQL can make use of host wildcards when granting permissions to users on specific databases. For example, you may grant a given privilege to ''@'%'.
Rationale:
Avoiding the use of wildcards within hostnames helps control the specific locations from which a given user may connect to and interact with the database."
solution : "Perform the following actions to remediate this setting:
Enumerate all users returned after running the audit procedure.
Either ALTER the user's host to be specific or DROP the user."
reference : "800-171|3.1.1,800-53|AC-3.,CIS_Recommendation|9.5,CN-L3|8.1.4.2(f),CN-L3|8.1.4.11(b),CN-L3|8.1.10.2(c),CN-L3|8.5.3.1,CN-L3|8.5.4.1(a),CSF|PR.AC-4,CSF|PR.PT-3,ISO/IEC-27001|A.9.4.1,ISO/IEC-27001|A.9.4.5,ITSG-33|AC-3,LEVEL|1A,NESA|T4.2.1,NESA|T5.4.4,NESA|T5.4.5,NESA|T5.5.4,NESA|T5.6.1,NESA|T7.5.2,NESA|T7.5.3,NIAv2|AM3,NIAv2|SS29,QCSC-v1|3.2,QCSC-v1|5.2.2,QCSC-v1|13.2,TBA-FIISB|31.1"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "SELECT user, host FROM mysql.user WHERE user='repl' AND host = '%';"
sql_types : POLICY_VARCHAR, POLICY_VARCHAR
sql_expect : NULL, NULL
type : SQL_POLICY
description : "10.1 Ensure All Group Replication Traffic is Secured"
info : "MySQL Group communication connections and distributed recovery connections can be secured using SSL.
Rationale:
SSL encryption ensures data cannot be seen over the network for Group Replication."
solution : "Edit my.cnf and set group_replication_ssl_mode, for example:
group_replication_ssl_mode=REQUIRED
Acceptable values are:
REQUIRED - Establish a secure connection if the server supports secure connections.
VERIFY_CA - Like REQUIRED, but additionally verify the server TLS certificate against the configured Certificate Authority (CA) certificates.
VERIFY_IDENTITY - Like VERIFY_CA, but additionally verify that the server certificate matches the host to which the connection is being established."
reference : "800-171|3.1.13,800-53|AC-17(2),CIS_Recommendation|10.1,CN-L3|7.1.2.7(g),CN-L3|7.1.3.1(d),CN-L3|8.1.4.1(c),CSF|PR.AC-3,CSF|PR.PT-4,ISO/IEC-27001|A.6.2.2,ITSG-33|AC-17(2),LEVEL|1M,NESA|T5.4.2,NIAv2|AM37,QCSC-v1|3.2,QCSC-v1|5.2.1,QCSC-v1|5.2.2,SWIFT-CSCv1|2.6"
see_also : "https://workbench.cisecurity.org/files/3477"
sql_request : "select @@group_replication_ssl_mode;"
sql_types : POLICY_VARCHAR
sql_expect : regex: "REQUIRED|VERIFY_CA|VERIFY_IDENTITY"
description : "CIS_MySQL_8.0_Enterprise_Benchmark_v1.1.0_Level_1_DB.audit from CIS Oracle MySQL 8.0 Enterprise Edition v1.1.0"
info : "NOTE: Nessus has not identified that the chosen audit applies to the target device.
NOTE: Nessus has not performed this check. Please review the benchmark to ensure target compliance."
see_also : "https://workbench.cisecurity.org/files/3477"