ports/81372: gpasm is vulnerable to a buffer overflow
Shaun Colley
scolleyuk at gmail.com
Sun May 22 21:10:02 UTC 2005
>Number: 81372
>Category: ports
>Synopsis: gpasm is vulnerable to a buffer overflow
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-ports-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sun May 22 21:10:02 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator: Shaun Colley
>Release: FreeBSD 5.3-RELEASE
>Organization:
>Environment:
bash-3.00# uname -a
FreeBSD my.host.name 5.3-RELEASE FreeBSD 5.3-RELEASE #6: Thu Mar 10 21:08:45 GMT 2005 my.host.name:/usr/src/sys/i386/compile/GENERIC i386
>Description:
gpasm, part of the devel/gputils port, is vulnerable to a stack overflow when parsing assembly code. gpasm will segmentation fault when given a long directive in a source file. If a user were tricked into assembling a source file, attacker-controlled code could be executed, giving rise to a security risk.
I *suspect* that the problem exists in gp_cod_strncpy, 'libgputils' strncpy wrapper. gp_cod_strncpy's code is as follows:
---
/* copy a string to a cod block using the pascal convention, i.e. the
string length occupies the first string location */
void
gp_cod_strncpy(char *dest, char *src, int max_len)
{
*(dest-1) = ( (max_len>strlen(src)) ? strlen(src) : max_len );
strncpy(dest, src, *(dest-1));
}
---
Although the routine's use of strncpy() may make it look secure, it may not be, because it uses the length of the source as the maximum length.
I can not be *absolutely* sure where the overflow is caused, but the above is my suspicion.
>How-To-Repeat:
Simply feed gpasm a malformed file with a long 'directive'. Here's my test file:
---
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
END
---
Upon being fed to gpasm, a seg fault should occur:
---
bash-3.00# ./gpasm a
Warning [226] Must use inhx8m format for EEPROM8
Segmentation fault (core dumped)
bash-3.00#
---
It seems evident that a stack overflow *is* actually occuring by observing execution in GDB.
---
bash-3.00# ./gpasm a
Warning [226] Must use inhx8m format for EEPROM8
Segmentation fault (core dumped)
bash-3.00# gdb -q -c gpasm.core
Core was generated by `gpasm'.
Program terminated with signal 11, Segmentation fault.
#0 0x2812bbb4 in ?? ()
(gdb) bt
#0 0x2812bbb4 in ?? ()
#1 0x0809c200 in ?? ()
#2 0xbfbfe788 in ?? ()
#33 0x00000001 in ?? ()
#34 0x00000004 in ?? ()
[...]
#37 0x61616161 in ?? ()
#38 0x61616161 in ?? ()
#39 0x61616161 in ?? ()
#40 0x61616161 in ?? ()
#41 0x61616161 in ?? ()
#42 0x61616161 in ?? ()
#43 0x61616161 in ?? ()
#44 0x61616161 in ?? ()
#45 0x61616161 in ?? ()
---Type <return> to continue, or q <return> to quit---Q
[...]
---
And here's another log:
---
bash-3.00# gdb -q ./gpasm
(no debugging symbols found)...(gdb) run a
Starting program: /usr/ports/devel/gputils/work/gputils-0.12.0/gpasm/gpasm a
(no debugging symbols found)...(no debugging symbols found)...Warning [226] Must use inhx8m format for EEPROM8
Program received signal SIGSEGV, Segmentation fault.
0x2812bbb4 in strncpy () from /lib/libc.so.5
(gdb)
[...]
(gdb) bt full
#0 0x2812bbb4 in strncpy () from /lib/libc.so.5
No symbol table info available.
#1 0x08057989 in gp_cod_strncpy ()
No symbol table info available.
#2 0x08050a52 in cod_write_symbols ()
No symbol table info available.
#3 0x0804da77 in lst_symbol_table ()
No symbol table info available.
#4 0x080499a4 in assemble ()
No symbol table info available.
#5 0x080490cc in main ()
No symbol table info available.
---
Though I could be wrong on the whole thing together, this seems like a stack overflow, triggered by a malformed source file, due to lack of proper bounds checking in gp_cod_strncpy().
I'm not sure how exploitable this would be, since there seem to be quite a few frames that need to be popped before the overwritten return address finally gets jumped to - and by the looks of it, gpasm seg faults before that, else the return address upon crash would probably be 0x61616161.
I haven't look at how exploitable it might be yet - any thoughts on that?
>Fix:
Further proof that a call to gp_cod_strncpy() is the culprit is the fact that this patch fixes it:
--- gpcod.orig.c Sun May 22 21:55:08 2005
+++ gpcod.c Sun May 22 21:55:30 2005
@@ -29,8 +29,8 @@
gp_cod_strncpy(char *dest, char *src, int max_len)
{
- *(dest-1) = ( (max_len>strlen(src)) ? strlen(src) : max_len );
- strncpy(dest, src, *(dest-1));
+ /**(dest-1) = ( (max_len>strlen(src)) ? strlen(src) : max_len )*/;
+ strncpy(dest, src, 80);
}
If the patch is applied to /usr/ports/devel/gputils/work/gputils-0.12.0/libgputils/gpcod.c, the overflow no longer exists:
---
bash-3.00# ./gpasm a
Warning [226] Must use inhx8m format for EEPROM8
bash-3.00#
---
I haven't given my opinion on which call to gp_cod_strncpy() is responsible, because fixing the actual wrapper function is probably a more reliable way.
The above patch is rough. I have no idea as to the actual requirements of string lengths - 80 might be too short, or too long.
I'm sorry if this was too brief, or too many copy-and-pastes were done. I did this in a hurry because I've got revision to be doing. :)
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-ports-bugs
mailing list