Showing posts with label mysql. Show all posts
Showing posts with label mysql. Show all posts

Tuesday, November 8, 2016

A nasty pair of MySQL exploits grant attackers system root from any database user

Four days ago I received an email from Dawid Golunski through the list illustrating one of the more brutal pair of security vulnerabilities I have seen recently. Here's how it works.
    The exploit uses a vulnerability within MariaDB, PerconaDB (and/or XtraDB Cluster) and MySQL to, first, gain access to the 'mysql' system user using any mysql user that has CREATE / INSERT / UPDATE permissions. The first part revolves around a race condition when sql generates temporary files as part of the `REPAIR table` command. Then using the mysql system user the second vulnerability grants the attacker root access to the server using a clever hack that takes advantage of mysql_safe's approach to writing to file based error logs. Below I've provided a list of vulnerable server versions. Just about any server using the more recent (unpatched) stable releases of MySQL or MariaDB through CentOS is vulnerable (Percona isn't part of the standard CentOS repositories), with a few of caveats.
    The first caveat is that an unpatched vulnerable server can prevent at least the 2nd exploit by disabling symlinks through /etc/my.cnf using skip-symbolic-links or symbolic-links=0
    The next caveat is that the 2nd exploit also depends on using file-based mysql logging. Using syslog will avoid trouble.
    The third caveat is that for the 1st exploit to work an attacker needs a mysql user and password.
    There is some good news here. The latest stable versions of MariaDB at least disable symbolic links in my.cnf by default (its been a while since I installed MySQL through the repo but I'm fairly sure its disabled here as well). And how would an attacker get a MySQL user anyway?
    Consider that because *any* MySQL user to be used, an un-patched shared server used by a hosting company would depend on the security competency of every one of that c customers to securely handle database authentication. Not only are there a variety of exploits available for obtaining a standard database user, but its depressingly common for web designers to place their connection strings with un-encrypted database username and password into world-readable files. There are a variety of feeds and sites that scan the internet for and compile such files.
    And even without the use of the 2nd exploit, an attacker can still do an enormous amount of damage without server root with only the mysql system user. The attacker will have full access to the MySQL system files. An attacker could easily delete an entire database instance, for example.
    Of course the best part is that this is a vulnerability in MySQL itself. Upgrading MySQL is the scariest, riskiest upgrade there is among standard repo software. A lot of admins compile it from source or install it from a direct RPM (in which cases symlinks are enabled by default). And applications are closely linked with the database version. Even successful upgrades can easily break applications that run on that database as calls used by the application become deprecated. Upgrading applications has substantial costs, whether you develop the application itself or license it. A patch was already in circulation before these exploits were posted, but for all of the reasons listed above, vulnerable databases will be active for years.

Here are the impacted DB versions:

 < 5.5.52
 < 10.1.18
        < 10.0.28

 <= 5.5.51
 <= 5.6.32
 <= 5.7.14

Percona Server
 < 5.5.51-38.2
 < 5.6.32-78-1
 < 5.7.14-8

Percona XtraDB Cluster
 < 5.6.32-25.17
 < 5.7.14-26.17
 < 5.5.41-37.0

Here the first two links below contain a comprehensive breakdown of both exploits with example scripts that you can run to test.

This link includes a video illustrating how a compromise takes place using the example scripts:

Sunday, October 26, 2014

Massive Critical Security Patch Released by Oracle Impacting Most Versions of MySQL

Oracle has released a Critical Security Patch for a long list of Oracle products. For MySQL specifically, the patch purports to resolve a multitude of vulnerabilities that allow remote execution without authentication, and impact nearly all versions of the database software.

Oracle provided the following Risk Matrix to their MySQL customers, which outlines the CVE numbers of stated vulnerabilities, the component used by the vulnerability and a number of other details.

I've included a copy of that Matrix for readers to review below.

As the reader can clearly see, the risk for unpatched MySQL users is huge. A total of 154 vulnerabilities are addressed with this update. Some of these vulnerabilities reach a forehead-slapping CVSS score of 9.0 (just one point beneath the score for the recent Shellshock bash vulnerability). 24 of the patches are for MySQL.

I highly advise anyone using MySQL or any Oracle product, including Java, to  update their software immediately.

Oracle MySQL Risk Matrix

Remote Exploit without Auth.?CVSS VERSION 2.0 RISK (see Risk Matrix Definitions)Supported Versions AffectedNotes
Base ScoreAccess VectorAccess ComplexityAuthen-
CVE-2014-6507MySQL ServerMySQL ProtocolSERVER:DMLNo8.0NetworkLowSinglePartial+Partial+Complete5.5.39 and eariler, 5.6.20 and earlier
CVE-2014-6491MySQL ServerMySQL ProtocolSERVER:SSL:yaSSLYes7.5NetworkLowNonePartial+Partial+Partial+5.5.39 and earlier, 5.6.20 and earlier
CVE-2014-6500MySQL ServerMySQL ProtocolSERVER:SSL:yaSSLYes7.5NetworkLowNonePartial+Partial+Partial+5.5.39 and earlier, 5.6.20 and earlier
CVE-2014-6469MySQL ServerMySQL ProtocolSERVER:OPTIMIZERNo6.8NetworkLowSingleNoneNoneComplete5.5.39 and eariler, 5.6.20 and earlier
CVE-2014-0224MySQL ServerMySQL ProtocolSERVER:SSL:OpenSSLYes6.8NetworkMediumNonePartialPartialPartial5.6.19 and earlierSee Note 1
CVE-2014-6530MySQL ServerMySQL ProtocolCLIENT:MYSQLDUMPNo6.5NetworkLowSinglePartial+Partial+Partial+5.5.38 and earlier, 5.6.19 and earlier
CVE-2014-6555MySQL ServerMySQL ProtocolSERVER:DMLNo6.5NetworkLowSinglePartial+Partial+Partial+5.5.39 and earlier, 5.6.20 and earlier
CVE-2014-6489MySQL ServerMySQL ProtocolSERVER:SPNo5.5NetworkLowSingleNonePartialPartial+5.6.19 and earlier
CVE-2012-5615MySQL ServerMySQL ProtocolSERVER:PRIVILEGES AUTHENTICATION PLUGIN APIYes5.0NetworkLowNonePartialNoneNone5.5.38 and earlier, 5.6.19 and earlier
CVE-2014-6559MySQL ServerMySQL ProtocolC API SSL CERTIFICATE HANDLINGYes4.3NetworkMediumNonePartial+NoneNone5.5.39 and earlier, 5.6.20 and earlier
CVE-2014-6494MySQL ServerMySQL ProtocolCLIENT:SSL:yaSSLYes4.3NetworkMediumNoneNoneNonePartial+5.5.39 and earlier, 5.6.20 and earlier
CVE-2014-6496MySQL ServerMySQL ProtocolCLIENT:SSL:yaSSLYes4.3NetworkMediumNoneNoneNonePartial+5.5.39 and earlier, 5.6.20 and earlier
CVE-2014-6495MySQL ServerMySQL ProtocolSERVER:SSL:yaSSLYes4.3NetworkMediumNoneNoneNonePartial5.5.38 and earlier, 5.6.19 and earlier
CVE-2014-6478MySQL ServerMySQL ProtocolSERVER:SSL:yaSSLYes4.3NetworkMediumNoneNonePartialNone5.5.38 and earlier, 5.6.19 and earlier
CVE-2014-4274MySQL ServerMySQL ProtocolSERVER:MyISAMNo4.1LocalMediumSinglePartial+Partial+Partial+5.5.38 and earlier, 5.6.19 and earlier
CVE-2014-4287MySQL ServerMySQL ProtocolSERVER:CHARACTER SETSNo4.0NetworkLowSingleNoneNonePartial+5.5.38 and earlier, 5.6.19 and earlier
CVE-2014-6520MySQL ServerMySQL ProtocolSERVER:DDLNo4.0NetworkLowSingleNoneNonePartial+5.5.38 and earlier
CVE-2014-6484MySQL ServerMySQL ProtocolSERVER:DMLNo4.0NetworkLowSingleNoneNonePartial+5.5.38 and earlier, 5.6.19 and earlier
CVE-2014-6464MySQL ServerMySQL ProtocolSERVER:INNODB DML FOREIGN KEYSNo4.0NetworkLowSingleNoneNonePartial+5.5.39 and earlier, 5.6.20 and earlier
CVE-2014-6564MySQL ServerMySQL ProtocolSERVER:INNODB FULLTEXT SEARCH DMLNo4.0NetworkLowSingleNoneNonePartial+5.6.19 and earlier
CVE-2014-6505MySQL ServerMySQL ProtocolSERVER:MEMORY STORAGE ENGINENo4.0NetworkLowSingleNoneNonePartial+5.5.38 and earlier, 5.6.19 and earlier
CVE-2014-6474MySQL ServerMemcachedSERVER:MEMCACHEDNo3.5NetworkMediumSingleNoneNonePartial+5.6.19 and earlier
CVE-2014-6463MySQL ServerMySQL ProtocolSERVER:REPLICATION ROW FORMAT BINARY LOG DMLNo3.3NetworkLowMultipleNoneNonePartial+5.5.38 and earlier, 5.6.19 and earlier
CVE-2014-6551MySQL ServerMySQL ProtocolCLIENT:MYSQLADMINNo2.1LocalLowNonePartialNoneNone5.5.38 and earlier, 5.6.19 and earlier

Tuesday, September 18, 2012

Disable Display_Errors in Production

Its a simple message, but worth repeating.

Yesterday I came across the website of a major internet security firm making a few first-day-on-the-job mistakes. While I am not going to "out" them before contacting them directly, what they did is silly enough that it warrants a bit of discussion in the abstract.

Display_errors was enabled in their web server's php.ini. As a result, a few helpful messages were displayed briefly at the top of several of pages on the site

1. The name of the database
2. The name of the table in use by that page
3. A list of every column in that table
4. An error indicating that the table is exceeding its maximum allowable size of 4GB

The site collects information about its users - IP address, browser info, referrer, etc, and stores that information to a table in a MySQL database - we know from the error itself that database is running on a server using a 32 bit operating system. With the structure of the database, we have everything we need for SQL injection.

That said, there was one additional level of security. The internet security company is masking database queries in URLs - clicking around the site, it became clear that calls to the database are encoded using an encrypted hash. Unfortunately for the internet security company, this technique obscures rather than protects. Because the hashing is not applied consistently across all requests, it actually helps to draw attention to pages that require further scrutiny from an attacker. And of course, since we already have the structure of a database, we can use php's md5 and sha-1 functions to encode our own injection attempts. I will give the internet security company bonus points for not using base64 encoding for the masking - its surprising how often base64 is used for this purpose when it is trivial to decode and under normal circumstances does not provide any performance benefit. If anyone knows of some good reasons to use base64, please shoot me an email or leave a comment.

In summary - I hope this post helps to illustrate how displaying error information, a very common mistake, can lead to the compromise of an otherwise secure site. I left out a lot of information as it was not my intention to create a "how to" guide on SQL injection. That said I hope I found a good balance between providing a practical example without encouraging nasty behavior. Always remember to disable remote error reporting and debugging features on production servers. When debugging is needed, enable it just long enough to resolve the issue and then turn it back off. Do not attempt to use verbosity settings as a way of securely displaying error information - it only takes one poorly worded error message to compromise a site.

Saturday, May 19, 2012

MySQL root Grants Broken Following a phpmyadmin Install in Windows

So this is a weird one. I recently installed phpmyadmin 3.5.1 in a MySQL 5.1 / IIS 7.5 environment. Everything was going well until I realized that following the installation (which was fully functional) I could not login to MySQL (from the CLI) without referencing the hostname (-h flag). I figured that maybe the .sql script included with the installer messed with my grants, but a quick show grants revealed I still had the same permissions granted to root as when I started. So I figured that I would update the grants on root to what was displayed in show grants just in case. This produced an insufficient permissions error even though root had "full" privileges.

To resolve this I added skip-grant-tables to my.ini, restarted the mysql service, logged in as root, flushed privileges, and again updated grants to what was displayed in "show grants". I then removed skip-grant-tables and restarted, and I was again able to login locally. I'm still not certain what caused this and there was of course no relevant data in the logs. If anyone has any ideas I would definitely appreciate feedback in the comments!