La red de la empresa es un quilombo. Tenemos la red de la oficina por un lado, con los desktops en una red privada y los servers en una red pública (parte de la red pública del edificio donde está la oficina). Tenemos dos CoLos, uno en Rotterdam (Verizon; no me pidan comentarios) y otro en Amsterdam (xs4all; parece que le da housing a la mitad de .nl). En el primero tenemos tres rangos públicos y al menos dos privados, y en el otro tenemos sólo un rango público y unos dos o tres privados, incluyendo un cross-over entre los dos firewalls para hacer fail-over. En resumen, 5 redes públicas y vayasabersecuántas privadas desperdigadas.
Para complicar un poco más las cosas, montamos (bueno, yo no tuve nada que ver, pero ya trabajaba acá) una VPN entre los dos CoLos, teniendo ambas puntas en los firewalls (sin contar de que una punta tenemos dos; uno duerme hasta que el otro se cae).
El último ingrediente de esta sopa: graficamos el tráfico con MRTG (si, ya sé de Munin, ya lo sugerí, pero son como 80 servers en total) sacando los datos por SNMP (que, como dicen en todos lados, de simple tiene sólo el nombre). Pero para el caso es simple: un cliente corre en el server graficador, en este caso en Rotterdam, y en el nodo a graficar un servidorcito SNMP; el tráfico es por UDP.
'Bueno, ¿y dónde está la complicación?', se preguntarán. Les cuento.
Esta gente (notar cómo cuando se mandan una 'cagada' me despego
:-P) tiene unos firewalls implementados a mano en
bash. No es la típica ristra de reglas
iptables, sino algo un poco más elaborado, con
funcioncitas, pero aún así son 1400 líneas de bash y
otras 630 de configuración (en bash también, obvio; no
hay manera más fácil de hacer configuración de scripts
bash que en bash mismo). Ya les comenté
de shorewall también, pero todo a su tiempo.
Entonces me tocó la tarea de poner a andar el SMNP contra los firewalls de Amsterdam. Parece una boludez, sobre todo porque el MRTG tiene scripts con los que crear la configuración automáticamente leyendo lo que hay disponible por el mismo protocolo (lo diseñadores tuvieron la decencia de ponerle 'descubribilidad'). Por simple que parezca, no andaba nipatrásnipadelante. Le dimos quichicientas vueltas y náa.
Lo más raro fue cuando empezamos a usar tcpdump en
las interfaces externas de los firewalls. Filtrando por el puerto
161 (snmp), en el firewall de Amsterdam veíamos el
tráfico entrante pero no el saliente. Eso nos llevó a pensar que el
firewall estaba jodiendo, pero entonces vimos que el tráfico que
generaba el gráfico para el otro firewall, el durmiente, hacía lo
mismo: veíamos el request pero no la respuesta. Pero el gráfico
andaba. Y para complicar las cosas, con IPSec andando no deberíamos
ver el tráfico, pues tcpdump no sabe desencriptar esos
paquetes, sino apenas reconocerlos.
Entonces sospechamos.
Probando el tcpdump en el firewall de la red de
Rotterdam vimos un comportamiento simétrico: no veíamos el request
pero si la respuesta. Y sospechamos mas fuerte.
Mirando con mas fuerza me dí con que los scripts de firewall
tenían un par de bugs: la función que seteaba las excepciones para
el firewall mismo no era llamada nunca y además llamaba a
iptables con parámetros erróneos.
La conclusión a la que llegamos, basada únicamente en lo que pudimos ver, es que el túnel anda, y que IPSec hace cosas raras con los paquetes; creemos que cuando los termina de procesar un paquete lo inyecta en la interfaz por la que entró, y eso es lo que hace que veamos el tráfico para un lado. Algún día que esté muy aburrido me voy a poner a ver si esta teoría es cierta.
sysadmin security
El otro día dí una charlita un poquito larga de ssh/scp y screen
en el IATE, el lugar donde
laburo. En la misma hablo de ssh/scp básico, mas cómo
poner claves públicas/privadas y cómo usar el
ssh-agent para administrarlas (algo de lo que ya
hablé en este glob), mas otros temas como el X11 forwarding y
el agent-forwarding. Además hablé de screen, una
herramineta que se complementa muy bien con ssh. Dejo
las filminas acá.
security utils
En este post veremos cómo crear pares de claves pública/privada
con passphrases, y cómo usar ssh-agent para no tener
que andar tipeándolas a cada rato.
Lo primero es generar el par. Hay dos tipos de pares de claves,
RSA y DSA. Los pares se guardan en nuestro .ssh/, así
que antes de generar un par nos fijamos qué hay allí:
mdione@cobra:~$ ls -l .ssh/
total 28
-rw-r--r-- 1 mdione mdione 190 2008-02-26 15:29 config
-rw------- 1 mdione mdione 1743 2008-09-19 16:55 id_dsa
-rw-r--r-- 1 mdione mdione 394 2008-09-19 16:55 id_dsa.pub
-rw------- 1 mdione mdione 11598 2008-09-02 10:35 known_hosts
-rw------- 1 mdione mdione 9388 2008-06-05 22:59 known_hosts.old
Hay una par DSA (id_dsa e id_dsa.pub),
así que creamos un par RSA para no pisarlo:
mdione@cobra:~$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/mdione/.ssh/id_rsa):
*** Enter passphrase (empty for no passphrase):
*** Enter same passphrase again:
Your identification has been saved in /home/mdione/.ssh/id_rsa.
Your public key has been saved in /home/mdione/.ssh/id_rsa.pub.
The key fingerprint is:
1c:da:2b:a8:97:72:7e:ab:ff:ea:bb:e8:6b:64:4c:93 mdione@cobra
The key's randomart image is:
+--[ RSA 2048]----+
| |
| |
| . . |
| E + . |
| o .. S |
| +. . |
| o... . |
| ..=... |
| .B**B*. |
+-----------------+
Notar que en *** ssh-keygen pide dos
veces una passphrase. El término passphrase viene
de la época en que las passwords sólo podían ser de un maximo de 8
caracteres. La passphrase puede ser de cualquier longitud; una
longitud buena está en los 15-20 caracteres. Se puede poner una
passphrase nula, pero por motivos de seguridad les sugiero que
no lo hagan. Si aprenden bien a usar
ssh-agent van a tener que tipearla poco.
Ahora copiamos la parte pública al servidor al que queremos entrar:
mdione@cobra:~$ ssh-copy-id -i .ssh/id_rsa.pub beetroot.except.com.ar
*** mdione@beetroot.except.com.ar's password:
Now try logging into the machine, with "ssh 'beetroot.except.com.ar'", and check in:
.ssh/authorized_keys
to make sure we haven't added extra keys that you weren't expecting.
Probamos entrar al server para ver que el par ande:
mdione@cobra:~$ ssh beetroot.except.com.ar
*** Enter passphrase for key '/home/mdione/.ssh/id_rsa':
Last login: Fri Sep 19 12:18:16 2008 from ginger.except.com.ar
mdione@beetroot:~$ logout
Connection to beetroot.except.com.ar closed.
Notar que en *** pide la passphrase del par que
acabamos de crear.
Ahora a usar ssh-agent. ssh-agent se
inicia en toda sesión en una distro moderna, podemos verlo dando
vueltas en nuestro background:
mdione@cobra:~$ ps fax | grep ssh-agent
2997 ? Ss 0:00 \_ ssh-agent screen
En este caso lo tengo corriendo antes de un screen,
pero en un desktop podemos ver algo de la pinta
/usr/bin/ssh-agent /usr/bin/dbus-launch --exit-with-session
x-session-manager.
Una vez que vemos el ssh-agent dando vueltas por
ahí, veamos qué claves tiene:
mdione@cobra:~$ ssh-add -l
The agent has no identities.
Ok, agreguemos identidades al agente:
mdione@cobra:~$ ssh-add /home/mdione/.ssh/id_rsa
*** Enter passphrase for /home/mdione/.ssh/id_rsa:
Identity added: /home/mdione/.ssh/id_rsa (/home/mdione/.ssh/id_rsa)
mdione@cobra:~$ ssh-add -l
2048 1c:da:2b:a8:97:72:7e:ab:ff:ea:bb:e8:6b:64:4c:93 /home/mdione/.ssh/id_rsa (RSA)
En *** ssh-add nos pide la passphrase
de la clave. Ok, probemos entrar al servidor:
mdione@cobra:~$ ssh beetroot.except.com.ar
Last login: Fri Sep 19 20:58:57 2008 from 200.69.231.1
mdione@beetroot:~$
No pidió la passphrase, que es lo que queríamos.
Las passphrases quedan en el ssh-agent por un
período determinado de tiempo. Por defecto duran para siempre, pero
con ssh-add -t <segundos> podemos cambiar eso.
También podemos borrar una identidad con ssh -d <clave
privada> o todas las identidades con ssh-add
-D (que molesta costumbre de estas herramientas que tienen
nombre de creación pero con algunas opciones de destrucción;
ssh-keygen tiene una opción -R que no
sólo borra claves, sino que lo hace sobre el
.ssh/known-hosts, cuando el comando por sí solo actúa
en los pares de claves).
En otro post mostraré cómo sacar identidades de un agent y ponerlo en otro.
utils security
Siguiendo un poco la historia de ayer, un reporte mas detallado. Antes de ir a los bifes, quiero decir que una de las máquinas que ayer dije que estaba infectada no lo estaba. Descartando esa máquina podemos agregar otro factor común que no me gusta ni mierda: yo tengo usuario en todas, pero no en todas tengo sudo. También se agregó otra máquina de mi casa, que tiene Apache, pero no en el puerto 80, no al menos desde fuera.
Como comenté, lo instalado está en /usr/lib/libb/... /. El contenido es el siguiente:
$ ls -laR
.:
total 654
drwxr-xr-x 3 mdione mdione 152 feb 1 09:07 .
drwxr-xr-x 3 mdione mdione 280 feb 1 09:07 ..
-rw-r--r-- 1 mdione mdione 1638 ene 10 2006 bugfalse.c
-rw-r--r-- 1 mdione mdione 2369 ene 10 2006 clear.sh
drwxr-xrwx 3 mdione mdione 984 ene 10 2006 rk
-rw-r--r-- 1 mdione mdione 657610 ene 10 2006 rk2.tgz
./rk:
total 1609
drwxr-xrwx 3 mdione mdione 984 ene 10 2006 .
drwxr-xr-x 3 mdione mdione 152 feb 1 09:07 ..
-rw-r--r-- 1 mdione mdione 382 mar 5 2004 .b
-rw-r--r-- 1 mdione mdione 427 ago 7 2002 brute.sh
-rwxr-xr-x 1 mdione mdione 116352 mar 5 2004 chfn
-rwxr-xr-x 1 mdione mdione 115828 mar 5 2004 chsh
-rw-r--r-- 1 mdione mdione 123 mar 6 2002 desuid.sh
-rw-r--r-- 1 mdione mdione 249 ago 14 2002 dlog
-rwxr-xr-x 1 mdione mdione 54041 mar 5 2004 du
-rwxr-xr-x 1 mdione mdione 57296 mar 5 2004 find
-rwxr-xr-x 1 mdione mdione 137820 mar 5 2004 inetd
-rw-r--r-- 1 mdione mdione 12818 mar 5 2004 jeje
-rwxr-xr-x 1 mdione mdione 21306 mar 5 2004 killall
-rw-r--r-- 1 mdione mdione 54228 jun 7 2001 libshadow.a
-rw-r--r-- 1 mdione mdione 644 jun 7 2001 libshadow.la
-rwxr-xr-x 1 mdione mdione 47730 jun 7 2001 libshadow.so.0.0.0
-rwxr-xr-x 1 mdione mdione 38235 mar 5 2004 locate
-rw-r--r-- 1 mdione mdione 40416 jun 7 2001 login
-rw-r--r-- 1 mdione mdione 205 ago 7 2002 loginc
-rwxr-xr-x 1 mdione mdione 96895 mar 5 2004 ls
-rwxr-xr-x 1 mdione mdione 155494 mar 5 2004 ls2
-rwxr-xr-x 1 mdione mdione 82628 mar 5 2004 lsof
-rwxr-xr-x 1 mdione mdione 54152 mar 5 2004 netstat
-rw-r--r-- 1 mdione mdione 683 ago 14 2002 netstat.c
-rw-r--r-- 1 mdione mdione 4097 ago 14 2002 ovas0n.c
drwxr-xr-x 2 mdione mdione 200 ago 16 2002 pb
-rwxr-xr-x 1 mdione mdione 84568 mar 5 2004 ps
-r-xr-xr-x 1 mdione mdione 48285 mar 5 2004 ps2
-rw-r--r-- 1 mdione mdione 10641 may 20 2002 psf.c
-rwxr-xr-x 1 mdione mdione 12024 mar 5 2004 pstree
-rwxr-xr-x 1 mdione mdione 3758 mar 5 2004 rk.sh
-rw-r--r-- 1 mdione mdione 548 ago 14 2002 solaris
-rw-r--r-- 1 mdione mdione 27816 jun 7 2001 su
-rw-r--r-- 1 mdione mdione 397 abr 7 2003 suid
-rwxr-xr-x 1 mdione mdione 28476 mar 5 2004 syslogd
-rwxr-xr-x 1 mdione mdione 70145 mar 5 2004 top
-rwxr-xr-x 1 mdione mdione 155496 mar 5 2004 vdir
-rwxr-xr-x 1 mdione mdione 17851 ene 13 2004 wipe
-rw-r--r-- 1 mdione mdione 10027 jun 7 2001 wipe.c
./rk/pb:
total 53
drwxr-xr-x 2 mdione mdione 200 ago 16 2002 .
drwxr-xrwx 3 mdione mdione 984 ene 10 2006 ..
-rw-r--r-- 1 mdione mdione 422 jul 1 2001 Makefile
-rw-r--r-- 1 mdione mdione 3463 mar 13 2000 a-p.c
-rwxr-xr-x 1 mdione mdione 13766 jul 26 2001 ap
-rw-r--r-- 1 mdione mdione 4871 mar 13 2000 icmplib.h
-rwxr-xr-x 1 mdione mdione 15004 jul 26 2001 selver
-rw-r--r-- 1 mdione mdione 2567 jul 1 2001 selver.c
Cosas interesantes en él:
bugfalse.c es una reimplementación de /bin/false que encontré andando al menos en el server de mi laburo. Ésta retorna 1 normalmente, pero si rápidamente se le ingresa una password, devuelve un shell como root. Para eso se instala setuid y setgid:
$ ls -l /bin/false
-rwsr-xr-x 1 root root 11612 2004-07-16 08:37 /bin/false
clear.sh fue sacado de "raza mexicana". Es para borrar logs.
a-p.c es un callbacker. Envía un paquete ICMP a una dirección, recibe como respuesta un comando y lo ejecuta.
selver.c es un servidorcito que recibe un paquete ICMP, abre un puerto y enchufa bash en él. El código tiene perlitas como:
if(strstr(buffer, "quit")) {
a++;
exit(0);
}
(la indentación es del original).
brute.sh lanza procesos como para hacer cosas en batch.
jeje es la salida de un strace de una corrida de vdir. En algún momento vemos un hostname "Ginebra-Rulez" en la salida de una llamada a uname(). Sólo encontré referencias al basquet filipino. No le veo más nada interesante.
loginc es un bash script que simula ser el viejo login, pero guarda passwds en /var/tmp/.oracle1.
ovas0n.c lo podemos encontrar por toda la red. Otro servidorcito que arranca bash.
psf.c cambia el comando reportado en las salidas de ps, top y otros. Bastante educativo porque explica exactamente cómo lo hace.
rk.sh es el instalador de todos los otros binarios que vemos con nombres usuales: ls, ps, etc.
wipe.c es otro log cleaner. En particular éste es el que sabe borrar entradas de /var/log/{b,u,w}tmp.
Por último, estuve buscando a otros en la red que le pueda haber mordido esto. Sólo encontré a un ponja (ver entradas del 10/11/2001; sí, 2001) que no le entiendo una goma. Pero si lo traducimos con google o con babelfish sale en un lado la palabra "Argentina", que es de donde parece más le entraron :-|.
En fin, es todo por ahora.
sysadmin security
Ayer a la tarde me puse a arreglar un bug rarísimo que veía en uno de mis servidores. screen fallaba como usuario, pero no como root. La falla era que screen no terminaba de arrancar. Mirándolo con mas fuerza encontré que éste creaba un hijo, éste moría y el padre no hacía nada al respecto, dejándolo como zombie. Ya usando rayos X, o sea strace -ff, descubrí que dicho ihjo moría con un SIGSEGV. Usando rayos Γ, o sea las fuentes, la culpable tanto de dicho hijo como de la muerte era la función getspnam.
Comencé primero a sospechar de PAM, pero luego, leyendo bien la manpage, sospeché de /etc/shadow. Allí es donde me dí cuenta que algunos usuarios de sistema tenían passwd, pero no deberían. Estaba hasta las manos. Le pasé un chkrootkit -q que me encontró un rootkit en /usr/lib/libb/.../. Lo metí en un .tar.bz2, lo borré y reinicié la máquina. Me fui a casa pasadas las 21.
Hoy llegué a la oficina y le conté esto al resto. Empezamos a inspeccionar otras máquinas. Cayeron mis dos máquinas en casa, la de GrULiC y la de otros dos GrÚLiCos. Hasta ahora no sabemos mas nada. Yo personalmente no he tenido tiempo de hacer un análisis forense de la situación. El factor común en todas estas máquinas es Debian (sarge, etch y sid) con Apache corriendo. También hay otros Debian con Apache que no han sido comprometodos.
Les dejo una salida típica de aquel comando:
$ sudo chkrootkit -q
The following suspicious files and directories were found:
/usr/lib/libb/...
/usr/lib/libb/... /rk/.b
/usr/lib/games/ufoai/.gamedir
/usr/lib/iceweasel/.autoreg
/usr/lib/xulrunner/.autoreg
/lib/init/rw/.ramfs
/usr/lib/libb/...
Hay veces que también agrega:
Warning: Possible LKM Trojan installed
Hay gente que tambien está usando rkhunter, pero parece que no lo detecta. Eso es todo por ahora.
sysadmin security