Demystifying MySQL Security for Web 2.0: Part 2

Access control exploits, user credential exposures and related security compromises are becoming increasingly common in Web 2.0 world ! Most of these issues pertain to broken or insufficient authentication controls and flawed credential management that allows attackers to compromise vulnerable applications by stealing or manipulating credentials such as passwords, keys, session cookies and/or impersonating another user through forged or guessed credentials.  Any such access control failure leads to unauthorized access and disclosure of underlying application databases, user accounts and stored data.  Most access control related vulnerabilities are due to the inherent application-specific weakness and failure to enforce authentication mechanisms, verify authentication credentials, lack of policy enforcement prior to granting or denying access to the underlying database.

This is my second installment of work exploring MySQL security features to enforce stronger authentication controls and defend against unauthorized disclosure of user account credentials and application-related database tables.  In simpler terms, I will be uncovering a set of MySQL security mechanisms intended for the following:

  1. X.509 certificate-based  MySQL authentication
  2. Enabling host verification to cease access from untrusted hosts
  3. Restricting remote access to MySQL database
  4. Disable unauthorized access to local files
  5. Securing MySQL user accounts, passwords and access privileges
  6. Data encryption using AES

X.509 Certificate based MySQL authentication

Enforcing X.509 v3 Certificate authentication allows clients to authenticate the MySQL database server using X.509 certificates and its attributes. To enable certificate based authentication,  the MySQL  GRANT statement allows to limit user access to request X.509 certificate by specifying a set of options.  To connect the client must specify the certificates using  –ssl-ca  (CA certificate),  –ssl-cert (Client certficate) and -ssl-key (Client key).


a)  The REQUIRE X509  option allows user to provide a valid X.509 certificate, where the signing authority should be verifiable using the CA certificate. 


mysql>  GRANT  ALL PRIVILEGES  ON  test.*  TO ‘ramesh’@’localhost’  IDENTIFIED  BY  ‘password’  REQUIRE  X509;


b) The REQUIRE SUBJECT  ..  AND ISSUER  .. option allows the user to provide a valid X.509 certificate containing the subject information of the user and the certificate issued by a specific CA  as defined in the GRANT statement. The user’s certificate and the specified SUBJECT and ISSUER attributes are verified against the information provided with GRANT statement.


mysql>  GRANT  ALL PRIVILEGES  ON  test.*  TO ‘ramesh’@’localhost’  IDENTIFIED  BY  ‘password’  REQUIRE SUBJECT  ‘/C=US/ST=Massachusetts/L=Burlington/O=Sun Microsystems/CN=Ramesh Nagappan/Email’  AND ISSUER ‘/C=US/ST=Massachusetts/L=Burlington/O=Sun Microsystems/CN=SunTest CA’;


c) In addition to SUBJECT and ISSUER, the user’s certificate can be identified with the specific CIPHER .  The REQUIRE CIPHER option allows to specify the required algorithm to grant access to the database.


mysql>  GRANT  ALL PRIVILEGES  ON  test.*  TO ‘ramesh’@’localhost’  IDENTIFIED  BY  ‘password’  REQUIRE SUBJECT  ‘/C=US/ST=Massachusetts/L=Burlington/O=Sun Microsystems/CN=Ramesh Nagappan/Email’  AND ISSUER ‘/C=US/ST=Massachusetts/L=Burlington/O=Sun Microsystems/CN=SunTest CA’   AND  CIPHER ”DHE-RSA-AES256-SHA’;


d)  To allow access to user with SSL-enabled connection.

GRANT  ALL PRIVILEGES  ON  test.*  TO ‘ramesh’@’localhost’  IDENTIFIED  BY  ‘password’  REQUIRE SSL;



Trusted Host Verification

Host identification helps to allow the user requests initiated from the specified host only. If the user and hostname doesnot match the specified host the server will deny access to the database.  To enable host verification, the MySQL  CREATE USER and GRANT statements allows to specify the user assigned with a target hostname.


a)  The CREATE USER allows to specify the user assigned to a specific hostname. The user will be allowed access only if the request orginated from the specified hostname.

