Tag: mysql

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 =Ramesh.Nagappan@mysqltest.com’  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 =Ramesh.Nagappan@mysqltest.com’  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’@'east.sun.com’;

 

 

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:

bind-address=Host-IP-address

 

 

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 :-)

Onlinerel Facebook Twitter Myspace Friendfeed Technorati del.icio.us Digg Google Yahoo Buzz StumbleUpon

Web 2.0 applications are proliferating and it has become widely popular for delivering dynamic user-generated content, information collaboration, data mashups, social networking and Web services. Building security for Web 2.0 applications pose several daunting challenges to Web 2.0 developers as these applications are publicly accessible and it blindly opens door to several intentional/unintentional abuses and malicious practices including data interception and manipulation by cyber-criminals.  Unfortunately, Web 2.0 has no silver bullet or one-size fits all security solution ! Interestingly, the most common Web 2.0 security threats pertain to the inherent flaws with the application design, deployment architecture and its failure to proactively identify the potential application-level risks  and mitigate them with appropriate countermeasures.

 

Lately Web 2.0 application databases have become an easier target for cyber criminals – as it is transparent to user with rich-client applications and draws close proximity to the network perimeter ignoring the traditional logical-tiers of insulation considered with multi-tier architectures (such as Java EE). If we explore the existing Web 2.0 attack patterns and attempt to identify the potential security threats and exploits of Web 2.0 databases, we will find the most common vulnerabilities pertain to the following issues:

·         Eavesdropping database connections

·         Un-trusted application clients

·         Insufficient authentication controls

·         Insecure database access execution privileges

·         Unauthorized disclosure of user account credentials

·         Unauthorized access to application data tables

·         SQL injection or Arbitrary code execution

·         Lack of auditing controls

 

Thus it becomes extremely critical to proactively address the known database security issues by deploying appropriate countermeasures and ensuring confidentiality and integrity of the database including user accounts and stored data.

MySQL is the most popular open-source database and widely popular in Web 2.0 application environments.  MySQL is certainly not my forte! Recently, I had my first experiences with MySQL on couple of projects so I ended up digging deeper into MySQL security and churned up  the features for use in Web 2.0 applications.  Here is my first installment of my hitchhiker’s view on MySQL security and its relevance to Web 2.0 applications.

 

Securing MySQL database connections

 

Enforcing confidentiality and integrity of database communications is critical for thwarting eavesdropping and untrusted client connections.  Enabling MySQL connections with SSL/TLS protocol guarantees transport-layer security and assures that the database communciation is not accessible for unauthorized access and the data exchanged is not modified or altered during transit.

 

To secure communication between the client and the database server,  MySQL supports the use of SSL for ensuring transport-level security using encrypted communication.  Since MySQL 5.0.x, MySQL bundles yaSSL  (compatible with OpenSSL ) to support SSL and related cryptographic requirements.

 

Configuring MySQL with SSL/TLS communication

 

If you are using binary versions of MySQL to verify the existence of yaSSL support, login to the mysql client and try the following:

 

mysql> SHOW VARIABLES LIKE ‘have_ssl’;

+—————+——-+

| Variable_name | Value  |

+—————+——-+

| have_ssl      | YES   |

+—————+——-+

 

 

Incase of using MySQL source distribution and if you want to choose OpenSSL  (I strongly recommend OpenSSL as it is FIPS-140 certified) as your SSL provider, you may choose to recompile your MySQL server using  –with-openssl   as configure switches.

 

# ./configure –with-openssl

 

To verify the configuration with OpenSSL

 

mysql> SHOW VARIABLES LIKE ‘have_openssl’;

+—————+——-+

| Variable_name | Value |

+—————+——-+

| have_openssl  | YES   |

+—————+——-+

 

To establish an SSL communication, you must obtain the SSL certificates from a certificate authority (CA) (recommended) or alternatively you would able generate the certificates using  Solaris Key Management Framework (pktool utility) or OpenSSL (refer my earlier post on OpenSSL as CA/SSL Test Kit: Cheat Sheet) .  To enable SSL, MySQL requires the following three certificate files for both server and client (if required):

 

a)      CA certificate

b)      Server certificate

c)      Client certificate

 

You may append the location of these certificate files in the [mysqld] and [client] section of the MySQL server configuration file  my.cnf.  For example:

 

[client]

ssl-ca=/client-certs/cacert.pem

ssl-cert=/client-certs/my-new-client-cert.pem

ssl-key=/client-certs/my-new-client-key.pem

     [mysqld]

ssl-ca=/certs/cacert.pem

ssl-cert=/certs/my-new-server-cert.pem

ssl-key=/certs/my-new-server-key.pem

    

 

Alternatively, you can specify each certificate as a command-line argument to mysqld (server) and mysql (client) environments. 

 

To start the MySQL server daemon with the SSL configuration:

 

mysqld

        –ssl-ca=cacert.pem

              –ssl-cert=my-new-server-cert.pem

                    -ssl-key=my-new-server-key.pem

 

To start the MySQL client to use SSL, assuming the connecting user has no client certificate authentication requirements:

 

