WL#12086: Cryptographically signed SET statements
Affects: Server-8.0 — Status: Complete — Priority: Medium
Extra authentication is needed to avoid privilege escalation via SET PERSIST ONLY setting sensitive data like for example secure-file-priv. This is to avoid the risk of somebody impersonating the DBA sql account. Currently the MySQL server doesn't allow these to be set so people are forced into authenticating to the host OS and editing a text file. But this is impractical for cases where there's no shell access. Hence we need to replace this extra authentication the OS remote login provides with something else. This worklog proposes that we replace the shell authentication with PKI signatures on the SQL session. We will add a new *read only* command line/config file option to the server: --persist_only_admin_x509_subject. Default value is empty, takes a X509 distinguished name. We will allow SET PERSIST [ONLY] setting the variables listed on this page (https://dev.mysql.com/doc/refman/8.0/en/nonpersistent-system-variables.html) when the session it's issued on has: * enough permissions to execute the SET PERSIST command * a client SSL certificate whose signature checks out against the server's CA list and it has a distinguished name matching the one supplied in --persist_only_admin_x509_subject.
FR1: A new global system variable will be added called "persist_only_admin_x509_subject". The variable will: FR1.1: be read only (not settable via SET GLOBAL) FR1.2: take its values in the system charset FR1.3: be available as a command line parameter FR1.4: not be settable via SET PERSIST ONLY. FR1.5: be settable via the my.cnf config file FR1.6: have empty ("") as a default value FR2: persist_only_admin_x509_subject, if specified and not empty, will allow executing SET PERSIST [ONLY] on the variables listed in the HLS, that are currently not settable via SET PERSIST [ONLY] *AND* are settable via the server command line/SET statements. FR3: if persist_only_admin_x509_subject is not specified or is empty, the variables listed in the HLS will keep being unsettable via SET PERSIST [ONLY] FR4: if persist_only_admin_x509_subject is not specified the default for it will be such that it will ensure full backward compatibility FR5: persisted_globals_load should not be settable via SET PERSIST_ONLY even when persist_only_admin_x509_subject is specified and it matches the X.509 subject of the client's certificate for the current session. This is because persisted_globals_load is checked before the persisted variables file is processed.
The variables affected are listed on https://dev.mysql.com/doc/refman/8.0/en/nonpersistent-system-variables.html. Not all variables on that list are affected, since some are not specifiable at the command line too. Here's a list of all affected variables: * audit_log_file * audit_log_format * auto_generate_certs * basedir * bind_address * caching_sha2_password_auto_generate_rsa_keys * caching_sha2_password_private_key_path * caching_sha2_password_public_key_path * character_sets_dir * daemon_memcached_engine_lib_name * daemon_memcached_engine_lib_path * daemon_memcached_option * datadir * default_authentication_plugin * ft_stopword_file * init_file * innodb_buffer_pool_load_at_startup * innodb_data_file_path * innodb_data_home_dir * innodb_dedicated_server * innodb_directories * innodb_force_load_corrupted * innodb_log_group_home_dir * innodb_page_size * innodb_read_only * innodb_temp_data_file_path * innodb_temp_tablespaces_dir * innodb_undo_directory * innodb_undo_tablespaces * keyring_encrypted_file_data * keyring_encrypted_file_password * lc_messages_dir * log_error * mecab_rc_file * named_pipe * pid_file * plugin_dir * port * relay_log * relay_log_info_file * secure_file_priv * sha256_password_auto_generate_rsa_keys * sha256_password_private_key_path * sha256_password_public_key_path * shared_memory * shared_memory_base_name * skip_networking * slave_load_tmpdir * socket * ssl_ca * ssl_capath * ssl_cert * ssl_crl * ssl_crlpath * ssl_key * tmpdir * version_tokens_session_number In general this applies to all variables defined to have the sys_var::NOTPERSIST flag on and to all plugin/component variables that have the PLUGIN_VAR_NOPERSIST flag on and that also are settable at the command line. Why we need the extra variable ? ================================ We already can check X509 SUBJECT for user accounts. Why not use that instead of --persist_only_admin_x509_subject ? Mostly because in this case if you happen to have CREATE USER you could start setting read only persisted sensitive variables in seconds: you just create a user account with a subject name of a certificate you have and voila ! --persist_only_admin_x509_subject is still not settable via SET PERSIST[_ONLY]. Hence it still does require the extra authentication that an OS session entails.
We will amend the place where we check for the sys_var::NOTPERSIST flag with checks if the: 1. session uses SSL 2. the connecting client have supplied a certificate validated against the server's CAs 3. the Subject of that certificate matches the string specified. Note that exactly the same way to generate the name will be used as in the server status variables that show the subject. This will allow one to just check the subject in the status var and copy it into the new system var. And the format is the same as CREATE USER ... REQUIRE SUBJECT ... too. == log_bin_use_v1_row_events == This variable was the only non-persisted variable that wasn't read-only. Before WL#12086 the non-persist flag was just ignored for non-read-only variables. Now it's honored. Hence the behavior of this variable changes.
Copyright (c) 2000, 2019, Oracle Corporation and/or its affiliates. All rights reserved.