CIS Oracle MySQL Community Server 8.0 Benchmark
Secure configuration guidelines for MySQL 8.0 Community and Enterprise editions
v1.3.0 January 2025Overview
▶This CIS Benchmark provides prescriptive guidance for establishing a secure configuration posture for MySQL 8.0. Recommendations cover OS-level hardening, file permissions, authentication, privilege management, logging, TLS, and replication security.
Profile Definitions
▶| Profile | Description | Intended Use |
|---|---|---|
| L1 | Level 1 — MySQL Server | Essential security for all MySQL deployments. |
| L2 | Level 2 — MySQL Server | Defense-in-depth. May impact performance or require application changes. |
1 — Operating System Level Configuration
▶1.1 File System
▶This recommendation verifies that the datadir Has Appropriate Permissions on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to the datadir Has Appropriate Permissions may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
SELECT @@datadir; stat -c '%a %U:%G' /var/lib/mysql # Should be 750 mysql:mysql
chmod 750 /var/lib/mysql chown mysql:mysql /var/lib/mysql
This recommendation verifies that the log_bin_basename Has Appropriate Permissions on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to the log_bin_basename Has Appropriate Permissions may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
SELECT @@log_bin_basename; ls -la /var/lib/mysql/*-bin.*
chmod 660 /var/lib/mysql/*-bin.* chown mysql:mysql /var/lib/mysql/*-bin.*
1.2 MySQL User
▶This recommendation verifies that MySQL Is Run Using a Non-Root User on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to mySQL Is Run Using a Non-Root User may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
ps -ef | grep mysqld | grep -v grep # Should show mysql user, not root
# my.cnf [mysqld]: user=mysql
This recommendation verifies that the MySQL User Has an Invalid Shell on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to the MySQL User Has an Invalid Shell may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
getent passwd mysql | cut -d: -f7 # Should be /bin/false or /sbin/nologin
usermod -s /sbin/nologin mysql
2 — Installation & Planning
▶2.1 Backup & Recovery
▶This recommendation verifies that Backups Are Regularly Performed and Tested on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to backups Are Regularly Performed and Tested may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
Review backup schedules, verify backup files exist, and confirm restore procedures have been tested.
# Check recent backup: ls -la /var/backups/mysql/
# Set up automated MySQL backups using mysqldump: # Create a daily backup script: cat <<'EOF' > /usr/local/bin/mysql-backup.sh #!/bin/bash BACKUP_DIR="/var/backups/mysql" DATE=$(date +%Y%m%d_%H%M%S) mkdir -p "$BACKUP_DIR" mysqldump --all-databases --single-transaction --routines --triggers \ --result-file="$BACKUP_DIR/full_backup_$DATE.sql" # Compress the backup: gzip "$BACKUP_DIR/full_backup_$DATE.sql" # Remove backups older than 30 days: find "$BACKUP_DIR" -name "*.sql.gz" -mtime +30 -delete EOF chmod 700 /usr/local/bin/mysql-backup.sh # Schedule via cron (daily at 2 AM): echo "0 2 * * * /usr/local/bin/mysql-backup.sh" | crontab - # Test backup restoration quarterly on a non-production instance.
2.2 Dedicated Machine
▶This recommendation verifies that MySQL Is Installed on a Dedicated Server on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to mySQL Is Installed on a Dedicated Server may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
ss -tlnp | grep -v mysql # Verify only essential services are running
# 1. Provision a dedicated server (physical or virtual) for MySQL # 2. Ensure no other network-accessible services are running: ss -tlnp | grep -v mysqld # Remove or disable any non-essential services # 3. Verify only MySQL-related processes are listening: ss -tlnp # Only mysqld should be listening on port 3306 # 4. Restrict the firewall to allow only MySQL traffic: # iptables example: iptables -A INPUT -p tcp --dport 3306 -s <app_server_ip> -j ACCEPT iptables -A INPUT -p tcp --dport 3306 -j DROP # Document the dedicated-server requirement in the deployment standard.
This recommendation verifies that the Latest Security Patches Are Applied on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to the Latest Security Patches Are Applied may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
mysql --version # Compare against https://dev.mysql.com/doc/relnotes/mysql/8.0/en/
# Update MySQL to the latest patch release: # RHEL/CentOS: sudo yum update -y mysql-community-server # Debian/Ubuntu: sudo apt-get update && sudo apt-get install -y mysql-server # Verify the current version after patching: mysql --version # Or from within MySQL: SELECT VERSION(); # Restart MySQL to apply updates: sudo systemctl restart mysqld # Subscribe to Oracle's Critical Patch Update advisories: # https://www.oracle.com/security-alerts/ # Review and apply patches within the organizationally defined timeframe.
3 — File System Permissions
▶3.1 Data & Log Directories
▶This recommendation verifies that plugin_dir Has Appropriate Permissions on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to plugin_dir Has Appropriate Permissions may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
SELECT @@plugin_dir; stat -c '%a %U:%G' /usr/lib64/mysql/plugin # Should be 750 mysql:mysql or 755 root:root
chmod 750 /usr/lib64/mysql/plugin
This recommendation verifies that the Audit Log Directory Has Appropriate Permissions on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to the Audit Log Directory Has Appropriate Permissions may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
SELECT @@audit_log_file; stat -c '%a %U:%G' /var/lib/mysql/audit.log
chmod 660 /var/lib/mysql/audit.log chown mysql:mysql /var/lib/mysql/audit.log
3.2 Configuration Files
▶This recommendation verifies that my.cnf Has Appropriate Permissions on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to my.cnf Has Appropriate Permissions may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
stat -c '%a %U:%G' /etc/my.cnf /etc/mysql/my.cnf 2>/dev/null # Should be 644 root:root or more restrictive
chmod 644 /etc/my.cnf chown root:root /etc/my.cnf
4 — General Configuration
▶4.1 Server Configuration
▶This setting controls whether 'local_infile' is disabled on the MySQL 8 database server. Disabling this feature reduces the attack surface by removing unnecessary functionality that could be exploited by an attacker.
Leaving 'local_infile' enabled when it is not required unnecessarily expands the attack surface. An attacker could leverage this feature to gain unauthorized access or escalate privileges on the MySQL 8 database server.
SHOW GLOBAL VARIABLES LIKE 'local_infile'; -- Should be OFF
# my.cnf [mysqld]: local_infile=0
This setting controls whether 'skip-symbolic-links' is enabled on the MySQL 8 database server. Enabling this feature strengthens the security posture by enforcing the recommended configuration via my.cnf, mysqld configuration, or SQL commands.
Without 'skip-symbolic-links' enabled, the MySQL 8 database server may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.
SHOW GLOBAL VARIABLES LIKE 'have_symlink'; -- Should be DISABLED
# my.cnf [mysqld]: symbolic-links=0
This recommendation addresses the proper configuration of 'secure_file_priv' on the MySQL 8 database server. Proper configuration ensures the component operates securely and in accordance with organizational security policies.
Misconfiguration of 'secure_file_priv' can lead to security gaps that may be exploited by attackers. A properly configured MySQL 8 database server reduces exposure to both known vulnerabilities and configuration drift.
SHOW GLOBAL VARIABLES LIKE 'secure_file_priv'; -- Should not be empty string
# my.cnf [mysqld]: secure_file_priv=/var/lib/mysql-files/
This recommendation verifies that 'sql_mode' Contains 'STRICT_ALL_TABLES' on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to 'sql_mode' Contains 'STRICT_ALL_TABLES' may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
SELECT @@sql_mode; -- Should contain STRICT_ALL_TABLES
# my.cnf [mysqld]: sql_mode=STRICT_ALL_TABLES,NO_ENGINE_SUBSTITUTION
4.2 Network & Connections
▶This recommendation addresses the proper configuration of 'bind-address' on the MySQL 8 database server. Proper configuration ensures the component operates securely and in accordance with organizational security policies.
Misconfiguration of 'bind-address' can lead to security gaps that may be exploited by attackers. A properly configured MySQL 8 database server reduces exposure to both known vulnerabilities and configuration drift.
SHOW GLOBAL VARIABLES LIKE 'bind_address'; -- Should not be '*' or '0.0.0.0' unless required
# my.cnf [mysqld]: bind-address=127.0.0.1
This setting enforces that 'skip-networking' Is Enabled When Not is required on the MySQL 8 database server. Making this mandatory ensures consistent security policy enforcement across the environment.
Failure to 'skip-networking' Is Enabled When Not Required may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
SHOW GLOBAL VARIABLES LIKE 'skip_networking'; -- If only local access needed, should be ON
# my.cnf [mysqld]: skip-networking
This recommendation verifies that 'max_connections' Is Set Appropriately on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to 'max_connections' Is Set Appropriately may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
SHOW GLOBAL VARIABLES LIKE 'max_connections';
# Set to organizational requirement: SET GLOBAL max_connections = 151;
5 — MySQL Permissions & Privileges
▶5.1 Access Control
▶This recommendation verifies that No Anonymous Accounts is present on the MySQL 8 database server. Having this configuration in place is essential for maintaining the expected security baseline defined by the CIS benchmark.
The absence of No Anonymous Accounts leaves the MySQL 8 database server without an important security control. Verifying its presence ensures the system meets the minimum security baseline required by the CIS benchmark.
SELECT user, host FROM mysql.user WHERE user = ''; -- Should return empty
DROP USER ''@'localhost'; DROP USER ''@'%';
'test' Database should be removed from the MySQL 8 database server when not required. Removing unnecessary components reduces the attack surface and limits the number of potential vulnerabilities that need to be managed.
Retaining 'test' Database when it is not needed increases the attack surface. Unpatched or unused components are frequent targets for exploitation and should be removed as part of system hardening.
SHOW DATABASES LIKE 'test'; -- Should return empty
DROP DATABASE test;
This recommendation verifies that 'root' Login Is Only Allowed from Localhost on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to 'root' Login Is Only Allowed from Localhost may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
SELECT user, host FROM mysql.user WHERE user = 'root'; -- host should only be 'localhost' or '127.0.0.1'
DELETE FROM mysql.user WHERE user='root' AND host NOT IN ('localhost', '127.0.0.1', '::1');
FLUSH PRIVILEGES;5.2 Privilege Grants
▶This setting ensures that SUPER Privilege is restricted on the MySQL 8 database server. Restricting this capability limits potential abuse and enforces the principle of least privilege across the environment.
Unrestricted SUPER Privilege could allow unauthorized users or processes to perform actions beyond their intended scope. Applying least-privilege principles to the MySQL 8 database server is essential for defense in depth.
SELECT user, host FROM mysql.user WHERE Super_priv = 'Y'; -- Should be minimal (e.g., root@localhost only)
REVOKE SUPER ON *.* FROM 'username'@'host';
This recommendation verifies that FILE Privilege Is Not Granted to Non-Admin Users on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to fILE Privilege Is Not Granted to Non-Admin Users may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
SELECT user, host FROM mysql.user WHERE File_priv = 'Y';
REVOKE FILE ON *.* FROM 'username'@'host';
This setting ensures that PROCESS Privilege is restricted on the MySQL 8 database server. Restricting this capability limits potential abuse and enforces the principle of least privilege across the environment.
Unrestricted PROCESS Privilege could allow unauthorized users or processes to perform actions beyond their intended scope. Applying least-privilege principles to the MySQL 8 database server is essential for defense in depth.
SELECT user, host FROM mysql.user WHERE Process_priv = 'Y';
REVOKE PROCESS ON *.* FROM 'username'@'host';
Wildcard Hosts should not be used on the MySQL 8 database server. Removing or disabling this component reduces the attack surface and prevents potential exploitation of unnecessary services or features.
If Wildcard Hosts remains used, it presents an unnecessary risk vector that attackers could exploit. Removing or disabling unused components is a fundamental principle of secure system hardening.
SELECT user, host FROM mysql.user WHERE host = '%'; -- Should return empty or only intended accounts
Replace wildcard host entries (%) with specific hostnames or IP addresses.
6 — Audit & Logging
▶6.1 General & Error Logs
▶This setting controls whether the Error Log is enabled on the MySQL 8 database server. Enabling this feature strengthens the security posture by enforcing the recommended configuration via my.cnf, mysqld configuration, or SQL commands.
Without the Error Log enabled, the MySQL 8 database server may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.
SHOW GLOBAL VARIABLES LIKE 'log_error'; -- Should point to a valid file path
# my.cnf [mysqld]: log_error=/var/log/mysql/error.log
This recommendation configures 'log_error_verbosity' to at Least 2 on the MySQL 8 database server. Setting this value appropriately ensures the system operates within the security parameters defined by the CIS benchmark.
An improperly configured value for 'log_error_verbosity' could weaken security controls or allow unintended behavior. Setting this to at Least 2 ensures the MySQL 8 database server operates within a well-defined security boundary.
SHOW GLOBAL VARIABLES LIKE 'log_error_verbosity'; -- Should be 2 (errors + warnings) or 3 (+ notes)
# my.cnf [mysqld]: log_error_verbosity=3
6.2 Binary & Slow Logs
▶This setting controls whether Binary Logging is enabled on the MySQL 8 database server. Enabling this feature strengthens the security posture by enforcing the recommended configuration via my.cnf, mysqld configuration, or SQL commands.
Without Binary Logging enabled, the MySQL 8 database server may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.
SHOW GLOBAL VARIABLES LIKE 'log_bin'; -- Should be ON
# my.cnf [mysqld]: log_bin=/var/lib/mysql/mysql-bin server-id=1
This setting controls whether Slow Query Log is enabled on the MySQL 8 database server. Enabling this feature strengthens the security posture by enforcing the recommended configuration via my.cnf, mysqld configuration, or SQL commands.
Without Slow Query Log enabled, the MySQL 8 database server may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.
SHOW GLOBAL VARIABLES LIKE 'slow_query_log'; SHOW GLOBAL VARIABLES LIKE 'long_query_time';
# my.cnf [mysqld]: slow_query_log=1 slow_query_log_file=/var/log/mysql/slow.log long_query_time=10
This recommendation addresses the proper configuration of 'binlog_expire_logs_seconds' on the MySQL 8 database server. Proper configuration ensures the component operates securely and in accordance with organizational security policies.
Misconfiguration of 'binlog_expire_logs_seconds' can lead to security gaps that may be exploited by attackers. A properly configured MySQL 8 database server reduces exposure to both known vulnerabilities and configuration drift.
SHOW GLOBAL VARIABLES LIKE 'binlog_expire_logs_seconds'; -- Recommended: 604800 (7 days) or per policy
# my.cnf [mysqld]: binlog_expire_logs_seconds=604800
7 — Authentication
▶7.1 Password Policies
▶This setting controls whether Password Complexity Policy is enabled on the MySQL 8 database server. Enabling this feature strengthens the security posture by enforcing the recommended configuration via my.cnf, mysqld configuration, or SQL commands.
Without Password Complexity Policy enabled, the MySQL 8 database server may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.
SHOW VARIABLES LIKE 'validate_password%'; -- validate_password.policy should be MEDIUM or STRONG
INSTALL COMPONENT 'file://component_validate_password'; SET GLOBAL validate_password.policy = STRONG; SET GLOBAL validate_password.length = 14;
This recommendation configures the expiration for Password on the MySQL 8 database server. Appropriate expiration values limit the window of opportunity for attacks and ensure resources are released in a timely manner.
Failure to password Expiration Is Set may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
SHOW GLOBAL VARIABLES LIKE 'default_password_lifetime'; -- Should be > 0 (e.g., 90 = 90 days)
SET GLOBAL default_password_lifetime = 90;
This setting ensures that Password Reuse is restricted on the MySQL 8 database server. Restricting this capability limits potential abuse and enforces the principle of least privilege across the environment.
Unrestricted Password Reuse could allow unauthorized users or processes to perform actions beyond their intended scope. Applying least-privilege principles to the MySQL 8 database server is essential for defense in depth.
SHOW GLOBAL VARIABLES LIKE 'password_history'; SHOW GLOBAL VARIABLES LIKE 'password_reuse_interval';
SET GLOBAL password_history = 5; SET GLOBAL password_reuse_interval = 365;
7.2 Plugin & TLS Authentication
▶This recommendation verifies that 'default_authentication_plugin' Uses Strong Auth on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to 'default_authentication_plugin' Uses Strong Auth may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
SHOW GLOBAL VARIABLES LIKE 'default_authentication_plugin'; -- Should be caching_sha2_password (default in 8.0)
# my.cnf [mysqld]: default_authentication_plugin=caching_sha2_password
This setting controls whether require_secure_transport is enabled on the MySQL 8 database server. Enabling this feature strengthens the security posture by enforcing the recommended configuration via my.cnf, mysqld configuration, or SQL commands.
Without require_secure_transport enabled, the MySQL 8 database server may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.
SHOW GLOBAL VARIABLES LIKE 'require_secure_transport'; -- Should be ON
SET GLOBAL require_secure_transport = ON; # And in my.cnf [mysqld]: require_secure_transport=ON
This recommendation verifies that TLS Version Is 1.2 or Higher on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to tLS Version Is 1.2 or Higher may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
SHOW GLOBAL VARIABLES LIKE 'tls_version'; -- Should be TLSv1.2,TLSv1.3
# my.cnf [mysqld]: tls_version=TLSv1.2,TLSv1.3
8 — Replication
▶8.1 Replication Security
▶This setting ensures that Replication uses encryption on the MySQL 8 database server. Encrypting data in transit and at rest protects sensitive information from interception and unauthorized disclosure.
Without encryption, Replication may transmit or store sensitive information in cleartext, exposing it to interception, eavesdropping, or tampering. Encryption is a critical control for data confidentiality and integrity.
SELECT ssl_allowed FROM mysql.slave_master_info; -- Should be 'Yes' if replication is configured
CHANGE REPLICATION SOURCE TO SOURCE_SSL=1, SOURCE_SSL_CA='/etc/mysql/certs/ca.pem', SOURCE_SSL_CERT='/etc/mysql/certs/client.pem', SOURCE_SSL_KEY='/etc/mysql/certs/client-key.pem';
This recommendation verifies that Replication User Has Minimal Privileges on the MySQL 8 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to replication User Has Minimal Privileges may leave the MySQL 8 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
SHOW GRANTS FOR 'repl_user'@'%'; -- Should only have REPLICATION SLAVE
CREATE USER 'repl_user'@'replica_host' IDENTIFIED BY '<strong_password>'; GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'replica_host';