Para tener un poco mas de contexto si todavía no los leíste, deberías pasar por los posts Una instancia a la deriva I y Una instancia a la deriva II. Acá va un resumen:
- A las 3:33 (02:33 UTC) de la mañana del 23 de Julio recibí 2 emails que indicaban autenticaciones exitosas en la instancia.
- A partir de ese momento, en los gráficos de consumo de recursos provistos por AWS, se puede ver claramente que el comportamiento de la instancia cambió drásticamente. Consumo de CPU, red y acceso a disco se incrementaron.
- A partir del análisis de algunas de las capturas de tcpdump se puede ver un número importante de conexiones SSH iniciadas por la instancia contra direcciones IP de terceros. Esto daría a entender que la instancia fue infectada y ahora se encontraba atacando otras direcciones para propagar el problema.
- Cerca de las 04:40 (UTC) la instancia inicio la secuencia de shutdown. A este punto no está claro qué lo desencadenó si audtitd por espacio insuficiente o el cronjob que controlaba la ejecución de tcpdump.
Analizando el disco y los archivos de la instancia
Dado que la instancia se encuentra apagada le quité el volumen raíz, y lo asocié a otra instancia recién lanzada. A continuación se puede ver el disco /dev/xvdf de 10GB
root@ip-172-31-56-203:/home/ubuntu# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda 202:0 0 8G 0 disk
`-xvda1 202:1 0 8G 0 part /
xvdf 202:80 0 10G 0 disk
`-xvdf1 202:81 0 10G 0 part
root@ip-172-31-56-203:/home/ubuntu#
Monté el disco en modo solo lectura para evitar modificar o eliminar archivos por error.
root@ip-172-31-56-203:/home/ubuntu# mount -o ro /dev/xvdf1 /mnt/
root@ip-172-31-56-203:/home/ubuntu# mount
/dev/xvda1 on / type ext4 (rw,discard)
...
/dev/xvdf1 on /mnt type ext4 (ro)
root@ip-172-31-56-203:/home/ubuntu#
y lo primero que observé es el espacio de almacenamiento disponible...
root@ip-172-31-56-203:/home/ubuntu# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/xvda1 7.8G 782M 6.6G 11% /
none 4.0K 0 4.0K 0% /sys/fs/cgroup
udev 492M 12K 492M 1% /dev
tmpfs 100M 336K 99M 1% /run
none 5.0M 0 5.0M 0% /run/lock
none 497M 0 497M 0% /run/shm
none 100M 0 100M 0% /run/user
/dev/xvdf1 9.8G 9.2G 62M 100% /mnt
root@ip-172-31-56-203:/home/ubuntu#
exacto! 100% utilizado (a penas 62 MB libres) esto parecería tirar por el suelo mi idea de que habían detenido el proceso tcpdump y refuerza a su vez la teoría de auditd deteniendo la instancia por imposibilidad de escribir logs.
No hay archivos creados en el directorio home del usuario comprometido, esto me llamó un poco la atención, esperaba al menos encontrar algo ahí
root@ip-172-31-56-203:~/restored# ls -lah /mnt/home/ubuntu/
total 32K
drwxr-xr-x 4 ubuntu ubuntu 4.0K Jul 19 20:49 .
drwxr-xr-x 3 root root 4.0K Jul 6 20:42 ..
-rw------- 1 ubuntu ubuntu 9 Jul 19 20:49 .bash_history
-rw-r--r-- 1 ubuntu ubuntu 220 Apr 9 2014 .bash_logout
-rw-r--r-- 1 ubuntu ubuntu 3.6K Apr 9 2014 .bashrc
drwx------ 2 ubuntu ubuntu 4.0K Jul 6 20:43 .cache
-rw-rw-r-- 1 ubuntu ubuntu 0 Jul 6 20:43 .cloud-locale-test.skip
-rw-r--r-- 1 ubuntu ubuntu 675 Apr 9 2014 .profile
drwx------ 2 ubuntu ubuntu 4.0K Jul 21 07:19 .ssh
root@ip-172-31-56-203:~/restored#
En el directorio home de root, donde se guardaban las capturas, podemos ver que las mismas ocuparon del orden de 5GB
root@ip-172-31-56-203:~/restored# du -sch /mnt/root/
5.0G /mnt/root/
5.0G total
root@ip-172-31-56-203:~/restored#
y que tenemos 1062 capturas
root@ip-172-31-56-203:~/restored# ls /mnt/root/sample*|wc -l
1062
root@ip-172-31-56-203:~/restored#
para bien o para mal, parece no faltar ninguna.
En cuanto a los archivos de logs parecen estar intactos y en su lugar. Lo mas llamativo es la cantidad de logs generados por auditd:
root@ip-172-31-56-203:~/restored# ls /mnt/var/log/audit/
audit.log audit.log.16 audit.log.23 audit.log.30 audit.log.38 audit.log.45 audit.log.52 audit.log.6 audit.log.67 audit.log.74
audit.log.1 audit.log.17 audit.log.24 audit.log.31 audit.log.39 audit.log.46 audit.log.53 audit.log.60 audit.log.68 audit.log.75
audit.log.10 audit.log.18 audit.log.25 audit.log.32 audit.log.4 audit.log.47 audit.log.54 audit.log.61 audit.log.69 audit.log.76
audit.log.11 audit.log.19 audit.log.26 audit.log.33 audit.log.40 audit.log.48 audit.log.55 audit.log.62 audit.log.7 audit.log.77
audit.log.12 audit.log.2 audit.log.27 audit.log.34 audit.log.41 audit.log.49 audit.log.56 audit.log.63 audit.log.70 audit.log.78
audit.log.13 audit.log.20 audit.log.28 audit.log.35 audit.log.42 audit.log.5 audit.log.57 audit.log.64 audit.log.71 audit.log.79
audit.log.14 audit.log.21 audit.log.29 audit.log.36 audit.log.43 audit.log.50 audit.log.58 audit.log.65 audit.log.72 audit.log.8
audit.log.15 audit.log.22 audit.log.3 audit.log.37 audit.log.44 audit.log.51 audit.log.59 audit.log.66 audit.log.73 audit.log.9
root@ip-172-31-56-203:~/restored#
esto es un gran problema. El número de rotaciones de logs de audit es de 80, lo que significa que es MUY probable que los primeros logs hayan sido desechados... Una miradita rápida al log mas viejo nos confirma esto
root@ip-172-31-56-203:~/restored# aureport -t -if /mnt/var/log/audit/audit.log.79
Log Time Range Report
=====================
/mnt/var/log/audit/audit.log.79: 07/23/15 03:15:20.105 - 07/23/15 03:17:17.037
root@ip-172-31-56-203:~/restored#
El log mas viejo contempla los registros entre las 03:15 y las 03:17 del 23 de Julio. Lo cuál significa que NO vamos a tener información de los primero minutos posteriores a las 02:33 ya que por el número de eventos y la cantidad de rotaciones esos logs fueron perdidos.
Analizando un poco los logs:
El primer paso fue incluir los últimos logs de autenticaciones (/var/log/auth.log) en la BD para poder contabilizarlos de manera mas sencilla. De este paso obtuve la siguiente información:
- 54.196.232.229 realizó 38 intentos fallidos de autenticación entre las 02:32:08 y las 02:33:28.
- 59.188.237.12 no realizó intentos fallidos.
Jul 23 02:33:28 ip-172-31-54-250 sshd[32683]: Accepted password for ubuntu from 54.196.232.229 port 37470 ssh2
Jul 23 02:33:28 ip-172-31-54-250 sshd[32683]: pam_unix(sshd:session): session opened for user ubuntu by (uid=0)
Jul 23 02:33:29 ip-172-31-54-250 sshd[32683]: pam_unix(sshd:session): session closed for user ubuntu
Jul 23 02:33:30 ip-172-31-54-250 sshd[316]: error: Could not load host key: /etc/ssh/ssh_host_ed25519_key
Jul 23 02:33:32 ip-172-31-54-250 sshd[316]: Accepted password for ubuntu from 59.188.237.12 port 2693 ssh2
Jul 23 02:33:32 ip-172-31-54-250 sshd[316]: pam_unix(sshd:session): session opened for user ubuntu by (uid=0)
Jul 23 02:33:33 ip-172-31-54-250 sshd[370]: Received disconnect from 59.188.237.12: 11: Shutdown.
Jul 23 02:33:33 ip-172-31-54-250 sshd[316]: pam_unix(sshd:session): session closed for user ubuntu
Jul 23 02:33:35 ip-172-31-54-250 sshd[380]: error: Could not load host key: /etc/ssh/ssh_host_ed25519_key
Jul 23 02:33:35 ip-172-31-54-250 sshd[381]: error: Could not load host key: /etc/ssh/ssh_host_ed25519_key
Jul 23 02:33:37 ip-172-31-54-250 sshd[380]: Accepted password for ubuntu from 59.188.237.12 port 2697 ssh2
Jul 23 02:33:37 ip-172-31-54-250 sshd[380]: pam_unix(sshd:session): session opened for user ubuntu by (uid=0)
Jul 23 02:33:37 ip-172-31-54-250 sshd[381]: Accepted password for ubuntu from 59.188.237.12 port 2696 ssh2
Jul 23 02:33:37 ip-172-31-54-250 sshd[381]: pam_unix(sshd:session): session opened for user ubuntu by (uid=0)
Jul 23 02:33:41 ip-172-31-54-250 chpasswd[504]: pam_unix(chpasswd:chauthtok): user "butter" does not exist in /etc/passwd
Jul 23 02:33:41 ip-172-31-54-250 sshd[489]: Received disconnect from 59.188.237.12: 11: Shutdown.
Jul 23 02:33:41 ip-172-31-54-250 sshd[381]: pam_unix(sshd:session): session closed for user ubuntu
Jul 23 02:34:44 ip-172-31-54-250 sshd[488]: Received disconnect from 59.188.237.12: 11: Shutdown.
Jul 23 02:34:44 ip-172-31-54-250 sshd[380]: pam_unix(sshd:session): session closed for user ubuntu
- A las 02:33:28 el host 54.196.232.229 dio con el password correcto para el usuario ubuntu.
- 4 segundos después a las 02:33:32 el host 59.188.237.12 inicia una sesión con el usuario y password correcto. Posiblemente para corroborar que sean válidos, dado que la sesión es terminada al segundo.
- A las 02:33:37 se inician dos sesiones desde la IP 59.188.237.12, esta vez duran unos segundos mas. Una de ellas es terminada a las 02:33:41 (4 segundos después de iniciar), mientras que la otra termina a las 02:34:44 (1 minuto y 7 segundos después de iniciar).
- A las 02:33:41 se ejecutó el comando chpasswd, básicamente es utilizado para cambiar passwords en batch. No entiendo para qué harían esto. De hecho el error saltó porque el usuario butter no existe en el sistema.
Los logs de auditd
De los logs de auditd, lamentablemente no hay mucho para decir ya que la parte más importante (los minutos correspondientes a las sesiones SSH) se perdió por la rotación. A pesar de esto, acá va lo que pude encontrar a partir de los logs que quedaron:
- Analizando el archivo mas viejo
root@ip-172-31-56-203:/home/ubuntu# aureport -i -if /mnt/var/log/audit/audit.log.79
Summary Report
======================
Range of time in logs: 07/23/15 03:15:20.105 - 07/23/15 03:17:17.037
Selected time for report: 07/23/15 03:15:20 - 07/23/15 03:17:17.037
Number of changes in configuration: 0
Number of changes to accounts, groups, or roles: 0
Number of logins: 0
Number of failed logins: 0
Number of authentications: 0
Number of failed authentications: 0
Number of users: 3
Number of terminals: 2
Number of host names: 1
Number of executables: 5
Number of files: 26
Number of AVC's: 0
Number of MAC events: 0
Number of failed syscalls: 0
Number of anomaly events: 0
Number of responses to anomaly events: 0
Number of crypto events: 0
Number of keys: 1
Number of process IDs: 226
Number of events: 11314
root@ip-172-31-56-203:/home/ubuntu#
Podemos identificar esos 5 ejecutables que se mencionan en el reporte general con el flag -x de la siguiente manera:
root@ip-172-31-56-203:/home/ubuntu# aureport -x --summary -if /mnt/var/log/audit/audit.log.79
Executable Summary Report
=================================
total file
=================================
11264 /tmp/squid64 (deleted)
15 /usr/sbin/cron
12 /bin/rm
11 /usr/sbin/tcpdump (deleted)
11 /bin/tar
root@ip-172-31-56-203:/home/ubuntu#
De los 5 ejecutables solo uno me resulta sospechoso y claramente es /tmp/squid64. Lamentablemente el archivo ya no se encuentra en /tmp, debe haber sido eliminado después de lanzarse el proceso probablemente, y no logré recuperarlo. Los otros ejecutables son parte de los procesos de control y monitoreo explicados en el primer post.
Podemos ver también cuáles fueron los archivos mas utilizados en estos eventos:
root@ip-172-31-56-203:/home/ubuntu# aureport -f --summary -if /mnt/var/log/audit/audit.log.79
File Summary Report
===========================
total file
===========================
11264 /etc/passwd
23 /root/
11 /root
2 /root/sample295.jpg
2 /root/sample296.jpg
2 /root/sample297.jpg
2 /root/sample298.jpg
2 /root/sample299.jpg
2 /root/sample300.jpg
2 /root/sample301.jpg
2 /root/sample302.jpg
2 /root/sample303.jpg
2 /root/sample304.jpg
2 /root/sample305.jpg
1 /root/sample294.jpg
1 sample296
1 sample297
1 sample298
1 sample299
1 sample300
1 sample301
1 sample302
1 sample303
1 sample304
1 sample305
1 sample306
root@ip-172-31-56-203:/home/ubuntu#
Parece mucha coincidencia que el proceso /tmp/squid64 y el archivo /etc/passwd se hayan registrado en la misma cantidad de eventos.
De hecho si filtramos el reporte por eventos vemos:
root@ip-172-31-56-203:/home/ubuntu# aureport -e -i --summary -if /mnt/var/log/audit/audit.log.79
Event Summary Report
======================
total type
======================
11298 SYSCALL
3 USER_END
3 USER_START
3 CRED_DISP
3 CRED_ACQ
3 USER_ACCT
1 CWD
root@ip-172-31-56-203:/home/ubuntu#
El evento SYSCALL (tipo 1300) se registró 11298 veces. A partir del reporte de las syscalls utilizadas vemos que la mas registrada fue open (syscall 2):
root@ip-172-31-56-203:/home/ubuntu# aureport -s -i --summary -if /mnt/var/log/audit/audit.log.79
Syscall Summary Report
==========================
total syscall
==========================
11275 open
12 unlinkat
11 creat
root@ip-172-31-56-203:/home/ubuntu#
De las 11275 llamadas a open, 11264 fueron para el archivo /etc/passwd, y llamada por el binario /tmp/squid64.
Por último miramos el registro de eventos por usuario y vemos claramente que la mayoría de los eventos fueron generados por el usuario comprometido (ubuntu):
root@ip-172-31-56-203:/home/ubuntu# aureport -u --summary -i -if /mnt/var/log/audit/audit.log.79
User Summary Report
===========================
total auid
===========================
11264 ubuntu
34 root
15 unset
root@ip-172-31-56-203:/home/ubuntu#
- Analizando un evento particular
root@ip-172-31-56-203:/home/ubuntu# ausearch -a "513448" -i -if /mnt/var/log/audit/audit.log.79
----
type=PATH msg=audit(07/23/15 03:15:20.113:513448) : item=0 name=/etc/passwd inode=397875 dev=ca:01 mode=file,644 ouid=root ogid=root rdev=00:00 nametype=NORMAL
type=CWD msg=audit(07/23/15 03:15:20.113:513448) : cwd=/home/ubuntu
type=SYSCALL msg=audit(07/23/15 03:15:20.113:513448) : arch=x86_64 syscall=open success=yes exit=26 a0=0x7f0beb4fd35c a1=O_RDONLY|O_CLOEXEC a2=0x1b6 a3=0x7f0bd0000078 items=1 ppid=1 pid=1588 auid=ubuntu uid=ubuntu gid=ubuntu euid=ubuntu suid=ubuntu fsuid=ubuntu egid=ubuntu sgid=ubuntu fsgid=ubuntu tty=(none) ses=30 comm=squid64 exe=/tmp/squid64 (deleted) key=(null)
root@ip-172-31-56-203:/home/ubuntu#
En esencia, el proceso PID 1588 ejecutado del binario /tmp/squid64 abre el archivo /etc/passwd en modo lectura (no entiendo con qué objetivo hace eso...). El hecho de que el PPID del proceso sea 1 (init) significa que el proceso padre fue terminado e init pasó a ser el padre del mismo. Muy probablemente el proceso padre original fue la shell abierta por SSH.
- El verdadero porque del shutdown
root@ip-172-31-56-203:/mnt# ausearch -a "1708" -i -if /mnt/var/log/audit/audit.log
----
type=DAEMON_END msg=audit(07/23/15 04:40:21.000:1708) : auditd normal halt, sending auid=root pid=13214 subj=l=3.13.0-48-generic auid=root pid=18333 subj=unconfined res=success res=success
root@ip-172-31-56-203:/mnt#
También se puede ver el reflejo de esto en /var/log/syslog, a las 04:39:56 se registró el primer mensaje indicando poco espacio disponible en el disco:
root@ip-172-31-56-203:/mnt# grep auditd var/log/syslog
Jul 23 04:39:04 ip-172-31-54-250 auditd[18333]: message repeated 108 times: [ Audit daemon rotating log files]
Jul 23 04:39:56 ip-172-31-54-250 auditd[18333]: Audit daemon is low on disk space for logging
Jul 23 04:40:01 ip-172-31-54-250 auditd[18333]: Audit daemon is low on disk space for logging
Jul 23 04:40:03 ip-172-31-54-250 auditd[18333]: Audit daemon rotating log files
Jul 23 04:40:05 ip-172-31-54-250 auditd[18333]: Audit daemon is low on disk space for logging
Jul 23 04:40:19 ip-172-31-54-250 auditd[18333]: The audit daemon is now halting the system
root@ip-172-31-56-203:/mnt#
Analizando un poco las capturas de red
Como mencioné antes, las capturas de red se encuentran totalmente disponibles y aparentemente intactas dentro del directorio home del usuario root. En el post anterior, me había quedado mucha intriga con respecto a la captura número 105, ya que no había sido enviada por email y era la que debería haber capturado toda la actividad de los dos hosts mencionados. Utilizando wireshark y su análisis de conversaciones podemos ver lo siguiente
Las muchas intervenciones hechas por la dirección 54.196.232.229:
- Se puede apreciar la similitud de todas las conversaciones TCP siempre con la misma cantidad de paquetes y bytes transferidos, estas conexiones son los intentos fallidos de login. La excepción es la última conexión que intercambió 6 paquetes mas y unos bytes mas también.
- La última conexión es la última actividad registrada para esta IP y muy probablemente se trate de la conexión con que se adivinó el password del usuario.
Las 3 intervenciones hechas por la dirección 59.188.237.12:
- En la primer conexión apenas se intercambiaron unos 7758 bytes, esta es la conexión que podría haber sido para comprobar la tupla ip, usuario, password
- La segunda conexión ya tuvo bastante mas tráfico 2.3MB aproximadamente, de los cuales 2.24 MB se movieron desde 59.188.237.12 a la instancia. Esto indica la subida de uno o mas archivos.
- No hay mucho para suponer de la 3er conexión, es significativamente mas chica que la segunda, pero el doble de la primera. Posiblemente para recolectar alguna información del host infectado.
Técnicamente las conexiones 2 y 3 se inician con una diferencia de milisegundos entre ellas.
Un dato muy interesante es que no todo en las capturas resulta ser tráfico SSH encriptado!!! Escripteando un poco con tcpdump, encontré tráfico HTTP entre la instancia y el host 59.188.237.12. Y adivinen qué se envía por este medio? sin cifrado y con un simple HTTP POST!!!!
Si... nada mas y nada menos que las tuplas ip, usuario, passowrd encontradas y de hecho con mi instancia encontraron varias xD. Se puede ver claramente como mediante una petición POST desde la intancia se cargan los valores en cuestión. Esto refuerza mas aún la hipótesis de que el host 59.188.237.12 se encarga de recolectar e infectar constantemente.
Intenté encontrar llamadas a curl o wget que se pudieran estar usando para este paso, pero no logré encontrar nada en los logs de audit, así que al parecer esta operación debe estar manejado por el mismo binario squid64.
Y /tmp/squid64 dónde está?
Después de tanto revuelo, wireshark, tcpdump y demás hierbas no pude encontrar el archivo que subieron y ejecutaron en la instancia, el famoso squid64. Así que con buena parte del misterio resuelto me puso a invertir unas horas mas en intentar saber algo mas sobre el archivo.
Haciendo uso de autopsy pude obtener una lista de Orphan files del volumen y uno de ellos me resultó muy interesante:
Inode: 13931 Type: regular Mode: 0755 Flags: 0x80000
Generation: 3210820034 Version: 0x00000000:00000001
User: 1000 Group: 1000 Size: 0
File ACL: 0 Directory ACL: 0
Links: 0 Blockcount: 0
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x55b07036:ba627a40 -- Thu Jul 23 04:40:22 2015
atime: 0x55b052ba:5086de40 -- Thu Jul 23 02:34:34 2015
mtime: 0x55b07036:ba627a40 -- Thu Jul 23 04:40:22 2015
crtime: 0x55b05286:a843ce40 -- Thu Jul 23 02:33:42 2015
dtime: 0x55b07036 -- Thu Jul 23 04:40:22 2015
Size of extra inode fields: 28
EXTENTS:
(END)
A pesar de que los bloques ya no se encuentran asoaciados al inodo 13931, podemos ver los metadatos
- Usuario 1000 (ubuntu)
- Fecha de creación: 02:33:42 del 23 de Juli
- Fecha de última modificación 04:40:22 del 23 de Julio
Yendo un poco mas profundo y buscando cadenas (strings) dentro de los bloques de disco no asignados encontré algunas cosas interesantes:
[-] ERROR: could not create SSH session
SUXX
/dev/urandom
/dev/random
socket error:
POST %s HTTP/1.1
Host: %s
Host: %s:%d
Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20090913 Firefox/3.5
.3
User-Agent: %s
Content-Length: %d
zhangyan7tian
data=%s %s %s
/stat.asp
59.188.237.12
ask_userauth
entering function %s line %d in /root/sshcrack/libssh-0.5.3/src/auth.c
ssh-userauth
leaving function %s line %d in /root/sshcrack/libssh-0.5.3/src/auth.c
...
Receiving banner: too large banner
ssh_send_banner
SSH-1.5-libssh-0.5.2
SSH-2.0-libssh-0.5.2
Received SSH_KEXDH_REPLY
Entre tantas cadenas podemos ver
- El banner SSH-2.0-libssh-0.5.2 con que se identifica el cliente SSH que realiza las conexiones de manera masiva.
- Un path de archivos fuente /root/sshcrack/libssh-0.5.3/src/auth.c parece tratarse del path the compilación de la aplicación sshcrack. Lo raro es que utiliza libssh-0.5.3 en lugar del 0.5.2.
- Vemos el encabezado HTTP con la llamada POST completa e incluso pareciera estar hardcodeada la IP de recolección e infección (59.188.237.12).
zhangyan
zhangyan7tian
3rddf
root
12345
root
admin
root
password
root
123muie123
root
root
root
1234
root
root123
root
123456
root
...
qwerty123
root
qwerty
root
pa55w0rd
root
1qaz2wsx
root
root
toor
...
root
^%$#@!
root
^&*()
root
5mmQ
En fin, no pude obtener el archivo, pero quedaron muchos rastros que podrían formar parte del mismo. Desafortunadamente no contemplé en ningún momento la posibilidad de perder logs de auditd, incluso sabiendo de la rotación, creí que 80 era un número mas que suficiente.
Resumen
Hasta aquí llegó mi amor! A modo de resumen para cerrar la saga es dejo los siguientes puntos:
- Está claro que hay al menos 2 tipos de nodos en este proceso. Los nodos (tipo A) como 54.196.232.229 que buscan usuarios con passwords triviales y nodos como 59.188.237.12 (tipo B) que se encargan de infectar y recolectar las tuplas obtenidas por los nodos tipo A.
- Cuando un nodo tipo A consigue un usuario y password lo reporta instantaneamente al nodo tipo B, mediante un mensaje POST HTTP.
- El nodo tipo B se conecta al host y realiza una serie de operaciones que no pudieron ser determinadas con precisión, pero que convierten al host en un nodo tipo A.