{"id":970,"date":"2009-03-29T10:30:11","date_gmt":"2009-03-29T15:30:11","guid":{"rendered":"http:\/\/www.coresecuritypatterns.com\/blogs\/?p=970"},"modified":"2020-08-08T04:03:11","modified_gmt":"2020-08-08T04:03:11","slug":"demystifying-mysql-security-for-web-20-part-2","status":"publish","type":"post","link":"https:\/\/websecuritypatterns.com\/blogs\/2009\/03\/29\/demystifying-mysql-security-for-web-20-part-2\/","title":{"rendered":"Demystifying MySQL Security for Web 2.0: Part 2"},"content":{"rendered":"<p>Access control exploits, user credential exposures and&nbsp;related <a href=\"http:\/\/www.websecuritypatterns.com\/blogs\/?p=833\" target=\"_blank\" rel=\"noopener noreferrer\">security compromises are becoming&nbsp;increasingly common in Web 2.0 world <\/a>!&nbsp;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&nbsp;and\/or impersonating another user through forged or guessed&nbsp;credentials.&nbsp; Any such access control failure leads to&nbsp;unauthorized access and disclosure of underlying application databases, user accounts and stored data.&nbsp;&nbsp;Most access control related vulnerabilities are due to the inherent application-specific&nbsp;weakness and&nbsp;failure to enforce authentication mechanisms, verify authentication credentials, lack of policy enforcement prior to granting or denying access to the underlying database.<\/p>\n<p>This is my second installment of work exploring MySQL security features to enforce stronger authentication controls and&nbsp;defend against u<span>nauthorized disclosure of user account credentials and application-related <\/span><span>database tables<\/span>.&nbsp;&nbsp;In simpler terms, I will be uncovering a set of MySQL security mechanisms intended for the following:<\/p>\n<ol>\n<li>X.509 certificate-based&nbsp; MySQL authentication<\/li>\n<li>Enabling host verification to cease access from untrusted hosts<\/li>\n<li>Restricting remote access to MySQL database<\/li>\n<li>Disable unauthorized access to local files<\/li>\n<li>Securing MySQL user accounts, passwords and access privileges<\/li>\n<li>Data encryption using AES<\/li>\n<\/ol>\n<h2>X.509 Certificate based MySQL authentication<\/h2>\n<p>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,&nbsp; the MySQL&nbsp; <strong><em>GRANT<\/em><\/strong> statement allows to limit user access to request X.509 certificate by specifying a set of options.&nbsp; To connect the client must specify the certificates using&nbsp;<em><span><span><span>&nbsp;<\/span>\u2013ssl-ca&nbsp; (CA certificate),&nbsp;<\/span><\/span><\/em><em><span><span><span>&nbsp;<\/span>\u2013ssl-cert (Client certficate) and <\/span><\/span><\/em><em><span><span>-ssl-key (Client key).<\/span><\/span><\/em><\/p>\n<p><em><\/em>&nbsp;<\/p>\n<p>a)&nbsp; The <strong><em>REQUIRE X509<\/em><\/strong>&nbsp;&nbsp;option allows user to provide a valid&nbsp;X.509 certificate, where&nbsp;the signing authority should be verifiable using the CA certificate.&nbsp;<\/p>\n<p><span><span><em>mysql&gt;&nbsp; GRANT&nbsp; ALL PRIVILEGES&nbsp; ON&nbsp; test.*&nbsp; TO &#8216;ramesh&#8217;@&#8217;localhost&#8217;&nbsp; IDENTIFIED&nbsp; BY&nbsp; &#8216;password&#8217;&nbsp; REQUIRE&nbsp; X509;<\/em><\/span><\/span><\/p>\n<p><span><span><em><\/em><\/span><\/span>&nbsp;<\/p>\n<p><span><span>b) The <strong><em>REQUIRE SUBJECT&nbsp; ..&nbsp; AND ISSUER<\/em><\/strong>&nbsp; .. option allows the user to provide a valid X.509 certificate containing the subject information of the user and the certificate&nbsp;issued by a specific CA&nbsp; as defined in the GRANT statement. The user&#8217;s certificate and the specified SUBJECT and ISSUER attributes are verified against the information provided with GRANT statement.<\/span><\/span><\/p>\n<p><span><span><span><span><em>mysql&gt;&nbsp; GRANT&nbsp; ALL PRIVILEGES&nbsp; ON&nbsp; test.*&nbsp; TO &#8216;ramesh&#8217;@&#8217;localhost&#8217;&nbsp; IDENTIFIED&nbsp; BY&nbsp; &#8216;password&#8217;&nbsp; REQUIRE SUBJECT&nbsp; &#8216;\/C=US\/ST=Massachusetts\/L=Burlington\/O=Sun<\/em><\/span><\/span><\/span><\/span><span><span><span><span><em>&nbsp;M<\/em><\/span><\/span><\/span><\/span><span><span><span><span><em>icrosystems\/CN=Ramesh Nagappan\/Email =Ramesh.Nagappan@mysqltest.com&#8217;&nbsp; AND ISSUER &#8216;\/C=US\/ST=Massachusetts\/L=Burlington\/O=Sun Microsystems\/CN=SunTest CA&#8217;;<\/em><\/span><\/span><\/span><\/span><\/p>\n<p><span><span><span><span><em><\/em><\/span><\/span><\/span><\/span>&nbsp;<\/p>\n<p><span><span><span><span>c) In addition to SUBJECT and ISSUER, the user&#8217;s certificate can be identified with the specific&nbsp;CIPHER .&nbsp; The <strong><em>REQUIRE CIPHER<\/em><\/strong> option allows to specify the required algorithm to grant access to the database.<\/span><\/span><\/span><\/span><\/p>\n<p><span><span><span><span><em>mysql&gt;&nbsp; GRANT&nbsp; ALL PRIVILEGES&nbsp; ON&nbsp; test.*&nbsp; TO &#8216;ramesh&#8217;@&#8217;localhost&#8217;&nbsp; IDENTIFIED&nbsp; BY&nbsp; &#8216;password&#8217;&nbsp; REQUIRE SUBJECT&nbsp; &#8216;\/C=US\/ST=Massachusetts\/L=Burlington\/O=Sun Microsystems\/CN=Ramesh Nagappan\/Email =Ramesh.Nagappan@mysqltest.com&#8217;&nbsp; AND ISSUER &#8216;\/C=US\/ST=Massachusetts\/L=Burlington\/O=Sun Microsystems\/CN=SunTest CA&#8217;&nbsp;&nbsp; AND&nbsp; CIPHER &#8221;<\/em>DHE-RSA-AES256-SHA&#8217;;<\/span><\/span><\/span><\/span><\/p>\n<p><span><span><span><span>d)&nbsp; To allow access to user with SSL-enabled connection.<\/span><\/span><\/span><\/span><\/p>\n<p><span><span><span><span><em>GRANT&nbsp; ALL PRIVILEGES&nbsp; ON&nbsp; test.*&nbsp; TO &#8216;ramesh&#8217;@&#8217;localhost&#8217;&nbsp; IDENTIFIED&nbsp; BY&nbsp; &#8216;password&#8217;&nbsp; REQUIRE SSL;<\/em><\/span><\/span><\/span><\/span><\/p>\n<p><span><span><span><span><em><\/em><\/span><\/span><\/span><\/span>&nbsp;<\/p>\n<h2><span>Trusted&nbsp;Host Verification<\/span><\/h2>\n<p><span>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.&nbsp; To enable host verification, the MySQL&nbsp; CREATE USER and GRANT statements allows to specify the user assigned with a target hostname.<\/span><\/p>\n<p><span>a)&nbsp; 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.<\/span><\/p>\n<p><span><span><span><em>mysql&gt;&nbsp;&nbsp; CREATE&nbsp; USER&nbsp; &#8216;ramesh&#8217;@&#8217;localhost&#8217;&nbsp; IDENTIFIED BY &#8216;some_password&#8217;;<\/em><\/span><\/span><\/span><\/p>\n<p>&nbsp;<span style=\"small;\"><span style=\"Times New Roman;\">The above statement creates an user &#8216;ramesh&#8217; assigned to hostname &#8216;localhost&#8217;.&nbsp; This means &#8216;ramesh&#8217;@&#8217;localhost&#8217; account can be used only when connecting from the localhost.<span style=\"yes\">&nbsp; <\/span><\/span><\/span><\/p>\n<p><span>b)&nbsp; The&nbsp;GRANT statement allows to define user privileges on a database table only when the user is accessed from a specified host.&nbsp; If the user connected from a different host the access will be denied.<\/span><\/p>\n<p><span><span><span><span><em>mysql&gt;&nbsp;&nbsp; GRANT SELECT,INSERT,UPDATE&nbsp; ON&nbsp; test.*&nbsp; TO&nbsp; <a href=\"mailto:'ramesh'@'east.sun.com'\">&#8216;ramesh&#8217;@&#8217;east.sun.com&#8217;<\/a>;<\/em><\/span><\/span><\/span><\/span><\/p>\n<p><span><span><span><span><em><\/em><\/span><\/span><\/span><\/span>&nbsp;<\/p>\n<p><span><span><span><span><em><\/em><\/span><\/span><\/span><\/span>&nbsp;<\/p>\n<h2><span><span><span><span>Disabling Remote Access from Network<\/span><\/span><\/span><\/span>&nbsp;<\/h2>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\"><span style=\"small;\"><span style=\"Times New Roman;\">If the MySQL database is accessed&nbsp;locally by the coexisting appplications, remote access from the network can be disabled.<span style=\"yes\">&nbsp; To disable remote access via network,&nbsp; you may add <strong><em>skip-networking<\/em><\/strong> under the <strong><em>[mysqld]<\/em><\/strong> section of <strong><em>my.cnf<\/em><\/strong> or start <strong><em>mysqld <\/em><\/strong>using the <strong><em>&#8211;skip-networking<\/em><\/strong> option.&nbsp; To enable MySQL listen to a specific host IP address, you need to set the following attribute in the <strong><em>[mysqld]<\/em><\/strong> section of <strong><em>my.cnf<\/em><\/strong>&nbsp; as follows:<\/span><\/span><\/span><\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\"><span style=\"small;\"><span style=\"Times New Roman;\"><span style=\"yes\"><em>bind-address=Host-IP-address<\/em><\/span><\/span><\/span><\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\">&nbsp;<\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\">&nbsp;<\/p>\n<h2 class=\"MsoNormal\"><span style=\"small;\"><span style=\"Times New Roman;\"><span style=\"yes\">Disabling unauthorized access to Local files<\/span><\/span><\/span><\/h2>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\"><span style=\"small;\"><span style=\"Times New Roman;\"><span style=\"yes\">To disable unauthorized access or reading of local files, particularly to prevent applications access local files using SQL injection attacks &#8211; you may add the <strong><em>set-variable=local-infile=0<\/em><\/strong> under the <strong><em>[mysqld]<\/em><\/strong> section of <strong><em>my.cnf<\/em><\/strong> . <\/span><\/span><\/span><\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\"><span style=\"small;\"><span style=\"Times New Roman;\"><span style=\"yes\">Also, run MySQL as run as an user with minimized privileges&nbsp;so that&nbsp;any potential&nbsp;attacks&nbsp;does not result in damages to the operating system and other processes.&nbsp; <\/span><\/span><\/span><\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\">&nbsp;<\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\">&nbsp;<\/p>\n<h2 class=\"MsoNormal\"><span style=\"small;\"><span style=\"Times New Roman;\"><span style=\"yes\">Securing MySQL User Accounts, Passwords and Privileges<\/span><\/span><\/span><\/h2>\n<h2 class=\"MsoNormal\">&nbsp;<\/h2>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\">a) To prevent unauthorized and anonymous access to the server,&nbsp; first remove the test database and all user accounts (with the exception of root account).<\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\"><em>mysql&gt; drop database test;<br \/>\nmysql&gt; use mysql;<br \/>\nmysql&gt; delete from db;<br \/>\nmysql&gt; delete from user where not (host=&#8221;localhost&#8221; and user=&#8221;root&#8221;);<br \/>\nmysql&gt; flush privileges;<\/em><\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\"><em>mysql&gt; quit;<\/em><\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\"><em><\/em>&nbsp;<\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\">b)&nbsp; Change the MySQL <em><strong>root<\/strong><\/em> password and make sure the password is done via mysql&gt; command line.&nbsp; It is a bad practice, to change passwords via <strong><em>mysqladmin &#8211; u root<\/em><\/strong>&nbsp;password as the password can be accessed via &#8220;ps -aef&#8221;&nbsp; (Solaris) &#8220;ps -aux&#8221; (Linux) command or by reviewing the Unix command history files.&nbsp;<\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\">&nbsp;<\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\">c)&nbsp; Passwords are&nbsp;usually visible as plain text in SQL statements especially while executing&nbsp;CREATE USER, GRANT and SET PASSWORD statements.&nbsp;If the MySQL server is logging the SQL events and action to tables, then make sure those tables are protected from unauthorized users.<\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\">&nbsp;<\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\">d) Change the default administrator account name from &#8216;root&#8217; to a harder to guess &#8216;username&#8217;.&nbsp; This would help defend against hackers performing dictionary\/brute-force guessing attacks for administrator credentials.<\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\"><em>mysql&gt;&nbsp; update user set user=&#8221;mysqlgeek&#8217; where user=&#8221;root&#8221;;<\/em><br \/>\n<em>mysql&gt; flush privileges;<\/em><\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\"><em><\/em>&nbsp;<\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\">e) MySQL stores user accounts and its passwords in <strong><em>mysql.user<\/em><\/strong> table. Disable access to this table for any non-administrator users.<\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\">&nbsp;<\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\">f)&nbsp; Enforce the &#8216;principle of least privileges&#8217; 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 <em><strong>define privileges as required at the Table and Column level<\/strong><\/em>.<\/p>\n<p class=\"MsoNormal\" style=\"0in 0in 0pt\"><em>&nbsp;&nbsp;&nbsp; grant &lt;privileges&gt; &lt;column&gt; on &lt;database&gt;.&lt;table&gt; to &lt;login-name&gt;@&lt;FQDN-or-IP&gt; identified by &lt;password&gt;;<\/em><\/p>\n<p><em><\/em>&nbsp;<\/p>\n<h2>Data Encryption using AES<\/h2>\n<p>MySQL supports data encryption functions by providing support for AES (Advanced Encryption Standard) and DES (Triple-DES) algorithms.&nbsp; 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 ( )&nbsp; to facilitate AES based encryption and decryption&nbsp; and DES_ENCRYPT( ) and DES_DECRYPT ( )&nbsp; to facilitate Triple-DES based encryption and decryption&nbsp; operations.<\/p>\n<p>For example:<\/p>\n<p><em>mysql&gt;&nbsp; insert into mytable (username, password)&nbsp; VALUES (&#8216;nramesh&#8217;,&nbsp; AES_ENCRYPT(&#8216;g01ns@n3&#8217;, &#8216;myaeskey&#8217;));<\/em><\/p>\n<p><em>mysql&gt;&nbsp;&nbsp;select username, AES_DECRYPT(password, &#8216;myaeskey&#8217;) from mytable;<\/em><\/p>\n<p>+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+<br \/>\n|&nbsp;username | des_decrypt(password, &#8216;myaesencryptionkey&#8217;)&nbsp; |<br \/>\n+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+<br \/>\n| nramesh | g01ns@n3 |<br \/>\n|&nbsp;bobama |&nbsp;s@v3u5a |<br \/>\n+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+<\/p>\n<p>It is important to note, the encryption KEY must be provided by the application user to MySQL. It means that MySQL does&#8217;nt provide mechanisms for generating the keys. Also it is critical to store the key for supporting further decryption operations.<\/p>\n<p>That&#8217;s all folks. I will revisit again on my next MySQL security project &#8230;till then let me practice wearing an Oracle shirt \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Access control exploits, user credential exposures and&nbsp;related security compromises are becoming&nbsp;increasingly common in Web 2.0 world !&nbsp;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&nbsp;and\/or impersonating another user through forged or guessed&nbsp;credentials.&nbsp; Any such access control&#8230; <a href=\"https:\/\/websecuritypatterns.com\/blogs\/2009\/03\/29\/demystifying-mysql-security-for-web-20-part-2\/\">Read more &raquo;<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[17,20,6,9],"tags":[37,48,50,57,62,73],"class_list":["post-970","post","type-post","status-publish","format-standard","hentry","category-database-security","category-java-ee","category-main","category-security","tag-j2ee","tag-mysql","tag-openssl","tag-pki-main","tag-security","tag-web2-0"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/websecuritypatterns.com\/blogs\/wp-json\/wp\/v2\/posts\/970","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/websecuritypatterns.com\/blogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/websecuritypatterns.com\/blogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/websecuritypatterns.com\/blogs\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/websecuritypatterns.com\/blogs\/wp-json\/wp\/v2\/comments?post=970"}],"version-history":[{"count":1,"href":"https:\/\/websecuritypatterns.com\/blogs\/wp-json\/wp\/v2\/posts\/970\/revisions"}],"predecessor-version":[{"id":2833,"href":"https:\/\/websecuritypatterns.com\/blogs\/wp-json\/wp\/v2\/posts\/970\/revisions\/2833"}],"wp:attachment":[{"href":"https:\/\/websecuritypatterns.com\/blogs\/wp-json\/wp\/v2\/media?parent=970"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/websecuritypatterns.com\/blogs\/wp-json\/wp\/v2\/categories?post=970"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/websecuritypatterns.com\/blogs\/wp-json\/wp\/v2\/tags?post=970"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}