Skip to content

EXECVE en auditd: auid, ses y argumentos en hexadecimal

Reconstruir líneas de comando desde audit.log de Linux: agrupar registros por evento, argumentos EXECVE, valores en hexadecimal, y auid y ses a través de sudo.

Publicado el 5 min de lectura

En resumen. Con una regla de execve cargada, audit.log registra cada programa ejecutado en el host. Una ejecución son varios registros (SYSCALL, EXECVE, CWD, PATH, PROCTITLE) que comparten la misma marca msg=audit(sec.msec:serial). Agrupa por esa marca, decodifica los argumentos en hexadecimal y usa auid (el usuario que inició sesión) y ses (la sesión de inicio) para seguir a un usuario a través de sudo -i hasta una shell de root, donde auth.log se queda ciego.

¿El host lo tiene siquiera?

auditd está instalado y habilitado por defecto en RHEL y Fedora, no en Debian ni en Ubuntu. Incluso donde se ejecuta, no existen registros execve a menos que una regla los pida, por ejemplo:

-a always,exit -F arch=b64 -S execve -k exec

Lee /etc/audit/rules.d/*.rules en la imagen (y la salida de auditctl -l si se recopiló en vivo) antes de sacar conclusiones de la ausencia de registros. Sin reglas de execve se siguen obteniendo los eventos de espacio de usuario: USER_AUTH, USER_LOGIN, USER_START, USER_END, USER_CMD (sudo), USER_CHAUTHTOK (cambio de contraseña), ADD_USER y los cambios de configuración de la auditoría.

Un evento, varios registros

type=SYSCALL msg=audit(1789381120.086:181322): arch=c000003e syscall=59 success=yes exit=0 ppid=3200 pid=3204 auid=1001 uid=0 gid=0 euid=0 tty=pts1 ses=114 comm="tar" exe="/usr/bin/tar" key="exec"
type=EXECVE msg=audit(1789381120.086:181322): argc=4 a0="tar" a1="czf" a2="/tmp/.f.tgz" a3=2F7372762F66696E616E63652F513320636C6F7365
type=CWD msg=audit(1789381120.086:181322): cwd="/home/svc_backup"
type=PATH msg=audit(1789381120.086:181322): item=0 name="/usr/bin/tar" inode=13113204 ... nametype=NORMAL
type=PROCTITLE msg=audit(1789381120.086:181322): proctitle=74617200637A66002F746D702F2E662E74677A002F7372762F66696E616E63652F513320636C6F7365
type=EOE msg=audit(1789381120.086:181322):

Las seis líneas son un único evento. La marca 1789381120.086:181322 son los segundos desde la época Unix (UTC), los milisegundos y un número de serie generado por el kernel. El número de serie se reinicia en cada arranque, así que agrupa por la marca completa, no solo por el número de serie. Los registros de eventos distintos pueden intercalarse en el archivo; agrupar por marca resuelve ese problema.

Reconstruir la línea de comando

El registro EXECVE contiene argc y un campo por argumento:

  • Los valores entre comillas (a1="czf") son texto plano.
  • Los valores hexadecimales sin comillas (a3=2F7372...) están codificados en hexadecimal porque el argumento contiene un espacio, una comilla doble, un carácter de control o bytes no ASCII. Decodificar 2F7372762F66696E616E63652F513320636C6F7365 da /srv/finance/Q3 close: un único argumento con un espacio, que la línea de sudo en texto plano de auth.log no permite distinguir de dos.
  • Los argumentos largos se dividen: a1_len=N seguido de fragmentos a1[0]=..., a1[1]=..., y una línea de comando grande puede ocupar varios registros EXECVE del mismo evento. Concatena los fragmentos en orden antes de decodificar.
  • PROCTITLE contiene la línea de comando tal como la veía el proceso, codificada en hexadecimal con separadores NUL y truncada por el kernel si es larga. Prefiere EXECVE cuando existen ambos.

CWD indica el directorio de trabajo, lo que permite resolver las rutas relativas de los argumentos. Los registros PATH enumeran el ejecutable y el cargador, con inodo y propietario.

auid y ses: seguir al usuario hasta root

El registro SYSCALL lleva dos identidades:

  • uid, euid: con qué usuario se ejecuta el proceso en ese momento (0 dentro de una shell de root).
  • auid: el UID de inicio de sesión de auditoría, fijado una sola vez cuando el usuario inicia sesión (el registro LOGIN: old-auid=4294967295 auid=1001) y heredado por todos los procesos hijos, incluso a través de sudo y su. 4294967295 significa sin asignar: daemons y procesos del arranque.

Y una sesión:

  • ses: el ID de sesión de auditoría, fijado al mismo tiempo. Todos los comandos de ese inicio de sesión, como el usuario o como root, lo llevan.

En la práctica: auth.log muestra a svc_backup ejecutando sudo -i a las 10:04 y después nada hasta que se cierra la shell. audit.log, para ses=114, muestra lo que ocurrió dentro de esa shell:

type=SYSCALL ... auid=1001 uid=0 euid=0 tty=pts1 ses=114 comm="passwd" exe="/usr/bin/passwd"
type=SYSCALL ... auid=1001 uid=0 euid=0 tty=pts1 ses=114 comm="crontab" exe="/usr/bin/crontab" key="exec"
type=EXECVE  ... argc=4 a0="crontab" a1="-u" a2="svc_backup" a3="/tmp/.c"

uid=0 indica que lo ejecutó root; auid=1001, que fue durante el inicio de sesión de svc_backup. El journal guarda los mismos valores como _AUDIT_LOGINUID y _AUDIT_SESSION, lo que permite vincular las entradas del journal con la sesión de auditoría.

RAW y ENRICHED

Con log_format = ENRICHED (el valor por defecto upstream en las versiones actuales de audit; las distribuciones pueden cambiarlo), auditd añade los nombres resueltos tras un byte 0x1D, en mayúsculas: AUID="svc_backup" UID="root" SYSCALL=execve. Esos nombres se resolvieron en el host original, por lo que son más fiables que ausearch -i ejecutado en una estación de análisis con un /etc/passwd distinto. Con RAW, resuelve los UID con el /etc/passwd de la propia imagen.

ausearch para los casos clásicos

ausearch -if audit.log -m EXECVE -ul 1001 -i        # todo lo ejecutado con el UID de inicio de sesión 1001
ausearch -if audit.log --session 114 -i             # una sesión de inicio
ausearch -if audit.log -m USER_CMD -i               # comandos de sudo, hexadecimal decodificado
ausearch -if audit.log -m CONFIG_CHANGE,DAEMON_END -i   # manipulación de la auditoría

-i interpreta los valores con los archivos de cuentas del equipo de análisis, salvo que el log sea ENRICHED.

Qué buscar

  • Reconocimiento justo después del inicio de sesión: id, uname, cat /etc/passwd, sudo -l.
  • Persistencia: crontab, systemctl --user enable, escrituras en /etc/systemd/system o ~/.config/systemd/user.
  • Preparación y exfiltración: tar, zip, rclone, curl, scp con rutas a datos sensibles.
  • Antiforense: rm de archivos del journal, scripts ejecutados contra /var/log/wtmp, ln -sf /dev/null ~/.bash_history, history -c (un builtin, así que sin registro execve), auditctl -D o -e 0.
  • Líneas de comando del tipo reverse shell: intérpretes o herramientas de red cuyos argumentos redirigen una shell a una dirección remota. Trata una coincidencia de patrón como una pista y lee la lista completa de argumentos.

En el navegador

Linux Log Parser agrupa los registros de auditoría por marca, reconstruye los argumentos EXECVE incluidos los hexadecimales y fragmentados, lee logs RAW y ENRICHED, usa ses para asociar los comandos a las sesiones reconstruidas y señala la persistencia, los comandos de borrado de logs, las herramientas sospechosas y los patrones de tipo reverse shell. El caso práctico sigue ses=114 de principio a fin, y la ficha de auditd cubre reglas, retención y tipos de registro.

Artículos relacionados

Investigación de logs de Linux en un host de salto sintético: adivinación de contraseñas SSH, acceso desde una IP nueva, sudo -i, persistencia y manipulación.
Cómo encajan las cuatro familias de logs de Linux en una investigación, qué prueba cada una, dónde discrepan y cómo unirlas en una sola línea de tiempo.
Leer /var/log/auth.log y /var/log/secure: fuerza bruta e inicios de sesión SSH, shells de root con sudo y su, cambios de contraseñas y cuentas, formatos de hora