mysql>   CREATE  USER  ‘ramesh’@’localhost’  IDENTIFIED BY ‘some_password’;

 The above statement creates an user ‘ramesh’ assigned to hostname ‘localhost’.  This means ‘ramesh’@’localhost’ account can be used only when connecting from the localhost. 


b)  The GRANT statement allows to define user privileges on a database table only when the user is accessed from a specified host.  If the user connected from a different host the access will be denied.

mysql>   GRANT SELECT,INSERT,UPDATE  ON  test.*  TO  ‘ramesh’@’’;



Disabling Remote Access from Network 


If the MySQL database is accessed locally by the coexisting appplications, remote access from the network can be disabled.  To disable remote access via network,  you may add skip-networking under the [mysqld] section of my.cnf or start mysqld using the –skip-networking option.  To enable MySQL listen to a specific host IP address, you need to set the following attribute in the [mysqld] section of my.cnf  as follows:




Disabling unauthorized access to Local files

To disable unauthorized access or reading of local files, particularly to prevent applications access local files using SQL injection attacks – you may add the set-variable=local-infile=0 under the [mysqld] section of my.cnf .

Also, run MySQL as run as an user with minimized privileges so that any potential attacks does not result in damages to the operating system and other processes. 



Securing MySQL User Accounts, Passwords and Privileges


a) To prevent unauthorized and anonymous access to the server,  first remove the test database and all user accounts (with the exception of root account).

mysql> drop database test;
mysql> use mysql;
mysql> delete from db;
mysql> delete from user where not (host=”localhost” and user=”root”);
mysql> flush privileges;

mysql> quit;


b)  Change the MySQL root password and make sure the password is done via mysql> command line.  It is a bad practice, to change passwords via mysqladmin – u root password as the password can be accessed via “ps -aef”  (Solaris) “ps -aux” (Linux) command or by reviewing the Unix command history files. 


c)  Passwords are usually visible as plain text in SQL statements especially while executing CREATE USER, GRANT and SET PASSWORD statements. If the MySQL server is logging the SQL events and action to tables, then make sure those tables are protected from unauthorized users.


d) Change the default administrator account name from ‘root’ to a harder to guess ‘username’.  This would help defend against hackers performing dictionary/brute-force guessing attacks for administrator credentials.

mysql>  update user set user=”mysqlgeek’ where user=”root”;
mysql> flush privileges;


e) MySQL stores user accounts and its passwords in mysql.user table. Disable access to this table for any non-administrator users.


f)  Enforce the ‘principle of least privileges’ by granting minimum privileges for performing the required actions especially for user accounts that connects to the MySQL database from external applications. Do not grant privileges at the database level, MySQL allows to define privileges as required at the Table and Column level.

    grant <privileges> <column> on <database>.<table> to <login-name>@<FQDN-or-IP> identified by <password>;


Data Encryption using AES

MySQL supports data encryption functions by providing support for AES (Advanced Encryption Standard) and DES (Triple-DES) algorithms.  It is important to note, the encryption function return binary strings as BLOBS, so you may need to store the encrypted data in columns of BLOB or VARBINARY data types. MySQL provides AES_ENCRYPT( ) and AES_DECRYPT ( )  to facilitate AES based encryption and decryption  and DES_ENCRYPT( ) and DES_DECRYPT ( )  to facilitate Triple-DES based encryption and decryption  operations.


For example:


mysql>  insert into mytable (username, password)  VALUES (‘nramesh’,  AES_ENCRYPT(‘g01ns@n3’, ‘myaeskey’));


mysql>  select username, AES_DECRYPT(password, ‘myaeskey’) from mytable;

| username | des_decrypt(password, ‘myaesencryptionkey’)  |
| nramesh | g01ns@n3 | 
| bobama | s@v3u5a |


It is important to note, the encryption KEY must be provided by the application user to MySQL. It means that MySQL does’nt provide mechanisms for generating the keys. Also it is critical to store the key for supporting further decryption operations.



That’s all folks. I will revisit again on my next MySQL security project …till then let me practice wearing an Oracle shirt 🙂

4 thoughts on “Demystifying MySQL Security for Web 2.0: Part 2

Leave a Reply

Your email address will not be published. Required fields are marked *