mysql –ssl-ca=cacert.pem

 

To start the MySQL client, assuming the connecting user is required to provide a client certificate for SSL authentication:

 

mysql

      –ssl-ca=cacert.pem

          –ssl-cert=my-new-client-cert.pem

                    -ssl-key=my-new-client-key.pem

 

 

To verify configuration and to ensure that the MySQL server uses SSL connection, the status can be checked from the MySQL client using ssl_cipher status variable.

 

mysql> SHOW STATUS LIKE ‘ssl_cipher’;

+—————+——————–+

| Variable_name | Value              |

+—————+——————–+

| Ssl_cipher    | DHE-RSA-AES256-SHA |

+—————+——————–+

 

Test-driving MySQL SSL connections using JDBC

 To test-drive SSL communication using JDBC, MySQL Connector/J  (MySQL JDBC driver) supports using SSL communication as long as the MySQL database server and Java client is configured with SSL certificates. To enable JDBC communication with SSL, it requires setting JDBC property requireSSL=true and useSSL=true.  In case, if you want to validate the Server certificate you may choose to use verifyServerCertificate=true.

 

Here is the example code, I tried out :

 

import java.sql.*;

public class TestJDBCoverSSL    {

public static void main(String args[])   {

      Connection mySQLconnection = null;

          try {

                //Register the JDBC driver for MySQL.
                 Class.forName(“com.mysql.jdbc.Driver”);

                 String url =  “jdbc:mysql://localhost:3306/mysql?&verifyServerCertificate=false&useSSL=true&requireSSL=true”;
                 mySQLconnection =  DriverManager.getConnection(url,  “jdbcuser”, “password”);

                 //Print URL and connection information
                  System.out.println(“URL: ” + url);
                  System.out.println(“Connection: ” + mySQLconnection); 
  
                 // Close the connection
                    mySQLconnection.close();

             }    catch(Exception ex)  {
                     ex.printStackTrace();
                  }
                }
     }

More importantly, You need to import the SSL certificates in the Java keystore and then provide the Java keystore location properties where the SSL certificates are stored. You may provide these values as -D Java runtime options on the command line as follows:

-Djavax.net.ssl.keyStore=path_to_Java_keystore_file
-Djavax.net.ssl.keyStorePassword=JavaKeyStore_password
-Djavax.net.ssl.trustStore=path_to_Java_truststore_file
-Djavax.net.ssl.trustStorePassword=JavaTruststore_password

Alternatively, you may incorporate the Java keystore and truststore properties in the JDBC application:

System.setProperty("javax.net.ssl.keyStore","path_to_Java_keystore_file");
System.setProperty("javax.net.ssl.keyStorePassword","JavaKeyStore_password");
System.setProperty("javax.net.ssl.trustStore","path_to_Java_truststore_file");
System.setProperty("javax.net.ssl.trustStorePassword","JavaTruststore_password");

To summarize, enabling SSL/TLS based MySQL connections ensure trusted communication between MySQL clients and the database server. It helps thwarting attacks related to eavesdropping MySQL communications, Man-in-the-Middle (MITM), Forged requests and so forth.  In my next post, I will discuss how to secure user accounts and enable stronger authentication controls in MySQL.

Onlinerel Facebook Twitter Myspace Friendfeed Technorati del.icio.us Digg Google Yahoo Buzz StumbleUpon

Our blog is back ….in action !

Finally, I had some time to play with WordPress 2.6.5…and did have success with importing those old stuff to new Sun MySQL database and the themes/customizations (the PHP scripts were too old so i ended up doing wild guess then hack)….to make it run on WordPress 2.6.5 -  it works ! Editing those messed up PHPs was an interesting experience. Still I have so much old stuff…am trying my best to migrate in to this new site soon. If it did’nt work, I will blame it on those RSS or whatever standards that supposed to take care of these issues.

Last ditch efforts did’nt help…sorry to note all the comments you folks posted were lost !!

The good news is I am dumping my blogger.com account.

Onlinerel Facebook Twitter Myspace Friendfeed Technorati del.icio.us Digg Google Yahoo Buzz StumbleUpon

I always had a love and hate interest with using OpenSSL ! But I should agree that it did help me many times…whenever I wanted to quickly test-drive my craziest ideas with PKI certificates. Couple of things I like about OpenSSL is its tools/utilities for testing as equivalent to a commerecial-grade CA and its FIPS-140 compliance. Also, I always get the required help on Web, right from the details of how-to install, configure…and all the operations. Here is my attempt to share a quick recipe on using OpenSSL commands.. particularly for those looking for help on test-driving SSL certificates using OpenSSL.

 

(A) Creating RSA Certificates

# openssl  genrsa   2048   >   myRSA-key.pem

 

This command creates a 2048-bit key pair and stores it in myRSA-key.pem. The default key size is 512 bits. In case if you want to password protect the RSA private key, use the following command:

 

# openssl genrsa 2048 -aes256 -out myRSA-key.pem

 

When you run the above command, OpenSSL prompts you for a passphrase for encrypting the key file using an algorithm – ex. AES (aes128, aes192 aes256), DES/3DES (des, des3).

 

(B) Creating a SSL Server Certificate Signing Request (CSR)

Important Note: This process requires signing by a valid Certificate Authority (CA)

 

For a commercial deployments, you need to obtain the SSL certificates and associated root CA certificates from a CA (ex. Cybertrust, Entrust, Verisign) . As a first step, you need to create a CSR for requesting the CA to sign (trust) your certificates. The following is the command for creating a CSR.

 

# openssl req -new rsa:1024 -node -out myCertReq.pem -keyout myPrivCertkey.pem -subj /C=US/ST=MA/L=Burlington/CN=myHost.domain.com/emailAddress=nramesh@sun.com

 

The generated certificate request (myCertReq.pem) must be signed by a CA otherwise it will not be a valid certificate. The key algorithm is RSA and size 1024 bits, the certificate will be valid for 365 days, and with -nodes option the key will be unencrypted. The -subj allows setting the Subject DN value that identifies the hostname “CN” must be fully qualified name that you’ll be using to access your SSL site.

 

Save the private key file (myPrivCertKey.pem) as you need the key in order to use the Server certificate from the CA. Just for the reason not to send the private key information to CA. Send the certificate request (myCertReq.pem) to the CA via email or using their web site. After signing process, The CA will return you the signed certificate and also root CA certificates.

 

(C) Creating the OpenSSL CA certificate

 

For Intranet or testing purpose, you may want to test with your own CA and it can be done with OpenSSL. Similar to the process (A) , you need to create a private CA key (myCA.key) and then a private CA X.509 certificate (myCACert.pem).

 

# openssl genrsa 2048 -aes256 -out myCA.key

# openssl req -new -x509 -days 3650 -key myCACert.key -out myCACert.pem

 

(D) Creating a Self-signed certificate (For SSL)

For your testing purposes, you may want to SSL test your applications with self-signed certificates and with your own CA. To create a self-signed certiicate:

 

# openssl req -nodes -x509 -newkey rsa:1024 -out mySelfSignedCert.pem -keyout myPrivServerKey.pem -days 365 -set_serial 01-subj “/C=US/ST=MA/L=Burlington/CN=myHost.domain.com/emailAddress=nramesh@sun.com

 

-x509 identifies it as a self-signed certificate and -set_serial sets the serial number for the server certificate. You may want to remove the password from the private key (so that the SSL server will not prompt you for password). Here is the command:

 

# openssl rsa -in myPrivServer.key -out myPrivServer.key.insecure

 

In some cases, you may want to create a single file that contains both private key and the self-signed certificate:

 

# openssl req -x509 -nodes -days 365 -newkey rsa:1024 -subj”/C=US/ST=MA/L=Burlington/CN=myHost.domain.com/emailAddress=nramesh@sun.com -keyout myServerCert.pem -out myServerCert.pem

 

To create a SSL certificate signed by your own Certification Authority (CA).

 

# openssl ca -cert myCACert.pem -in myCertReq.pem -out myServerCert.pem

 

Where myCACert.pem is the CA certificate, we discussed in (C).

 

(E) Testing the Certificate with OpenSSL

OpenSSL provides an s_server command that provides a SSL/TLS server implementation to test/verify support SSL/TLS based connections. By default, the s_server listens on port 4433. You should able to test your certificate by running the following command:

 

# openssl s_server -cert myServerCert.pem -www

 

The above command should launch an OpenSSL based SSL server using your certificates. To verify SSL connection with your certificates, try accessing https://localhost:4443/ from your browser. You must be seeing a simple web page listing the connection details and all the supported ciphers.

 

(F) Converting certificates from PEM to PKCS#12 formats

PKCS12 is an RSA standard for creating “Personal Information Exchange Syntax Standard” based certificates commonly used for email signatures (ex. pfx or p12). A PKCS#12 file combines all-in-one file including public key, private key, and the root CA certificate. With OpenSSL, you would able to convert a PEM file to PKCS#12 format file, you would use the following command (all in one line ignore \ ):

 

# openssl pkcs12 -export -in myServerCert.pem -inkey myPrivateServerKey.pem -certfile myCACert.pem -name “[friendly name - Ramesh Nagappan]” -out myServerPKCS12Cert.pfx

 

(G) SSL Certificate Pre-requisites for Apache and MySQL

If you are thinking about configuring SSL for your Apache Web Server or MySQL database connections, you would need the following:

1) Create the CA (private key and public cert) certificates.

2) Create your SSL server key.

3) Create your SSL server certificate.

Make sure your Common Name (CN( identifies “full-qualified domain name (FQDN)” of your server. Follow the directions for configuring SSL using Apache and MySQL documentation.

Enjoy. Let me know, if you had any suggestions.

Onlinerel Facebook Twitter Myspace Friendfeed Technorati del.icio.us Digg Google Yahoo Buzz StumbleUpon

Important Disclaimer:The information presented in this weblog is provided “AS IS” with no warranties, and confers no rights. It solely represents our opinions. This weblog does not represent the thoughts, intentions, plans or strategies of our employers.
.